Обучение Word2vec с использованием gensim начинает замену после предложений 100K

Я пытаюсь обучить модель word2vec, используя файл с примерно 170 К строк, с одним предложением в строке.

Я думаю, что я могу представить специальный случай использования, потому что "предложения" имеют произвольные строки, а не слова слова. Каждое предложение (строка) содержит около 100 слов, и каждое "слово" содержит около 20 символов с символами типа "/", а также номерами.

Код тренировки очень прост:

# as shown in http://rare-technologies.com/word2vec-tutorial/
import gensim, logging, os

logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)

class MySentences(object):
    def __init__(self, dirname):
        self.dirname = dirname

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

current_dir = os.path.dirname(os.path.realpath(__file__))

# each line represents a full chess match
input_dir = current_dir+"/../fen_output"
output_file = current_dir+"/../learned_vectors/output.model.bin"

sentences = MySentences(input_dir)

model = gensim.models.Word2Vec(sentences,workers=8)

Дело в том, что все работает очень быстро до 100 тыс. предложений (моя оперативная память постоянно растет), но затем у меня заканчивается оперативная память, и я вижу, что мой компьютер начал заменять, и обучение прерывается. У меня нет большого количества оперативной памяти, только около 4 ГБ и word2vec использует все это, прежде чем начать замену.

Я думаю, что OpenBLAS правильно связан с numpy: вот что numpy.show_config() говорит мне:

blas_info:
  libraries = ['blas']
  library_dirs = ['/usr/lib']
  language = f77
lapack_info:
  libraries = ['lapack']
  library_dirs = ['/usr/lib']
  language = f77
atlas_threads_info:
  NOT AVAILABLE
blas_opt_info:
  libraries = ['openblas']
  library_dirs = ['/usr/lib']
  language = f77
openblas_info:
  libraries = ['openblas']
  library_dirs = ['/usr/lib']
  language = f77
lapack_opt_info:
  libraries = ['lapack', 'blas']
  library_dirs = ['/usr/lib']
  language = f77
  define_macros = [('NO_ATLAS_INFO', 1)]
openblas_lapack_info:
  NOT AVAILABLE
lapack_mkl_info:
  NOT AVAILABLE
atlas_3_10_threads_info:
  NOT AVAILABLE
atlas_info:
  NOT AVAILABLE
atlas_3_10_info:
  NOT AVAILABLE
blas_mkl_info:
  NOT AVAILABLE
mkl_info:
  NOT AVAILABLE

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

Спасибо заранее.

Ответ 1

Как первый принцип, вы всегда должны получать больше ОЗУ, если ваш бюджет и машина могут управлять им. Это экономит так много времени и проблем.

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

Использование памяти Word2Vec - это функция размера словаря (количество токенов), а не общий объем данных, используемых для обучения. Таким образом, вы можете использовать более крупный min_count, чтобы уменьшить количество отслеживаемых слов, чтобы ограничить использование ОЗУ во время обучения. (Слова, которые не отслеживаются моделью, будут тихо опущены во время тренировки, как будто их там не было - и делать это для редких слов не сильно больно, а иногда даже помогает, сближая другие слова друг с другом.)

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

В частности, в последних версиях gensim вы также можете разбить шаг build_vocab(corpus) на три шага scan_vocab(corpus), scale_vocab(...) и finalize_vocab().

Шаг scale_vocab(...) можно вызвать с помощью параметра dry_run=True, который предсказывает, насколько велика ваша лексика, подвыбранный корпус и ожидаемое использование памяти, после того, как вы попробуете разные значения параметров min_count и sample. Когда вы находите значения, которые кажутся управляемыми, вы можете вызвать scale_vocab(...) с этими выбранными параметрами и без dry_run, чтобы применить их к вашей модели (а затем finalize_vocab() для инициализации больших массивов).

Ответ 2

похоже, что моя настройка не настроена должным образом (или мой код неэффективная)?

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

2) Вы можете попробовать остановить или лучше: lemmatization. Вы сократите количество слов, поскольку, например, единственные и множественные формы будут считаться одним и тем же словом

3) Тем не менее, я думаю, что 4 ГБ ОЗУ, вероятно, ваша главная проблема здесь (помимо вашей ОС, вероятно, у вас есть только 1-2 ГБ, которые действительно могут использоваться процессами/потоками. Я бы действительно подумал об инвестировании в более оперативной памяти.Например, в настоящее время вы можете получить хорошие 16 ГБ комплекты ОЗУ за 100 долларов США, однако, если у вас есть деньги, чтобы инвестировать в достойную оперативную память для обычной задачи "Наука о данных", я бы рекомендовал > 64 ГБ