pytorch 的嵌入层内发生了什么"exactly"?

What "exactly" happens inside embedding layer in pytorch?

通过多次搜索和 pytorch 文档本身,我可以发现在嵌入层内部有一个查找 table,其中存储了嵌入向量。我无法理解的内容:

  1. 这一层的训练到底发生了什么?
  2. 什么是权重以及这些权重的梯度是如何计算的?
  3. 我的直觉是至少应该有一个带有一些参数的函数来生成查找键 table。如果是,那么那个函数是什么?

我们将不胜感激。谢谢

真是个好问题! PyTorch 的嵌入层(Tensorflow 也是如此)用作查找 table 只是为了检索每个输入的嵌入,即索引。考虑以下情况,您有一个句子,其中每个单词都被标记化了。因此,你句子中的每个单词都用一个唯一的整数(索引)表示。如果索引(单词)列表是 [1, 5, 9],并且您想使用 50 维向量(嵌入)对每个单词进行编码,您可以执行以下操作:

# The list of tokens
tokens = torch.tensor([0,5,9], dtype=torch.long)
# Define an embedding layer, where you know upfront that in total you
# have 10 distinct words, and you want each word to be encoded with
# a 50 dimensional vector
embedding = torch.nn.Embedding(num_embeddings=10, embedding_dim=50)
# Obtain the embeddings for each of the words in the sentence
embedded_words = embedding(tokens)

现在,回答您的问题:

  1. 在前向传播过程中,句子中每个标记的值将以与 Numpy 的索引工作类似的方式获得。因为在后端,这是一个可微分的操作,在向后传递(训练)期间,Pytorch 将计算每个嵌入的梯度并相应地重新调整它们。

  2. 权重是嵌入本身。 word embedding矩阵其实就是一个权重矩阵,训练的时候会学习到

  3. 本身没有实际功能。正如我们上面定义的,句子已经被标记化(每个单词都用一个唯一的整数表示),我们可以只获得句子中每个标记的嵌入。

最后,我多次提到索引的例子,让我们试试看。

# Let us assume that we have a pre-trained embedding matrix
pretrained_embeddings = torch.rand(10, 50)
# We can initialize our embedding module from the embedding matrix
embedding = torch.nn.Embedding.from_pretrained(pretrained_embeddings)
# Some tokens
tokens = torch.tensor([1,5,9], dtype=torch.long)

# Token embeddings from the lookup table
lookup_embeddings = embedding(tokens)
# Token embeddings obtained with indexing
indexing_embeddings = pretrained_embeddings[tokens]
# Voila! They are the same
np.testing.assert_array_equal(lookup_embeddings.numpy(), indexing_embeddings.numpy())

nn.Embedding 图层可以用作查找 table。这意味着如果你有一个 n 元素的字典,你可以在创建嵌入时通过 id 调用每个元素。

在这种情况下,字典的大小为 num_embeddingsembedding_dim 为 1。

在这种情况下,您没有任何要学习的东西。你可能会说,你只是索引了字典的元素,或者你对它们进行了编码。所以在这种情况下不需要前向传递分析。

如果你使用过像 Word2vec 这样的词嵌入,你可能已经用过这个。

另一方面,您可以将嵌入层用于分类变量(一般情况下的特征)。在那里,您将嵌入维度 embedding_dim 设置为您可能拥有的类别数。

在那种情况下,您从随机初始化的嵌入层开始,然后向前学习类别(特征)。