Поток текста в Генсиме - PullRequest
2 голосов
/ 28 марта 2019

Gensim использует потоковую передачу текста, чтобы минимизировать требования к памяти.Это за счет производительности из-за бесконечного дискового ввода-вывода.Есть ли хитрость, чтобы на лету скопировать весь файл с диска (один дисковый ввод-вывод) во временный файл в памяти?Мне нравится сохранять код как есть (без перекодировки в структуры списка), но это не отличный способ отладки функциональности

Ожидаемый результат: гораздо более быстрый код

Еще немного информации овопрос

Исходный код на https://github.com/skipgram/modern-nlp-in-python/blob/master/executable/Modern_NLP_in_Python.ipynb. Код примера взят из раздела моделирования фраз

Я вычисляю униграммы.Все отзывы на

review_txt_filepath = os.path.join(intermediate_directory,'review_text_all.txt'),

все символы должны идти на

unigram_sentences_filepath = os.path.join(intermediate_directory, 'unigram_sentences_all.txt') 

Важнейшие процедуры:

def punct_space(token):
    return token.is_punct or token.is_space

def line_review(filename):
    # generator function to read in reviews from the file
    with codecs.open(filename, encoding='utf_8') as f:
        for review in f:
            yield review.replace('\\n', '\n')

def lemmatized_sentence_corpus(filename):
    # generator function to use spaCy to parse reviews, lemmatize the text, and yield sentences

    for parsed_review in nlp.pipe(line_review(filename),
                              batch_size=10000, n_threads=4):
        for sent in parsed_review.sents:
            yield u' '.join([token.lemma_ for token in sent
                             if not punct_space(token)])

Символы рассчитаны как

with codecs.open(unigram_sentences_filepath, 'w', encoding='utf_8') as f:
    for sentence in lemmatized_sentence_corpus(review_txt_filepath):
        f.write(sentence + '\n')

Выполнение этого для 5000 строк требует некоторого терпения, 1 ч 30 м; -)

Я не настолько знаком с итерациями, но правильно ли я понимаю, что сначала мне нужно прочитать сам файл (на диске)) в переменную "list_of_data" и обработайте ее

with (review_txt_filepath, 'r', encoding='utf_8') as f:
    list_of_data = f.read()

with codecs.open(unigram_sentences_filepath, 'w', encoding='utf_8') as f:
    for sentence in lemmatized_sentence_corpus(list_of_data):
        f.write(sentence + '\n')

Итак, стратегия такова:

1. read all data into a list in memory
2. process the data
3. write the results to disc
4. delete the list from memory by setting list_with_data = ()

Проблема с этим, очевидно, в том, что line_review выполняет чтение файла

1 Ответ

1 голос
/ 28 марта 2019

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

По сути, если у вас достаточно ОЗУ, чтобы весь ваш набор данных находился в памяти, просто используйте итеративное чтение IO, чтобы прочитать данные один раз в список.Затем передайте этот список классу gensim, где он ожидает любую итеративную последовательность.

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

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

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

...