我从Keras转到PyTorch。我希望创建一个PyTorch的Embedding层(一个大小为V x D
的矩阵,其中V
是词汇表词索引,D
是嵌入向量维度),并使用GloVe向量,但对所需步骤感到困惑。
在Keras中,你可以通过让Embedding层构造函数接受weights
参数来加载GloVe向量:
# Keras代码.embedding_layer = Embedding(..., weights=[embedding_matrix])
当查看PyTorch和TorchText库时,我发现嵌入应该被加载两次,一次在Field
中,然后再次在Embedding
层中。这是我找到的示例代码:
# PyTorch代码。# 为文本创建一个字段,并使用'glove.6B.100d'预训练嵌入构建词汇表TEXT = data.Field(tokenize = 'spacy', include_lengths = True)TEXT.build_vocab(train_data, vectors='glove.6B.100d')# 使用带有Embedding层的RNN模型构建类class RNN(nn.Module): def __init__(self, ...): super().__init__() self.embedding = nn.Embedding(vocab_size, embedding_dim) ...# 使用词汇表中的GloVe嵌入初始化嵌入层。为什么需要两个步骤?model = RNN(...)pretrained_embeddings = TEXT.vocab.vectorsmodel.embedding.weight.data.copy_(pretrained_embeddings)
具体来说:
- 为什么GloVe嵌入要加载到
Field
中以及Embedding
中? - 我以为
Field
函数build_vocab()
只是从训练数据中构建其词汇表。GloVe嵌入在此步骤中是如何参与的?
以下是其他StackOverflow问题,并没有回答我的问题:
PyTorch / Gensim – 如何加载预训练的词嵌入
PyTorch LSTM – 使用词嵌入而不是nn.Embedding()
感谢任何帮助。
回答:
当torchtext
构建词汇表时,它会将标记索引与嵌入对齐。如果你的词汇表大小和排序与预训练嵌入不一致,索引将无法保证匹配,因此你可能会查找错误的嵌入。build_vocab()
为你的数据集创建词汇表及其对应的嵌入,并丢弃其余未使用的嵌入。
GloVe-6B嵌入包括大小为400K的词汇表。例如,IMDB数据集仅使用了其中的约120K,其余280K未使用。
import torchfrom torchtext import data, datasets, vocabTEXT = 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])# 为了比较完整的GloVeglove = vocab.GloVe(name="6B", dim=100)glove.vectors.size() # => torch.Size([400000, 100])# 首个标记的嵌入不是相同的torch.equal(TEXT.vocab.vectors[0], glove.vectors[0]) # => False# 单词“the”的索引TEXT.vocab.stoi["the"] # => 2glove.stoi["the"] # => 0# 使用相同单词的各自索引时嵌入是相同的torch.equal(TEXT.vocab.vectors[2], glove.vectors[0]) # => True
构建词汇表及其嵌入后,输入序列将以标记化的版本提供,其中每个标记由其索引表示。在模型中,你希望使用这些嵌入,因此你需要创建嵌入层,但使用你的词汇表的嵌入。最简单且推荐的方法是nn.Embedding.from_pretrained
,这基本上与Keras版本相同。
embedding_layer = nn.Embedding.from_pretrained(TEXT.vocab.vectors)# 或者如果你希望使其可训练trainable_embedding_layer = nn.Embedding.from_pretrained(TEXT.vocab.vectors, freeze=False)
你没有提到在Keras版本中如何创建embedding_matrix
,也没有提到如何构建词汇表以便与embedding_matrix
一起使用。如果你手动完成(或使用任何其他工具),你根本不需要torchtext
,你可以像在Keras中一样初始化嵌入。torchtext
纯粹是为了常见数据相关任务的便利性。