Удаление рандомизации векторной инициализации для doc2vec
Я использую предварительно обученную модель doc2vec BOW (AP-news). Я делаю следующее:
import gensim.models as g
start_alpha=0.01
infer_epoch=1000
model="\\apnews_dbow\\doc2vec.bin"
m = g.Doc2Vec.load(model)
text='this is a sample text'
vec=m.infer_vector(text,alpha=start_alpha, steps=infer_epoch)
Но если я снова вычислю vec для того же текста, то получу другое векторное представление того же текста. Почему это происходит и как я могу избежать этого. Я хочу вернуть тот же вектор, если я дам точно такой же текст. Я пытался после этого поста, но, похоже, не помогает.
3 ответа
Как описано в Gensim проекта Github проблема для детерминистского вывода, должно быть достаточноseed()
конкретный генератор случайных чисел, используемый внутри модели каждый раз перед попыткой логического вывода. (Предложение комментариев @Coldspeed - правильная общая идея, но модель Doc2Vec использует свою собственную random
экземпляр, а не numpy
глобальный.)
То есть везде у вас есть линия, как ваша...
vec=m.infer_vector(text,alpha=start_alpha, steps=infer_epoch)
... вам нужно будет предшествовать этому infer_vector()
с вынужденным повторнымseed()
случайного генератора модели:
m.random.seed(0)
Только тогда будет следующее infer_vector()
использовать эквивалентную последовательность случайных чисел. (И если одна и та же модель используется несколькими потоками, все ставки отключены, потому что PRNG может продвигаться другими потоками между заполнением и использованием.)
Хотя это должно сработать, не стоит полагаться на это. Алгоритм, лежащий в основе большинства режимов Doc2Vec (и Word2Vec), включает в себя собственную случайность, и каждый вектор является просто результатом процесса прогрессивной аппроксимации, который основывается на "достаточно хорошем" векторе, с учетом не только этой внутренней случайности, но и всех других параметров. Оценки должны быть устойчивыми к небольшому джиттеру в результатах, чтобы учесть внутреннюю дисперсию модели.
Вы должны сбрасывать семя каждый раз перед вызовом m.infer_vector(), как уже указывал @gojomo.
Если вы не хотите жестко кодировать семя, вы можете сделать это:
m.random.seed(m.seed)
vec=m.infer_vector(text,alpha=start_alpha, steps=infer_epoch)
Если вы хотите удалить рандомизацию инициализации вектора для doc2vec, используйте следует установить
workers=1
в Doc2Vec и исправьте PYTHONHASHSEED с помощью следующего кода.
import os
import sys
hashseed = os.getenv('PYTHONHASHSEED')
if not hashseed:
os.environ['PYTHONHASHSEED'] = '0'
os.execv(sys.executable, [sys.executable] + sys.argv)