Время прочтения: 3 мин.

Большой объём всевозможных текстовых сообщений представляет собой интерес с точки зрения текстового анализа, однако именно их количество создаёт ряд проблем, связанных с временем которое требуется на их обработку. Даже с учётом использования методов Natural Language Processing на подготовку данных и формирование модели может уходить большое количество времени, так что полезно понимать каким образом можно повысить скорость выполнения расчётов.

В ходе работы служб банка возникает большой объём текстовых данных самого разного вида – договоры, жалобы, обращения, внутренняя переписка. Обрабатывать подобные данные вручную — это очень трудоёмкий и продолжительный процесс, но мы можем значительно упростить эту задачу с использованием Natural Language Processing.

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

Первый пример будет сделан на основе библиотеки pymorphy2.

Инициализируем необходимые библиотеки и данные:

import pymorphy2
from nltk.corpus import stopwords
from string import punctuation
from nltk.stem.wordnet import WordNetLemmatizer
import pandas as pd
import time

docs = pd.read_csv(r"example.txt", sep = ",",\
     quoting = 1, quotechar = "'", nrows = 100, encoding = 'utf-8', header = None, engine ='python')
russian_stopwords = stopwords.words("russian")
lemma = pymorphy2.MorphAnalyzer()

Код функции обработки текста:
def preprocess_text(doc):
    stop_free = " ".join([i for i in doc.lower().split() if i not in russian_stopwords])
    punc_free = ''.join(ch for ch in stop_free if ch not in punctuation)
    text = " ".join([lemma.parse(word)[0].normal_form for word in punc_free.split(' ')])
    return text

замерим производительность на 100, 300 и 1000 строк:

Кол-во строкВремя, сек
1000.56
3001.70
10004.54

Видно линейную зависимость, можно примерно оценить время обработки обращений исходя из их количества сделав предварительную обработку на малом объёме.

Сравним это с библиотекой pymystem3:

В предоставленный код требуется внести несколько изменений, загрузить библиотеку Pymystem3 и внести изменения в код обработки:

from pymystem3 import Mystem
mystem = Mystem() 
russian_stopwords = stopwords.words("russian")
def preprocess_text(doc):
    stop_free = " ".join([i for i in doc.lower().split() if i not in russian_stopwords])
    punc_free = ''.join(ch for ch in stop_free if ch not in punctuation)
    tokens = mystem.lemmatize(punc_free)
    tokens = [token for token in tokens if  token != " "]
    text = " ".join(tokens)
    
    return text
    text = " ".join([lemma.parse(word)[0].normal_form for word in punc_free.split(' ')])

Время обработки составляет:

Кол-во строкВремя, сек
100196
300580
10002044

Видно, что по каким-то причинам время выполнения на два порядка превышает pymorphy2, обработка одной строки занимает до двух секунд, не зависимо от одержимой строки.  
Попробуем внести изменения в наш код:

doc_split = []
buf = []
test = preprocess_text(' ‽ '.join(docs[1][0:1000]))
for x in test.split(' '):
    if '‽' in x:
        if len(x) > 1:
            doc_split += [' '.join(buf)]
            doc_split += ['']
        else:
            doc_split += [' '.join(buf)]
        buf = []
    else:
        buf += [x]
doc_split += [' '.join(buf)]

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

Кол-во строкВремя, сек
1001.88
3002.1
10002.7
100009.1

Результат заметно улучшен. И хотя на малом количестве строк время обработки по-прежнему превышает pymorphy2, на большом количестве текста мы получаем значительную выгоду за счёт нелинейного прироста времени выполнения.
Как видно подготовка текста для последующего использования в различных методах текстового анализа может занимать продолжительное время, но пользуясь различными методами его можно сократить, за счёт чего получится уменьшить общее время обработки. Правильный выбор алгоритмов обработки зависит от ряда характеристик исходного текста, и потому требуется проверять скорость выполнения на реальных данных чтобы добиться наилучшего результата.