代码之家  ›  专栏  ›  技术社区  ›  MBT Nina Golyandina

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

  •  0
  • MBT Nina Golyandina  · 技术社区  · 6 年前

    我不想补充 pre-trained embeddings 一个模特。但似乎没有 词汇表外(OOV) 代币。不存在看不见单词的向量。

    那我该怎么处理呢 我遇到了什么?我有一些想法,但似乎都不是很好:

    • 逻辑 对现有模型的修改。如果我只是随机创建它,我担心向量可能会意外地与一个非常频繁的单词非常相似,比如 “the”、“for”、“that” 等等,这不是我的本意。

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

    • 我还想尝试训练这个向量。然而,如果我想在训练期间冻结嵌入的其余部分,这就不是很方便了。

    (非常感谢一个通用的解决方案,但我想补充一点,我正在使用Pytork——以防万一Pytork已经为这个问题提供了一个方便的解决方案。)

    那么,什么是一个好的 容易的 创建这样一个向量的策略?

    1 回复  |  直到 6 年前
        1
  •  2
  •   Umang Gupta    6 年前

    你可以用多种方法处理。我不认为我能举出哪种方法更有效的参考文献。

    :

    1. 你可以指所有的嵌入向量,这样你就避免了脱离实际分布的风险。
    2. 此外,嵌入通常带有在培训期间学习的“unk”向量,您可以使用该向量。

    可培训选项 :

    您可以为OOV声明一个单独的嵌入向量,并使其在保持其他嵌入固定的情况下可训练。为此,您可能必须重写嵌入查找的正向方法。你可以申报一个新的可培训课程 Variable 在前向传递中,使用这个向量作为OOV的嵌入,而不是进行查找。


    针对OP的评论:

    我不确定这三种不可培训的方法中哪一种可能更有效,我也不确定是否有相关的工作。但方法4)应该更有效。

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

    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()