Spacy - предварительная обработка и лемматизация, занимающая много времени - PullRequest
0 голосов
/ 19 сентября 2018

Я работаю над проблемой классификации текста, и я попробовал WordNetLemmmatizer, а затем TF-IDF, CountVectorizer.Сейчас я пытаюсь очистить текст с помощью Spacy перед передачей в TF-IDF.Входной файл содержит около 20000 записей, каждая из которых имеет несколько предложений.Общий размер файла 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)

Ответы [ 2 ]

0 голосов
/ 19 сентября 2018

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

Кроме того, использование стоп-слов nltk будет узким местом, я думаю.Если вы используете 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()

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

0 голосов
/ 19 сентября 2018

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

  • 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
  • загружаете ли вы пространственную модель более одного раза?
  • настолько маловероятно, насколько это возможно, вы могли бы бытьНедостаточно памяти. Пейджинг на диск сильно замедлит работу. Проверьте системный монитор / диспетчер задач
...