嵌入pytorch

use*_*468 17 word-embedding pytorch

我查看了pytorch的教程和simialr问题.实际上我很困惑,在pytorch(嵌入)中嵌入是否使相似的单词彼此接近?我只需要把所有的句子都给它?或者它只是一个查找表,我需要编码模型?

Ave*_*Liu 22

您可以将其nn.Embedding视为查找表,其中键是单词索引,值是相应的单词向量.但是,在使用它之前,您应该指定查找表的大小,并自己初始化单词向量.以下是一个证明这一点的代码示例.

import torch.nn as nn 

# vocab_size is the number of words in your train, val and test set
# vector_size is the dimension of the word vectors you are using
embed = nn.Embedding(vocab_size, vector_size)

# intialize the word vectors, pretrained_weights is a 
# numpy array of size (vocab_size, vector_size) and 
# pretrained_weights[i] retrieves the word vector of
# i-th word in the vocabulary
embed.weight.data.copy_(torch.fromnumpy(pretrained_weights))

# Then turn the word index into actual word vector
vocab = {"some": 0, "words": 1}
word_indexes = [vocab[w] for w in ["some", "words"]] 
word_vectors = embed(word_indexes)
Run Code Online (Sandbox Code Playgroud)

  • 所以我仍然没有得到在整个训练过程中学习这些随机初始化嵌入的方法。这是一个简单的 CBOW 或 Skip-gram 程序还是其他什么? (4认同)
  • 关键是 nn.Embedding 并不关心你用来训练词嵌入的任何方法,它只是一个存储训练好的嵌入的“矩阵”。在使用 nn.Embedding 加载外部词嵌入(例如 Glove 或 FastText)时,这些外部词嵌入的职责是确定训练方法。 (3认同)
  • 是的,`nn.Embedding`也是一个模型参数层,默认情况下是可训练的,你也可以通过冻结其梯度使其不可训练。 (3认同)
  • 我明白你的意思。但是,当未指定权重矩阵(随机初始化)时,如何在训练过程中对其进行微调?这些权重可能是自编码器的瓶颈权重?在微调过程中,后台是否发生了简单的重建? (2认同)
  • 如果选择在训练期间微调单词向量,则这些单词向量将被视为模型参数,并通过反向传播进行更新。 (2认同)
  • nn.Embedding是可训练层吗? (2认同)
  • @Zarkopafilis 感谢您指出 n-gram 词嵌入的问题。另外,对于通过 Google 来到这里的人来说,看看预训练的语言模型(例如 BERT、XLNet 等)会很好。它们通常会比使用老式嵌入得到更好的结果。 (2认同)

Esc*_*tor 20

nn.Embedding拥有一个维度张量(vocab_size, vector_size),即词汇量x每个向量嵌入维度的张量,以及一个执行查找的方法。

创建嵌入层时,张量会随机初始化。只有当您训练它时,相似词之间的这种相似性才会出现。除非您使用以前训练有素的模型(例如GloVe或Word2Vec)覆盖了嵌入的值,但这是另外一回事了。

因此,一旦定义了嵌入层,并对词汇表进行了定义和编码(即,为词汇表中的每个单词分配了唯一的编号),就可以使用nn.Embedding类的实例来获取相应的嵌入。

例如:

import torch
from torch import nn
embedding = nn.Embedding(1000,128)
embedding(torch.LongTensor([3,4]))
Run Code Online (Sandbox Code Playgroud)

将返回与词汇表中单词3和4对应的嵌入向量。由于尚未训练任何模型,因此它们将是随机的。

  • @Escachator我明白了你解释的原理。我主要想知道在训练模型中学习的嵌入如何应用于测试数据。例如,我有大约 20,000 个单词,我已将它们转换为数字并进行了嵌入。现在,在测试集中,如果我有一个序列 [3,2,5,4],模型权重是否已经包含进行分解和执行嵌入的方法?我只是不确定背景中的数学。 (3认同)
  • 例如,如果我有一个神经机器翻译模型,而我不使用预训练的嵌入,则嵌入层将随机初始化单词向量,并将这些向量与翻译模型一起训练? (2认同)
  • 确实,它们最初将是随机的,并且将是模型的可训练参数。 (2认同)
  • @KanishkMair 测试集中的嵌入是固定的。没有因式分解或任何要做的事情。`embedding(torch.LongTensor([3,2,5,4]))` 只会返回单词(或标记)3 和单词 2 等在张量为 `[dim_embedding, 4]` 中的嵌入 (2认同)

Gar*_*ain 10

torch.nn.Embedding 只需创建一个查找表,以获取给定单词索引的单词嵌入。

