как ускорить инициализацию gensim word2vec с предварительно обработанным корпусом? - PullRequest
0 голосов
/ 16 апреля 2019

Я тренирую несколько моделей word2vec в одном корпусе. (Я делаю это для изучения вариаций в изученных векторах слов)

Я использую этот учебник для справки: https://rare -technologies.com / word2vec-tutorial /

предполагается, что по умолчанию gensim.models.word2vec будет перебирать корпус как минимум дважды. один раз для инициализации, а затем снова для обучения (повторение указанного количества эпох)

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

как это можно сделать?

это мои текущие настройки:

subdirectory = 'corpus_directory'
for i in range(10):
    sentences = MySentences(subdirectory) # a memory-friendly iterator
    model = gensim.models.Word2Vec(sentences, min_count=20, size=100, workers=4)
    model.train(sentences, total_examples=model.corpus_count, epochs=1)
    word_vectors = model.wv
    fname = 'WV{}.kv'
    word_vectors.save(fname.format(i))

где MySentences определяется аналогично учебнику: (я внес небольшое изменение, поэтому порядок корпусных предложений будет перетасовываться при каждой инициализации)

class MySentences(object):
    def __init__(self, dirname):
        self.dirname = dirname
        self.file_list = [fname for fname in os.listdir(dirname) if fname.endswith('.txt')]
        random.shuffle(self.file_list)

    def __iter__(self):
        for article in self.file_list:
            for line in open(os.path.join(self.dirname, article)):
                yield line.split()

1 Ответ

1 голос
/ 17 апреля 2019

Если вы предоставляете корпус sentences для экземпляра класса, как это сделал ваш код, вам не нужно вызывать train().Это уже будет сделано автоматически, и ваш второй train() будет лишним.(Я рекомендую выполнять все такие операции с включенным ведением журналов на уровне INFO и просматривать lgos после каждого запуска, чтобы понять, что происходит - такие вещи, как два полных тренинга от начала до конца, должны выделяться в журналах.)

Случай, когда вы бы явно вызвали train(), - это если вы хотите больше контролировать промежуточные этапы.Вы оставляете sentences вне класса-экземпляра, но тогда вам необходимо выполнить два явных шага: оба - один вызов build_vocab() (для начального сканирования словаря) и затем один вызов train() (для фактическогомногоэпоховое обучение).

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

Таким образом, вы можете многократно перезагружать эту модель словаря для разных переменных, чтобы тренироваться по-разному.Для некоторых мета-параметров модели - например, window или даже dm mode - вы можете даже напрямую изменять их значения в модели после построения словарного запаса, чтобы попробовать разные варианты.

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

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

...