Использование предварительно обученных вложений слов - как создать вектор для неизвестного / OOV Token? - PullRequest
0 голосов
/ 15 ноября 2018

Я не хочу добавлять предварительно обученные вложения к модели.Но, как кажется, нет вне словаря (OOV) жетон соотв.не существует вектора для невидимых слов.

Так, что я могу сделать, чтобы обращаться с OOV-токенами , с которыми я сталкиваюсь?У меня есть некоторые идеи, но ни одна из них не кажется очень хорошей:

  • Я мог бы просто создать случайный вектор для этого токена, но в идеале я бы хотел, чтобы вектор находился внутри логика существующей модели.Если я просто создаю его случайно, я боюсь, что вектор случайно мог бы быть очень похож на очень часто встречающееся слово типа '', 'for', 'это' и т. Д., Которое не является моим намерением.

  • Или я должен вместо этого просто инициализировать вектор с простыми нулями?

  • Другая идея - усреднить токен по другим существующим векторам.Но усреднение по каким векторам тогда?На все?Это не кажется слишком убедительным.

  • Я также думал о попытке обучить этот вектор.Однако это не очень удобно, если я хочу заморозить оставшуюся часть встраивания во время тренировки.

(Общее решение приветствуется, но я хотел добавить, что я использую PyTorch - на тот случай, если PyTorch уже предлагает удобное решение этой проблемы.)

Так что же будет хорошей и легкой стратегией для создания такого вектора?

1 Ответ

0 голосов
/ 16 ноября 2018

Есть несколько способов, с которыми вы можете иметь дело. Я не думаю, что могу привести ссылку на то, что работает лучше.

Не обучаемый вариант :

  1. Случайный вектор как вложение
  2. Вы можете использовать все нулевые векторы для OOV.
  3. Вы можете иметь в виду весь вектор внедрения, чтобы избежать риска быть в стороне от фактического распределения.
  4. Также вложения обычно идут с «unk» векторами, изученными во время обучения, которым вы можете воспользоваться.

Вариант обучения :

Вы можете объявить отдельный вектор встраивания для OOV и сделать его обучаемым, сохраняя другие встраивания фиксированными. Возможно, вам придется переписать прямой метод встраивания поиска для этого. Вы можете объявить новый обучаемый Variable и в прямом проходе использовать этот вектор как вложение для OOV вместо поиска.


Обращаясь к комментариям ОП:

Я не уверен, какой из трех не обучаемых методов может работать лучше, и я не уверен, есть ли какая-то работа по этому поводу. Но метод 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()
...