PyTorch:将词向量加载到字段词汇表与嵌入层

PyTorch: Loading word vectors into Field vocabulary vs. Embedding layer

我正从 Keras 转到 PyTorch。 我想创建一个 PyTorch 嵌入层(大小为 V x D 的矩阵,其中 V 是词汇索引,D 是嵌入矢量维度)与 GloVe 向量,但对所需的步骤感到困惑。

在 Keras 中,you can load the GloVe vectors 通过让嵌入层构造函数采用 weights 参数:

# Keras code.
embedding_layer = Embedding(..., weights=[embedding_matrix])

在查看 PyTorch 和 TorchText 库时,我看到嵌入应该加载 两次 ,一次在 Field 中,然后在 [=17] 中再次加载=]层。这是我发现的sample code

# PyTorch code.

# Create a field for text and build a vocabulary with 'glove.6B.100d'
# pretrained embeddings.
TEXT = data.Field(tokenize = 'spacy', include_lengths = True)

TEXT.build_vocab(train_data, vectors='glove.6B.100d')


# Build an RNN model with an Embedding layer.
class RNN(nn.Module):
    def __init__(self, ...):

        super().__init__()
        self.embedding = nn.Embedding(vocab_size, embedding_dim)

        ...

# Initialize the embedding layer with the Glove embeddings from the
# vocabulary. Why are two steps needed???
model = RNN(...)
pretrained_embeddings = TEXT.vocab.vectors
model.embedding.weight.data.copy_(pretrained_embeddings)

具体来说:

  1. 除了 Embedding 之外,为什么还要在 Field 中加载 GloVe 嵌入?
  2. 我认为 Field 函数 build_vocab() 只是从训练数据中构建词汇表。在此步骤中,GloVe 嵌入如何参与?

以下是 没有 回答我的问题的其他 Whosebug 问题:

Embedding in pytorch

感谢您的帮助。

torchtext 构建词汇表时,它会将标记索引与嵌入对齐。如果您的词汇表与预训练嵌入的大小和顺序不同,则无法保证索引匹配,因此您可能会查找不正确的嵌入。 build_vocab() 使用相应的嵌入为您的数据集创建词汇表并丢弃其余的嵌入,因为它们未被使用。

GloVe-6B 嵌入包含一个大小为 400K 的词汇表。例如 IMDB dataset 只使用其中的大约 120K,其他 280K 未使用。

import torch
from torchtext import data, datasets, vocab

TEXT = data.Field(tokenize='spacy', include_lengths=True)
LABEL = data.LabelField()

train_data, test_data = datasets.IMDB.splits(TEXT, LABEL)
TEXT.build_vocab(train_data, vectors='glove.6B.100d')

TEXT.vocab.vectors.size() # => torch.Size([121417, 100])

# For comparison the full GloVe
glove = vocab.GloVe(name="6B", dim=100)
glove.vectors.size() # => torch.Size([400000, 100])

# Embedding of the first token is not the same
torch.equal(TEXT.vocab.vectors[0], glove.vectors[0]) # => False

# Index of the word "the"
TEXT.vocab.stoi["the"] # => 2
glove.stoi["the"] # => 0

# Same embedding when using the respective index of the same word
torch.equal(TEXT.vocab.vectors[2], glove.vectors[0]) # => True

使用嵌入构建词汇表后,输入序列将以标记化版本给出,其中每个标记均由其索引表示。在模型中你想使用这些的嵌入,所以你需要创建嵌入层,但要使用你的词汇表的嵌入。最简单也是推荐的方式是nn.Embedding.from_pretrained,本质上和Keras版本是一样的

embedding_layer = nn.Embedding.from_pretrained(TEXT.vocab.vectors)

# Or if you want to make it trainable
trainable_embedding_layer = nn.Embedding.from_pretrained(TEXT.vocab.vectors, freeze=False)

您没有提到 embedding_matrix 是如何在 Keras 版本中创建的,也没有提到词汇表是如何构建的以便它可以与 embedding_matrix 一起使用。如果您手动(或使用任何其他实用程序)执行此操作,则根本不需要 torchtext,并且您可以像在 Keras 中一样初始化嵌入。 torchtext纯粹是为了方便常见的数据相关任务。