
Данная статья основана на пакете quick_sentiments для Python, который я разработал для упрощения анализа тональности. С исходным кодом можно ознакомиться здесь.
Хотели бы запускать полный сквозной анализ тональности — от исходного текста до готового прогноза — всего в три простых шага? Именно для решения этой задачи я создал свой новый Python-пакет quick_sentiments. Он берёт на себя все сложные и трудоемкие задачи по очистке текста, векторизации и машинному обучению «под капотом», позволяя вам сосредоточиться на результатах, а не на шаблонном коде.
Если вы когда-либо создавали проект по анализу тональности с нуля, то знаете, с какими трудностями приходиться сталкиваться в начале работы. Вы жонглируете импортами из nltk, scikit-learn и других библиотек, надеясь, что обновление не нарушит работу вашей среды. quick_sentiments создан, чтобы решить эту проблему. Он абстрагирует всю начальную настройку, управляя всеми зависимостями и сложными вызовами функций за вас.
Установить пакет в Python можно с помощью следующей команды:
!pip install quick-sentiments
#или
git clone https://github.com/AlabhyaMe/quick_sentiments.gitp
ШАГ 1: Предварительная обработка текста
Итак, начнем с первого шага: предварительной обработки текста. Прежде чем модель сможет понять текст, его необходимо очистить. Это критически важный, но утомительный этап, который включает целый список задач: удаление HTML-тегов, исключение эмодзи и знаков препинания, работа со стоп-словами, лемматизация и приведение к единому регистру. Чистый текст является необходимым фундаментом для качественной векторизации и, в конечном счете, для точной работы модели.
Как видно из примера, использование функции pre_process невероятно просто.
import polars as pl
#ИМПОРТИРУЕМ pre_process из quick_sentiments
from quick_sentiments import pre_process
df_train = pl.read_csv("yourpath.csv",encoding='ISO-8859-1')
response_column = "reviewText"
sentiment_column = "sentiment"
#ИСПОЛЬЗУЕМ pre_process
df_train = df_train.with_columns(
pl.col(response_column).map_elements(lambda x: pre_process(x, remove_brackets=True)).alias("processed") #добавляем внутри map_elements
)
Подумайте, что обычно требуется для очистки текста с нуля. Вам придется импортировать:
-
reдля регулярных выражений, чтобы обрабатывать URL-адреса;
- регулярные выражения для HTML-тегов;
nltkдля загрузки и инициализации списка стоп-слов;
-
nltkдля лемматизатора.
Это долгая и утомительная настройка, которую придется выполнять для каждого отдельного проекта.
quick_sentiments сжимает весь этот процесс в одну высоко настраиваемую функцию. Посмотрите, какие возможности управления появляются сразу после установки:
def pre_process(doc,
remove_brackets=True,
remove_urls=True,
remove_html=True,
lemmatize=True,
remove_stop_words=True,
remove_nums=False,
... # и много других параметров
return_string=True):
#КОД ДЛЯ ВСЕХ ЭТИХ ФУНКЦИЙ УЖЕ НАПИСАН ДЛЯ ВАС ВНУТРИ ПАКЕТА.
Исходный код также доступен по ссылке.
Эта единственная функция представляет собой полноценный пайплайн очистки текста. В примере с polars использованы настройки по умолчанию, но специально активирован параметр remove_brackets=True. Если же вам потребуется сохранить числа в тексте, передайте параметр remove_nums=False. Чтобы пропустить этап лемматизации для ускорения работы, установите lemmatize=False.
pre_process выполняет весь перечень задач — от нормализации юникода и удаления эмодзи до токенизации и лемматизации — одним чистым и простым вызовом.
Очищенная токенизированная строка теперь представляет собой идеальную основу для следующего шага: векторизации.
ШАГ 2: Разделение данных, векторизация, модели машинного обучения, точность
Переходим к самому мощному функционалу пакета quick_sentiments. После предварительной обработки остается наиболее трудоемкая часть работы, связанная с машинным обучением: разделением данных, векторизацией, обучением модели и оценкой. Именно на этом этапе большинство проектов замедляется, и именно здесь на помощь приходит run_pipeline().
Одна эта функция обрабатывает всю сложность за вас. Что критически важно, она выполняет разделение на обучающую и тестовую выборки до векторизации — это правильный подход для предотвращения утечки данных и получения достоверной оценки производительности модели.
Вам остается лишь предоставить свои данные, назвать столбцы и, что наиболее важно, выбрать эксперимент.
Хотите протестировать классический TF-IDF с логистической регрессией? Или сразу перейти к 100-мерным вложениям GloVe с нейронной сетью? Или пойти еще дальше с 300-мерным Word2Vec? Просто выберите то, что вам нужно.
Вот полный список методов векторизации и моделей машинного обучения, уже созданных и готовых к вызову по имени:
Методы векторизации (vectorizer_name):
"bow": Bag-of-Words;
"tf": частота терминов;
"tfidf": TF-IDF;
"wv": Word2Vec (обученная на ваших данных; будет загружена, если у вас ее еще нет);
"glove_25","glove_50","glove_100","glove_200": предварительно обученные вложения GloVe в различных измерениях.
Модели машинного обучения (model_name):
"logit": логистическая регрессия;
"rf": случайный лес;
"xgb": XGBoost;
"nn": простая нейронная сеть.
Вся эта мощь заключена в одном простом вызове функции:
dt= run_pipeline(
vectorizer_name="glove_25", # BOW, tf, tfidf, wv, glove_25,glove_50, glove_100, gl0ve_200
model_name="logit", # logit, rf, XGB, nn
df=df_train,
text_column_name="processed", # это название колонки с текстовыми данными,
sentiment_column_name = "sentiment",
perform_tuning = False # установите True, если хотите выполнить настройку гиперпараметров; это займет больше времени и
# может привести к нехватке памяти при работе с большими наборами данных,
)
Код доступен по ссылке.
#ВОТ ЧТО возвращает run_pipeline. Это важно для прогнозов
return {
"model_object": trained_model_object,
"vectorizer_name": vectorizer_name,
"vectorizer_object": fitted_vectorizer_object,
"label_encoder": label_encoder,
"y_test": y_test,
"y_pred": y_pred,
"accuracy": accuracy_score(y_test, y_pred),
"report": classification_report(y_test, y_pred, output_dict=True, target_names=label_encoder.classes_)
}
Одна из ключевых особенностей run_pipeline заключается не только в том, что она делает, но и в том, что возвращает. По завершении работы функция возвращает единственный, но мощный словарь Python, содержащий все обученные «артефакты».
Это означает, что подогнанный векторизатор, обученная модель, кодировщик меток и даже названия столбцов — все перечисленное упаковано и возвращено вам. Это невероятно важно, потому что это — «мозг», который вы только что обучили, сохраненный «в коробке» и готовый к применению на новых, ранее невиданных данных.
На этом этапе основная рабочая задача анализа тональности выполнена всего двумя функциями. С помощью всего лишь pre_process и run_pipeline мы успешно очистили, векторизовали, обучили и оценили модель на исходном наборе данных.
Но как насчет прогнозирования на совершенно новых данных? Именно здесь quick_sentiments облегчает следующий шаг. Вам, конечно, нужно будет пропустить новый необработанный текст через ту же функцию pre_process, но при этом не придется ничего переучивать. Объект «артефакт», возвращенный run_pipeline, содержит все подобранные компоненты, необходимые для мгновенного применения правильной векторизации, и модели к новым данным, обеспечивая последовательность всего процесса от начала до конца.
ШАГ 3: Выигрыш — прогнозирование на совершенно новых данных
#ПРЕДОБРАБОТКА НОВЫХ ДАННЫХ
new_data = new_data.with_columns(
pl.col(response_column).map_elements(lambda x: pre_process(x, remove_brackets=True)).alias("processed") #add inside the map_elements
)
Итак, вы успешно обучили и оценили модель на своем наборе данных, и функция run_pipeline() вернула словарь Python (сохраненный нами как dt), содержащий все обученные «артефакты».
Теперь пришло время использовать этот обученный «мозг» на совершенно новых, реальных данных.
quick_sentiments делает этот последний шаг делает таким же простым, как и первые два. Пропустив новый необработанный текст через ту же функцию pre_process() (чтобы обеспечить идентичную очистку), вы будете готовы к выполнению последней однострочной команды:
# Объект 'dt' - это словарь, возвращенный из вызова run_pipeline()
predictions_df = make_predictions(
new_data=new_data,
text_column_name="processed",
vectorizer=dt["vectorizer_object"],
best_model=dt["model_object"],
label_encoder=dt["label_encoder"],
prediction_column_name="sentiment_predictions" # Вы можете назвать выходной столбец
)
Что происходит «под капотом»
В этом единственном вызове make_predictions() проявляется вся мощь пайплайна. Чтобы понять, почему этот подход столь надежен, разберем аргументы:
vectorizer=dt["vectorizer_object"]: вы передаете конкретный обученный векторизатор, который был настроен на ваших данных;
best_model=dt["model_object"]: вы передаете конкретную обученную модель;
label_encoder=dt["label_encoder"]: вы передаете настроенный кодировщик меток, чтобы правильно преобразовать выходные данные обратно в ваши исходные метки (например, «положительный», «отрицательный»).
Такая конструкция избавляет вас от написания повторяющегося кода для векторизации и прогнозирования. Но что еще важнее, она устраняет наиболее распространенные и опасные ошибки в машинном обучении.
Как? Передавая обученные артефакты, вы делаете ошибки практически невозможными. Вам не нужно задавать себе следующие вопросы:
- «Не переобучил ли я случайно свой векторизатор на новых данных?»
- «Использую ли я те же
ngram_rangeиmax_features, что и для обучающих данных?» - «Использую ли я модель с лучшими гиперпараметрами или просто модель по умолчанию?»
Функция make_predictions() гарантирует обработку новых данных через точно такой же, последовательный пайплайн, как и исходные обучающие данные. Риск ошибки здесь сведен к нулю, поскольку вся сложная работа выполняется за вас «под капотом».
И вот у вас готов новый датафрейм с дополнительным столбцом прогнозов. Всего за три основных шага — pre_process(), run_pipeline() и make_predictions() — мы прошли полный путь анализа тональности: от необработанного текста до надежных прогнозов для реальных данных.
Полный исходный код доступен здесь.
Читайте также:
- Ruby может быть лучше Python для абсолютных новичков
- Создание простой платформы потоковой передачи данных
- Осваиваем веб-скрэпинг на Python
Читайте нас в Telegram, VK и Дзен
Перевод статьи Alabhya Dahal: Sentiment Analysis in 3 steps: Using quick_sentiments in Python





