使用预先训练的词嵌入-如何为未知/ OOV令牌创建向量?

时间:2018-11-15 09:26:30

标签: neural-network deep-learning nlp pytorch word-embedding

我不会在模型中添加pre-trained embeddings。但是,似乎没有语音提示(OOV)。不存在看不见单词的向量。

那我该如何处理遇到的 OOV令牌?我有一些想法,但似乎都不是很好:

  • 我可以为此令牌创建一个随机向量,但理想情况下,我希望该向量位于现有模型的 logic 中。如果我只是随机创建它,恐怕矢量会偶然地与非常常见的词(例如'the','for','that'等)非常相似,这不是我的意图。 / p>

  • 还是我应该使用纯零来初始化矢量?

  • 另一个想法是在其他现有向量上平均令牌。但是,然后平均什么向量呢?所有?这似乎也不是很确定。

  • 我还考虑过尝试训练此向量。但是,如果我想在训练过程中冻结其余的嵌入内容,这并不是很方便。

(赞赏了一般的解决方案,但我想补充一点,我正在使用PyTorch,以防万一PyTorch已经为该问题提供了便捷的解决方案。)

那么创建这样的向量的一种好又简单策略是什么?

1 个答案:

答案 0 :(得分:1)

您可以采用多种方式处理。我认为我不能引用哪种方法更好。

不可训练的选项

  1. 随机向量嵌入
  2. 您可以将全零矢量用于OOV。
  3. 您可以指所有的嵌入向量,这样可以避免远离实际分布的风险。
  4. 嵌入也通常带有在训练期间学习到的“ unk”向量,您可以使用它。

培训选项

您可以为OOV声明一个单独的嵌入向量,并使它可训练,同时保持其他嵌入不变。为此,您可能必须覆盖嵌入查找的正向方法。您可以声明一个新的可训练的Variable,并在前向传递中将此向量用作OOV的嵌入,而不是进行查找。


处理OP的评论:

我不确定这三种不可训练的方法中哪种方法效果更好,也不确定是否有一些解决方法。但是方法4)应该可以更好地工作。

对于可训练选项,您可以如下创建一个新的嵌入层。

class Embeddings_new(torch.nn.Module): 
    def __init__(self, dim, vocab): 
        super().__init__() 
        self.embedding = torch.nn.Embedding(vocab, dim) 
        self.embedding.weight.requires_grad = False
        # vector for oov 
        self.oov = torch.nn.Parameter(data=torch.rand(1,dim)) 
        self.oov_index = -1 
        self.dim = dim 

    def forward(self, arr): 
        N = arr.shape[0] 
        mask =  (arr==self.oov_index).long() 
        mask_ = mask.unsqueeze(dim=1).float() 
        embed =(1-mask_)*self.embedding((1-mask)*arr) + mask_*(self.oov.expand((N,self.dim))) 
        return embed 

用法:

model = Embeddings_new(10,20000)    
out = model.forward(torch.tensor([-1,-1, 100, 1, 0]))
# dummy loss
loss = torch.sum(a**2)
loss.backward()