Использование нового пакета Python EDA для очистки беспорядочного и неструктурированного текста

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

Data-description, который является одним из таких инструментов, представляет собой пакет с открытым исходным кодом, который предназначен для использования специалистами по данным для ускорения процесса исследовательского анализа данных. В то время как пакет имеет больше функций, помимо работы с текстом, в оставшейся части этой статьи исследуется очистка беспорядочных данных с помощью data-description, а затем показаны некоторые из его функций моделирования тем. Полное раскрытие информации: я являюсь одним из авторов data-describe, поэтому я не являюсь беспристрастным источником. Однако это не просто беспардонный плагин, поэтому продолжайте читать, чтобы увидеть, насколько полезным может быть этот инструмент.

Мы можем начать с импорта функций предварительной обработки текста из data-describe вместе с наборами данных scikit-learn, которые мы будем использовать. Категории были выбраны случайным образом, поэтому не стесняйтесь экспериментировать и экспериментировать, чтобы увидеть разные результаты.

from data_describe.text.text_preprocessing import *
from sklearn.datasets import fetch_20newsgroups
categories = ['rec.sport.baseball', 'rec.autos', 'sci.med', 'sci.space']
text_docs = fetch_20newsgroups(subset='train', categories=categories)['data']

Давайте взглянем на первый документ в нашем разнообразном корпусе:

Валовой. Множество символов новой строки, заглавных букв и знаков препинания, от которых нужно избавиться. Наша работа создана для нас. Давайте начнем с «токенизации» нашего текста или разделения однострочного документа на список слов.

При рассмотрении отдельных функций этого модуля предварительной обработки текста следует помнить о двух вещах:

  1. Для каждой отдельной отображаемой функции предварительной обработки выводом будет список строк.
  2. В коде отдельные функции предварительной обработки будут заключены в другую функцию «to_list». Это потому, что эти функции являются генераторами, то есть они выполняют итерацию по списку для возврата значений. Это обеспечивает расширяемость для более эффективной обработки, такой как многопроцессорность.
tokens = to_list(tokenize(text_docs))
tokens[0]

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

lower = to_list(to_lower(tokens))
lower[0]

Прогресс! Далее мы удалим знаки препинания. Эта функция может удалять или заменять знаки препинания. По умолчанию знаки препинания удаляются только в конце или в начале, но также можно настроить удаление всех экземпляров знаков препинания.

no_punct = to_list(remove_punct(lower))
no_punct[0]

После удаления знаков препинания мы можем перейти к удалению цифр и любых слов, содержащих цифры.

no_digits = to_list(remove_digits(no_punct))
no_digits[0]

Следующая функция удалит из текста все пустые пробелы или отдельные символы.

no_single_char_and_space = to_list(remove_single_char_and_spaces(no_digits))
no_single_char_and_space[0]

Далее следует удаление игнорируемых слов. В тематическом моделировании идея состоит в том, чтобы разделить текстовые документы по важным словам внутри тех документов, которые имеют центральное значение для смысла документа. По этой причине часто используемые слова, которые мало помогают в этом смысле, такие как «то», «что», «те» и т. Д., Удалены из документов. Хотя следующая функция удаляет все стоп-слова, определенные NLTK, из ваших документов, функция может принимать список дополнительных пользовательских стоп-слов в качестве параметра для их удаления.

no_stopwords = to_list(remove_stopwords(no_single_char_and_space))
no_stopwords[0]

Последующие функции могут быть использованы для «лемматизации» или «ограничения» документов. Идея состоит в том, чтобы сгруппировать похожие слова вместе, чтобы их можно было идентифицировать как таковые при моделировании темы. Например, при лемматизации слов «ломается» и «сломался» для каждого из них будет возвращено «разрыв». Точно так же слова во множественном и единственном числе будут рассматриваться как одно и то же. Основное различие между двумя разными методами заключается в том, что лемматизированные слова всегда остаются настоящими словами, в то время как это не относится к словам с корнем. Примеры ниже.

lem_docs = to_list(lemmatize(no_stopwords))
lem_docs[0]

stem_docs = to_list(stem(no_stopwords))
stem_docs[0]

После того, как все это будет сделано, мы можем вернуть список слов обратно в формат однострочного текстового документа.

clean_text_docs = to_list(bag_of_words_to_docs(no_stopwords))
clean_text_docs[0]

