Spacy - предварительная обработка и лемматизация занимают много времени

Я работаю над проблемой классификации текста, и я попробовал WordNetLemmmatizer, а затем TF-IDF, CountVectorizer. Теперь я пытаюсь очистить текст с помощью Spacy перед подачей в TF-IDF. Входной файл содержит около 20 000 записей, каждая из которых содержит несколько предложений. Общий размер файла 45 МБ.

Лемматизация с использованием WordNet занимала всего несколько секунд. Но приведенный ниже код с использованием Spacy занимает слишком много времени. Через 20 минут мой ноутбук повесили. Пожалуйста, посоветуйте, как оптимизировать Spacy для предварительной обработки текста и лемматизации.

Я использую Spacy 2.0.12.

import spacy
nlp = spacy.load('en', disable=['parser', 'tagger', 'ner'])

def spacy_lemma_text(text):
    doc = nlp(text)
    tokens = [tok.lemma_.lower().strip() for tok in doc if tok.lemma_ != '-PRON-']
    tokens = [tok for tok in tokens if tok not in nltk_stopwords and tok not in punctuations]
    tokens = ' '.join(tokens)
    return tokens

df['spacy_lemma_text'] = df['text'].apply(spacy_lemma_text)

person Chetan Ambi    schedule 19.09.2018    source источник


Ответы (2)


На ум приходят несколько возможных объяснений:

  • nltk_stopwords - это список, а не набор, поэтому проверки типа tok not in nltk_stopwords принимают линейное время вместо постоянного. Попробуйте добавить nltk_stopwords = set(nltk_stopwords) перед определением функции

  • возможно, вы используете другие пространственные модели, а не только лемматизатор и токенизатор. Лучше быть явным (пример из https://spacy.io/api/tokenizer):

    from spacy.lang.en import English
    tokenizer = English().Defaults.create_tokenizer(nlp)
    tokens = tokenizer(u'This is a sentence')
    assert len(tokens) == 4
  • вы загружаете просторную модель более одного раза?
  • как бы это ни было маловероятно, у вас может быть нехватка памяти. Пейджинг на диск сильно замедлит вас. Проверьте свой системный монитор / диспетчер задач
person mbatchkarov    schedule 19.09.2018
comment
Как и предполагалось, я пробовал использовать nltk_stopwords = set(nltk_stopwords), но все равно это занимает много времени и не дает результатов. В рамках предварительной обработки я пытаюсь лемматизировать слова, соединить их и добавить в новый столбец фрейма данных pandas. И я загружаю просторную модель только один раз в коде. - person Chetan Ambi; 19.09.2018

Вам следует использовать функцию spacy nlp.pipe, если вы выполняете итерацию по нескольким документам. Это позволит вам включить размер пакета, а также многопоточность. Spacy не настроен на работу так, как вы предложили.

Кроме того, я думаю, что использование стоп-слов nltk будет узким местом. Если вы используете spacy, продолжайте и используйте вместо него стоп-слова spacy. Они должны быть оптимизированы для использования в spacy, в отличие от nltk.

import spacy
from spacy.attrs import *
import numpy as np

nlp = spacy.load('en_core_web_lg')
texts = ["this is some sentence","This is the last sentence"]
max_length =10

data = np.zeros((len(texts), max_length), dtype=np.uint64)

for row, doc in enumerate(nlp.pipe(texts, n_threads=8, batch_size=10000)):
    dat = doc.to_array([LEMMA, IS_STOP])
    # Check to see if text length is not 0
    if len(dat) > 0:
        delete = np.where(dat[:, 1] == 1)
        dat = np.delete(dat, delete, 0)
        length = min(len(dat), max_length)
        data[row, :length] = dat[:length, 0].ravel()

Это оставит вам объемные хеш-данные, хранящиеся в массиве numpy. Затем эти хеш-данные можно преобразовать, обратившись к словарю spacy. У меня нет времени проверять это прямо сейчас, но я предполагаю, что это будет намного быстрее. Надеюсь это поможет.

person Nate Raw    schedule 19.09.2018