Как вручную изменить векторные размеры слова в Gensim Word2Vec

У меня есть модель Word2Vec с большим количеством векторов слов. Я могу получить доступ к слову вектор как так.

word_vectors = gensim.models.Word2Vec.load(wordspace_path)
print(word_vectors['boy'])

Выход

[ -5.48055351e-01   1.08748421e-01  -3.50534245e-02  -9.02988110e-03...]

Теперь у меня есть правильное векторное представление, которым я хочу заменить word_vectors['boy'].

word_vectors['boy'] = [ -7.48055351e-01   3.08748421e-01  -2.50534245e-02  -10.02988110e-03...]

Но выдается следующая ошибка

TypeError: 'Word2Vec' object does not support item assignment

Есть ли способ или обходной путь для этого? То есть вручную управлять векторами слов после обучения модели? Возможно ли это на других платформах, кроме Gensim?

1 ответ

Решение

Так как векторы word2vec, как правило, создаются только итеративным процессом обучения, затем осуществляется доступ, gensim Word2Vec Объект не поддерживает прямое присвоение новых значений по своим индексам слов.

Однако, как и в Python, все его внутренние структуры полностью доступны для просмотра / взлома вами, и, поскольку он является открытым исходным кодом, вы можете точно увидеть, как он выполняет все свои существующие функции, и использовать его в качестве модели того, как делать новые вещи.

В частности, необработанные слова-векторы (в последних версиях gensim) хранятся в свойстве Word2Vec объект называется wv, и это wv свойство является экземпляром KeyedVectors, Если вы изучите его исходный код, вы можете увидеть доступ к словам-векторам по строковому ключу (например, 'boy'), в том числе [] Индексирование осуществляется __getitem__() метод, пройти его метод word_vec(), Вы можете просмотреть источник этого метода либо в вашей локальной установке, либо на Github:

https://github.com/RaRe-Technologies/gensim/blob/c2201664d5ae03af8d90fb5ff514ffa48a6f305a/gensim/models/keyedvectors.py

Там вы увидите, что слово фактически преобразуется в целочисленный индекс (через self.vocab[word].index) затем используется для доступа к внутреннему syn0 или же syn0norm массив (в зависимости от того, обращается ли пользователь к необработанному или единичному нормализованному вектору). Если вы посмотрите в другом месте, где они установлены, или просто изучите их в своей консоли / коде (как если бы word_vectors.wv.syn0), вы увидите это numpy массивы, которые поддерживают прямое назначение по индексу.

Таким образом, вы можете напрямую изменять их значения целочисленным индексом, как если бы:

word_vectors.wv.syn0[word_vectors.wv.vocab['boy'].index] = [ -7.48055351e-01   3.08748421e-01  -2.50534245e-02  -10.02988110e-03...]

А потом, будущие доступы word_vectors.wv['boy'] вернет ваши обновленные значения.

Заметки:

• Если ты хочешь syn0norm быть обновленным, иметь правильные единичные векторы (которые используются в most_similar() и другие операции), вероятно, было бы лучше изменить syn0 сначала, затем отбросить и пересчитать syn0norm, с помощью:

word_vectors.wv.syn0norm = None
word_vectors.wv.init_sims()

• Добавление новых слов потребует более сложного вмешательства в объект, потому что это потребует увеличения syn0 (заменив его большим массивом) и обновив vocab ДИКТ

Другие вопросы по тегам