Итак, мы прошли долгий путь с момента появления первых необработанных текстовых документов. В этот момент все, вероятно, задаются вопросом, действительно ли нужно вводить ВСЕ эти функции, чтобы это сделать? Не беспокоиться! Есть одна функция, которая выполняет все эти шаги одним быстрым нажатием кнопки. Но ждать! Что, если необходимо применить настраиваемый шаг во время всей предварительной обработки? Еще раз не волнуйтесь! Пользовательские функции могут быть смешаны с предварительной обработкой. Следующий блок кода продемонстрирует, как это сделать.

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

Подсказка регулярного выражения.

import re
pattern = re.compile(r"[\s\S]*\nLines:([\s\S]*)")
def extract_lines(docs):
    for doc in docs:
        extract = pattern.match(doc).groups(0)[0]
        yield extract

Давайте посмотрим, как выглядит документ после сопоставления с шаблоном регулярного выражения выше.

Удаление темы и отправителя из документа (предупреждение о спойлере: документы представляют собой электронные письма) кажется хорошей идеей, чтобы убедиться, что содержимое документа остается актуальным, когда мы перейдем к моделированию темы. Это подводит нас к нашей функции предварительной обработки святого Грааля (примечание: функции из data-describe могут быть указаны с использованием строк в настраиваемом конвейере, в то время как настраиваемые функции вводятся как объекты функций).

clean_text_docs = preprocess_texts(text_docs, custom_pipeline=[
    extract_lines,
    'tokenize',
    'to_lower',
    'remove_punct',
    'remove_digits',
    'remove_single_char_and_spaces',
    'remove_stopwords',
    'stem',
    'bag_of_words_to_docs'
])
clean_text_docs[0]

Намного лучше. На этом этапе мы готовы к моделированию темы. Здесь также может помочь data-describe с помощью «виджета», который позволяет моделировать темы по выбору, будь то LDA, LSA, LSI, NMF или SVD. Хотя все это настраивается вместе с количеством тем и множеством других параметров, если параметры не введены, функция автоматически проверяет значения согласованности для модели для двух тем на протяжении всех десяти тем. Количество тем с наивысшим значением согласованности - это модель, которая будет возвращена.

from data_describe.text.topic_modeling import topic_model
lda_model = topic_model(clean_text_docs, model_type='LDA')

Первое, что мы можем сделать, это посмотреть на самые важные слова по теме, что можно сделать, показывая объект модели в новой ячейке.

lda_model

Здесь мы можем сделать ряд наблюдений. Мы должны помнить, что эти слова были вырезаны как часть конвейера предварительной обработки. В целом, если посмотреть на темы, «Тема 1» явно посвящена бейсболу, а «Тема 2» - космосу. Как модель решила, что количество тем будет шесть? Давайте посмотрим на значения согласованности для каждой модели с разным количеством тем.

lda_model.elbow_plot()

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

pd.set_option('display.max_colwidth', 500)
top_docs = lda_model.top_documents_per_topic(clean_text_docs_regex)
top_docs = top_docs[['Topic 1', 'Topic 2']]
top_docs.head(3)

Мы можем более подробно рассмотреть верхний документ по теме 1 ниже.

top_docs['Topic 1'].iloc[0][:700]

Как и ожидалось, этот документ посвящен бейсболу. Просматривая наши темы, мы видим, что, хотя первые две темы ясны по своему значению, остальные не так ясны. Это могло быть по разным причинам. Известно, что тематическое моделирование значительно лучше работает с более длинными документами, а не с более короткими текстами, такими как рассмотренные выше электронные письма. Возможно, потребуется дополнительная обработка регулярных выражений для обработки цитируемых цепочек и цепочек ответов в электронных письмах. Возможно, потребуется дополнительная настройка, начиная с рассмотрения частот слов (пока что не является функцией описания данных, но мы с радостью принимаем усилия по внесению вклада!). EDA - это только первый шаг в процессе моделирования, и именно в этом нам поможет data-describe.

Все, что упомянуто выше, представляет собой отличное введение в предварительную обработку текста и моделирование темы с использованием data-description, но это лишь поверхностное представление о возможностях пакета. Другие включают сводки данных, кластеризацию, корреляции, тепловые карты, графики распределения, ранжирование функций, диаграммы разброса, уменьшение размерности и многое другое, а также обеспечивают поддержку больших данных и конфиденциальных данных. Функции и улучшения постоянно добавляются авторами (включая меня) и сообществом разработчиков ПО с открытым исходным кодом, поэтому, пожалуйста, не стесняйтесь обращаться с любыми вопросами или присоединяться и начинать вносить свой вклад уже сегодня!