from collections import Counter
import torch.nn as nn

# Let's say you have 2 sentences(lowercased, punctuations removed) :
sentences = "i am new to PyTorch i am having fun"

words = sentences.split(' ')
    
vocab = Counter(words) # create a dictionary
vocab = sorted(vocab, key=vocab.get, reverse=True)
vocab_size = len(vocab)

# map words to unique indices
word2idx = {word: ind for ind, word in enumerate(vocab)} 

# word2idx = {'i': 0, 'am': 1, 'new': 2, 'to': 3, 'pytorch': 4, 'having': 5, 'fun': 6}

encoded_sentences = [word2idx[word] for word in words]

# encoded_sentences = [0, 1, 2, 3, 4, 0, 1, 5, 6]

# let's say you want embedding dimension to be 3
emb_dim = 3 
Run Code Online (Sandbox Code Playgroud)

现在,嵌入层可以初始化为:

emb_layer = nn.Embedding(vocab_size, emb_dim)
word_vectors = emb_layer(torch.LongTensor(encoded_sentences))
Run Code Online (Sandbox Code Playgroud)

这从标准正态分布(即 0 均值和单位方差)初始化嵌入。因此,这些词向量没有任何“相关性”的意义。

word_vectors 是大小为 (9,3) 的火炬张量。(因为我们的数据中有 9 个单词)

emb_layer 有一个称为weight 的可训练参数,默认情况下设置为训练。您可以通过以下方式检查:

emb_layer.weight.requires_grad
Run Code Online (Sandbox Code Playgroud)

返回True。如果您不想在模型训练期间训练您的嵌入(例如,当您使用预训练的嵌入时),您可以通过以下方式将它们设置为 False:

emb_layer.weight.requires_grad = False
Run Code Online (Sandbox Code Playgroud)

如果您的词汇量大小为 10,000,并且您希望使用预训练的嵌入来初始化嵌入,例如 Word2Vec,请执行以下操作:

emb_layer.load_state_dict({'weight': torch.from_numpy(emb_mat)})
Run Code Online (Sandbox Code Playgroud)

在这里,emb_mat 是一个大小为 (10,000, 300) 的 Numpy 矩阵,其中包含词汇表中 10,000 个单词中每个单词的 300 维 Word2vec 词向量。

现在,嵌入层加载了 Word2Vec 词表示。


pro*_*sti 8

啊啊!我认为这部分仍然缺失。展示当您设置嵌入层时,您会自动获得权重,您可以稍后更改 nn.Embedding.from_pretrained(weight)

import torch
import torch.nn as nn

embedding = nn.Embedding(10, 4)
print(type(embedding))
print(embedding)

t1 = embedding(torch.LongTensor([0,1,2,3,4,5,6,7,8,9])) # adding, 10 won't work
print(t1.shape)
print(t1)


t2 = embedding(torch.LongTensor([1,2,3]))
print(t2.shape)
print(t2)

#predefined weights
weight = torch.FloatTensor([[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]])
print(weight.shape)
embedding = nn.Embedding.from_pretrained(weight)
# get embeddings for ind 0 and 1
embedding(torch.LongTensor([0, 1]))
Run Code Online (Sandbox Code Playgroud)

输出:

<class 'torch.nn.modules.sparse.Embedding'>
Embedding(10, 4)
torch.Size([10, 4])
tensor([[-0.7007,  0.0169, -0.9943, -0.6584],
        [-0.7390, -0.6449,  0.1481, -1.4454],
        [-0.1407, -0.1081,  0.6704, -0.9218],
        [-0.2738, -0.2832,  0.7743,  0.5836],
        [ 0.4950, -1.4879,  0.4768,  0.4148],
        [ 0.0826, -0.7024,  1.2711,  0.7964],
        [-2.0595,  2.1670, -0.1599,  2.1746],
        [-2.5193,  0.6946, -0.0624, -0.1500],
        [ 0.5307, -0.7593, -1.7844,  0.1132],
        [-0.0371, -0.5854, -1.0221,  2.3451]], grad_fn=<EmbeddingBackward>)
torch.Size([3, 4])
tensor([[-0.7390, -0.6449,  0.1481, -1.4454],
        [-0.1407, -0.1081,  0.6704, -0.9218],
        [-0.2738, -0.2832,  0.7743,  0.5836]], grad_fn=<EmbeddingBackward>)
torch.Size([2, 3])

tensor([[0.1000, 0.2000, 0.3000],
        [0.4000, 0.5000, 0.6000]])
Run Code Online (Sandbox Code Playgroud)

最后一部分是嵌入层权重可以通过梯度下降来学习。