Есть ли способ сохранить и загрузить словарь модели Gensim Doc2Vec

редактировать

Корпус поезда - это фреймворк данных Spark, который я построил перед этим шагом. Я загрузил его из формата паркета и создал класс «Feed», который передал Gensim lib итератор в корпусе поезда:

class Feed():
    def __init__(self, train_data):
        self.train_data = train_data

    def __iter__(self):
        for row in self.train_data.rdd.toLocalIterator():
            yield \
                gensim.models.doc2vec.TaggedDocument(\
                words=[kw.lower() for kw in row["keywords"]] + list(row["tokens_filtered"]),\
                tags=[row["id"]])


sdf = spark.read.parquet(save_dirname)
train_corpus = Feed(sdf)

конец править

Я хочу обучить модель Gensim Doc2Vec на ~ 9 миллионах текстовых новостных документов. Вот определение моей модели:

model = gensim.models.doc2vec.Doc2Vec(
        workers=8,
        vector_size=300,
        min_count=50,
        epochs=10)

Первый шаг - пополнение словарного запаса:

model.build_vocab(train_corpus)

Это заканчивается через 90 минут. Вот информация о регистрации в конце этого процесса:

INFO:gensim.models.doc2vec:collected 4202859 word types and 8950263 unique tags from a corpus of 8950339 examples and 1565845381 words
INFO:gensim.models.word2vec:Loading a fresh vocabulary
INFO:gensim.models.word2vec:min_count=50 retains 325027 unique words (7% of original 4202859, drops 3877832)
INFO:gensim.models.word2vec:min_count=50 leaves 1546772183 word corpus (98% of original 1565845381, drops 19073198)
INFO:gensim.models.word2vec:deleting the raw counts dictionary of 4202859 items
INFO:gensim.models.word2vec:sample=0.001 downsamples 9 most-common words
INFO:gensim.models.word2vec:downsampling leaves estimated 1536820314 word corpus (99.4% of prior 1546772183)
INFO:gensim.models.base_any2vec:estimated required memory for 325027 words and 300 dimensions: 13472946500 bytes

Затем я обучаю модель с помощью класса итератора в корпусе поезда:

model.train(train_corpus, total_examples=nb_rows, epochs=model.epochs)

Последние журналы тренировок:

INFO:gensim.models.base_any2vec:EPOCH 1 - PROGRESS: at 99.99% examples, 201921 words/s, in_qsize 16, out_qsize 0
INFO:gensim.models.base_any2vec:worker thread finished; awaiting finish of 7 more threads
INFO:gensim.models.base_any2vec:worker thread finished; awaiting finish of 6 more threads
INFO:gensim.models.base_any2vec:worker thread finished; awaiting finish of 5 more threads
INFO:gensim.models.base_any2vec:worker thread finished; awaiting finish of 4 more threads

Но он никогда не заканчивает оставшиеся потоки. Я не впервые сталкиваюсь с этой проблемой, даже при гораздо меньшем составе поездов. Обычно я перезапускаю весь процесс (настройка словарного запаса и обучение модели), и он продолжается.

К настоящему времени, чтобы сэкономить время, я хочу НЕ рассчитывать снова словарь, используя ранее успешно рассчитанный, и просто пытаться снова обучить модель. Есть ли способ сохранить только словарную часть модели, а затем загрузить ее для обучения модели непосредственно в корпусе поезда?


person JC Garnier    schedule 22.05.2019    source источник


Ответы (1)


Что касается причины зависания, похоже, что вы в целом делаете правильные вещи, но что-то может пойти не так с вашим train_corpus, конструкцию которого вы не показали.

Дважды проверьте его реализацию и, возможно, отредактируйте свой вопрос, чтобы показать более подробную информацию о его типе / инициализации. Просмотрите журналы, чтобы увидеть, есть ли доказательства каких-либо ошибок попадания потоков, которые оставили их в состоянии, при котором они не отчитываются должным образом.

Вы можете .save() различные части Doc2Vec модели, такие как model.wv.save(wv_path), но нет простого способа восстановить модель из этих частей. (Это возможно, но требует внимательного отношения к требуемому состоянию объекта, просмотра источника и подвержено ошибкам.)

Но также, что более важно, вы можете .save() полную Doc2Vec модель в любое время - и это, вероятно, лучший подход для ваших нужд. То есть вы можете .save() это после build_vocab(), или после вызова .train() и т. Д.

Если на самом деле ваше текущее зависание находится в какой-то записной книжке, где вы можете прервать зависшее действие и выполнить новый код в новой ячейке, вы, вероятно, можете просто сохранить модель оттуда, отладить свой train_corpus, затем повторно загрузить и повторно обучить - при условии, что размер корпуса / словарный запас соответствует тому, что было изучено в build_vocab().

Однако на такой частично обученный .save() в конце концов повлияет почти полное обучение, которое уже произошло. Таким образом, конечные результаты будут не только истинным отражением ваших параметров конфигурации, но и кучей избыточного специального обучения.

Если вы хотите «очистить» остаточные эффекты этого частичного обучения после повторной загрузки сохраненной Doc2Vec модели, я считаю, что это должно сделать следующее:

model.trainables.reset_weights(model.hs, model.negative, model.wv, model.docvecs)
person gojomo    schedule 22.05.2019
comment
Привет, годжомо, спасибо. Я попытаюсь сохранить модель после построения словаря и сбросить веса модели перед обучением, если она снова не удастся. Я отредактировал вопрос, включив в него строительство корпуса поезда. Как получить больше логов от gensim, чтобы объяснить зависание? - person JC Garnier; 23.05.2019
comment
... и я не понимаю, что могло быть не так в корпусе поезда, чтобы произвести такое зависание потока. У вас есть какие-нибудь примеры? - person JC Garnier; 23.05.2019
comment
Я бы ожидал, что просмотр консолей со стандартным выходом / стандартными ошибками, а также ведение журнала INFO, которое вы уже используете, покажут любые основные блоки - вам просто нужно будет просмотреть все журналы для всего запуска. (Вы также можете попробовать установить уровень журнала gensim на DEBUG, но не уверены, что это поймает что-нибудь еще релевантное.) Я вижу, что вы используете spark, что означает, что данные могут быть собраны из многих источников по сети - и могут быть представлены другие возможные режимы отказа. Так что наблюдение за журналами / уровнями журналов Spark может помочь. Можете ли вы проверить вне gensim, что train_corpus будет предлагать nb_rows примеры на повторяющихся итерациях? - person gojomo; 23.05.2019
comment
Поскольку функция toLocalIterator () загружает каждый раздел Spark в драйвере, я увеличил выделенную память драйвера Spark (и уменьшил рабочие), и, наконец, это сработало. Однако я не уверен, что это была основная причина зависания потоков: та же проблема возникла с очень небольшим набором данных (без Spark) и работала нормально, если я просто перезапустил весь процесс обучения (включая словарь). Было бы хорошо, если бы в функции поезда был параметр, который сохранял бы промежуточную модель между каждой эпохой и позволял бы снова начать обучение в этой точке в случае сбоя. - person JC Garnier; 26.05.2019
comment
В любом случае, я отмечаю ответ на вопрос, поскольку ваше предложение может быть решением. Спасибо еще раз. - person JC Garnier; 26.05.2019