Вступление
Классификация текстов-одна из важнейших задач обработки естественного языка . Это процесс классификации текстовых строк или документов по различным категориям в зависимости от содержания строк. Классификация текста имеет множество приложений, таких как определение настроений пользователей по твиту, классификация электронной почты как спама или ветчины, классификация сообщений в блогах по различным категориям, автоматическая маркировка запросов клиентов и т. Д.
В этой статье мы рассмотрим реальный пример классификации текста. Мы будем обучать модель машинного обучения, способную предсказать, является ли данный обзор фильма положительным или отрицательным. Это классический пример сентиментального анализа, когда чувства людей по отношению к тому или иному субъекту классифицируются по различным категориям.
Набор данных
Набор данных, который мы собираемся использовать для этой статьи, можно загрузить из Cornell Natural Language Processing Group . Набор данных состоит в общей сложности из 2000 документов. Половина документов содержит положительные отзывы о фильме, а остальная половина-отрицательные. Более подробную информацию о наборе данных можно найти по ссылке this link .
Распакуйте или извлеките набор данных после его загрузки. Откройте папку “txt_send token”. Папка содержит две подпапки: “neg” и “pos”. Если вы откроете эти папки, то увидите текстовые документы, содержащие обзоры фильмов.
Анализ настроений с помощью Scikit-Learn
Теперь, когда мы загрузили данные, пришло время увидеть некоторые действия. В этом разделе мы выполним ряд шагов, необходимых для прогнозирования настроений на основе отзывов о различных фильмах. Эти шаги можно использовать для любой задачи классификации текста. Мы будем использовать библиотеку Scikit-Learn Python для машинного обучения для обучения модели классификации текста.
Ниже приведены шаги, необходимые для создания модели классификации текста в Python:
- Импорт библиотек
- Импорт набора данных
- Предварительная обработка текста
- Преобразование текста в числа
- Учебные и тестовые наборы
- Обучающая Модель Классификации текста и прогнозирования настроений
- Оценка Модели
- Сохранение и загрузка модели
Импорт библиотек
Выполните следующий сценарий для импорта необходимых библиотек:
import numpy as np import re import nltk from sklearn.datasets import load_files nltk.download('stopwords') import pickle from nltk.corpus import stopwords
Импорт набора данных
Мы будем использовать функцию load_files
из библиотеки sklearn_datasets
для импорта набора данных в наше приложение. Функция load_files
автоматически делит набор данных на наборы данных и целевые наборы. Например, в нашем случае мы передадим ему путь к каталогу “text_send token”. Файл load_files
будет рассматривать каждую папку внутри папки “text_send token” как одну категорию, и всем документам внутри этой папки будет присвоена соответствующая категория.
Выполните следующий скрипт, чтобы увидеть load_files
функцию в действии:
movie_data = load_files(r"D:\txt_sentoken") X, y = movie_data.data, movie_data.target
В приведенном выше скрипте функция load_files
загружает данные из папок “neg” и “pos” в переменную X
, в то время как целевые категории хранятся в y
. Здесь X
– это список из 2000 элементов строкового типа, где каждый элемент соответствует одному пользовательскому обзору. Аналогично, y
– это массив numpy размером 2000. Если вы напечатаете y
на экране, вы увидите массив 1s и 0s. Это происходит потому, что для каждой категории функция load_files
добавляет число в целевой массив numpy. У нас есть две категории: “neg” и “pos”, поэтому 1s и 0s были добавлены в целевой массив.
Предварительная обработка текста
После импорта набора данных следующим шагом является предварительная обработка текста. Текст может содержать цифры, специальные символы и ненужные пробелы. В зависимости от проблемы, с которой мы сталкиваемся, нам может понадобиться или не понадобиться удалять эти специальные символы и цифры из текста. Однако ради объяснения мы удалим все специальные символы, цифры и ненужные пробелы из нашего текста. Выполните следующий сценарий для предварительной обработки данных:
documents = [] from nltk.stem import WordNetLemmatizer stemmer = WordNetLemmatizer() for sen in range(0, len(X)): # Remove all the special characters document = re.sub(r'\W', ' ', str(X[sen])) # remove all single characters document = re.sub(r'\s+[a-zA-Z]\s+', ' ', document) # Remove single characters from the start document = re.sub(r'\^[a-zA-Z]\s+', ' ', document) # Substituting multiple spaces with single space document = re.sub(r'\s+', ' ', document, flags=re.I) # Removing prefixed 'b' document = re.sub(r'^b\s+', '', document) # Converting to Lowercase document = document.lower() # Lemmatization document = document.split() document = [stemmer.lemmatize(word) for word in document] document = ' '.join(document) documents.append(document)
В приведенном выше сценарии мы используем регулярные выражения из библиотеки Python re для выполнения различных задач предварительной обработки. Мы начинаем с удаления всех несловесных символов, таких как специальные символы, цифры и т. Д.
Далее мы удаляем все одиночные символы. Например, когда мы убираем знак препинания из “Давида” и заменяем его пробелом, мы получаем “Давида” и один символ “s”, который не имеет никакого значения. Для удаления таких одиночных символов мы используем \s+[a-zA-Z]\s+
регулярное выражение, которое заменяет все одиночные символы, имеющие пробелы с обеих сторон, одним пробелом.
Затем мы используем регулярное выражение \^[a-zA-Z]\s+
для замены одного символа из начала документа одним пробелом. Замена отдельных символов одним пробелом может привести к появлению нескольких пробелов, что не является идеальным решением.
Мы снова используем регулярное выражение \s+
для замены одного или нескольких пробелов одним пробелом. Когда у вас есть набор данных в байтовом формате, буква алфавита “b” добавляется перед каждой строкой. Регулярное выражение ^b\s+
удаляет “b” из начала строки. Следующий шаг-преобразовать данные в нижний регистр, чтобы слова, которые на самом деле одинаковы, но имеют разные падежи, можно было рассматривать одинаково.
Заключительным этапом предварительной обработки является лемматизация . В лемматизации мы сводим слово к словарной корневой форме. Например, “кошки” преобразуются в “кошку”. Лемматизация делается для того, чтобы избежать создания признаков, которые семантически похожи, но синтаксически различны. Например, мы не хотим, чтобы две разные функции назывались “кошки” и “кошка”, которые семантически похожи, поэтому мы выполняем лемматизацию.
Преобразование текста в числа
Машины, в отличие от людей, не могут понять сырой текст. Машины могут видеть только цифры. В частности, статистические методы, такие как машинное обучение, могут работать только с числами. Поэтому нам нужно преобразовать наш текст в числа.
Существуют различные подходы к преобразованию текста в соответствующую числовую форму. Модель мешка слов и Модель встраивания слов являются двумя наиболее часто используемыми подходами. В этой статье мы будем использовать модель мешка слов для преобразования нашего текста в числа.
Мешок слов
Следующий сценарий использует модель bag of words для преобразования текстовых документов в соответствующие числовые объекты:
from sklearn.feature_extraction.text import CountVectorizer vectorizer = CountVectorizer(max_features=1500, min_df=5, max_df=0.7, stop_words=stopwords.words('english')) X = vectorizer.fit_transform(documents).toarray()
Приведенный выше скрипт использует класс CountVectorizer
из библиотеки sklearn.feature_extraction.text|/. Есть некоторые важные параметры, которые необходимо передать конструктору класса. Первый параметр-это параметр
max_features , который имеет значение 1500. Это происходит потому, что при преобразовании слов в числа с помощью подхода "мешок слов" все уникальные слова во всех документах преобразуются в объекты. Все документы могут содержать десятки тысяч уникальных слов. Но слова, которые имеют очень низкую частоту встречаемости, обычно не являются хорошим параметром для классификации документов. Поэтому мы устанавливаем параметр
max_features равным 1500, что означает, что мы хотим использовать 1500 наиболее часто встречающихся слов в качестве признаков для обучения нашего классификатора.
Следующий параметр – min_df
, и он был установлен на 5. Это соответствует минимальному количеству документов, которые должны содержать эту функцию. Поэтому мы включаем только те слова, которые встречаются по крайней мере в 5 документах. Аналогично, для функции max_df
значение устанавливается равным 0,7; в которой дробь соответствует проценту. Здесь 0.7 означает, что мы должны включать только те слова, которые встречаются максимум в 70% всех документов. Слова, встречающиеся почти в каждом документе, обычно не подходят для классификации, поскольку они не дают никакой уникальной информации о документе.
Наконец, мы удаляем стоп-слова из нашего текста, поскольку в случае анализа настроений стоп-слова могут не содержать никакой полезной информации. Чтобы удалить стоп-слова, мы передаем объект stop words из библиотеки
nltk.corpus в параметр
stop_words .
Функция fit_transform
класса CountVectorizer
преобразует текстовые документы в соответствующие числовые объекты.
Поиск TFIDF
Подход “мешок слов” отлично подходит для преобразования текста в числа. Однако у него есть один недостаток. Он присваивает оценку слову на основе его появления в конкретном документе. При этом не учитывается тот факт, что это слово может также иметь высокую частоту встречаемости и в других документах. TFIDF решает эту проблему путем умножения частоты термина слова на обратную частоту документа. TF расшифровывается как “Частота термина”, а IDF-как “Обратная частота документа”.
Термин частота вычисляется как:
Term frequency = (Number of Occurrences of a word)/(Total words in the document)
А обратная частота документа вычисляется как:
IDF(word) = Log((Total number of documents)/(Number of documents containing the word))
Значение TFIDF для слова в конкретном документе выше, если частота встречаемости этого слова выше в этом конкретном документе, но ниже во всех других документах.
Чтобы преобразовать значения, полученные с помощью модели bag of words, в значения TF IDF, выполните следующий скрипт:
from sklearn.feature_extraction.text import TfidfTransformer tfidfconverter = TfidfTransformer() X = tfidfconverter.fit_transform(X).toarray()
Примечание:
Вы также можете напрямую конвертировать текстовые документы в значения функций TFIDF (без предварительного преобразования документов в функции bag of words), используя следующий скрипт:
from sklearn.feature_extraction.text import TfidfVectorizer tfidfconverter = TfidfVectorizer(max_features=1500, min_df=5, max_df=0.7, stop_words=stopwords.words('english')) X = tfidfconverter.fit_transform(documents).toarray()
Наборы для обучения и тестирования
Как и любая другая контролируемая задача машинного обучения, мы должны разделить наши данные на обучающие и тестовые наборы. Для этого мы воспользуемся утилитой train_test_split
из библиотеки sklearn.model_selection
. Выполните следующий сценарий:
from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
Приведенный выше сценарий делит данные на 20% тестового набора и 80% обучающего набора.
Обучающая Модель Классификации текста и прогнозирования настроений
Мы разделили наши данные на обучающий и тестовый набор. Сейчас самое время увидеть реальное действие. Мы будем использовать алгоритм Случайного леса для обучения нашей модели. Вы можете использовать любую другую модель по вашему выбору.
Для обучения нашей модели машинного обучения с использованием алгоритма случайного леса мы будем использовать Классификатор случайного леса
класс из библиотеки sklearn.ensemble
. Метод fit
этого класса используется для обучения алгоритма. Нам нужно передать обучающие данные и обучающие целевые наборы этому методу. Взгляните на следующий сценарий:
classifier = RandomForestClassifier(n_estimators=1000, random_state=0) classifier.fit(X_train, y_train)
Наконец, чтобы предсказать настроение документов в нашем тестовом наборе, мы можем использовать метод predict
класса RandomForestClassifier
, как показано ниже:
y_pred = classifier.predict(X_test)
Поздравляю, вы успешно обучили свою первую модель классификации текста и сделали некоторые прогнозы. Теперь самое время посмотреть на производительность модели, которую вы только что создали.
Оценка модели
Чтобы оценить эффективность классификационной модели, такой как та, которую мы только что обучили , мы можем использовать такие метрики, как матрица путаницы , мера F1 и точность.
Чтобы найти эти значения, мы можем использовать утилиты classification_report
, confusion_matrix
и accuracy_score
из библиотеки sklearn.metrics
. Для этого выполните следующий сценарий:
from sklearn.metrics import classification_report, confusion_matrix, accuracy_score print(confusion_matrix(y_test,y_pred)) print(classification_report(y_test,y_pred)) print(accuracy_score(y_test, y_pred))
Вывод выглядит следующим образом:
[[180 28] [ 30 162]] precision recall f1-score support 0 0.86 0.87 0.86 208 1 0.85 0.84 0.85 192 avg / total 0.85 0.85 0.85 400 0.855
Из выходных данных видно, что наша модель достигла точности 85,5%, что очень хорошо, учитывая тот факт, что мы случайным образом выбрали все параметры для CountVectorizer
, а также для нашего алгоритма случайного леса.
Сохранение и загрузка модели
В приведенном выше сценарии выполнение нашей модели машинного обучения не заняло много времени. Одной из причин быстрого времени обучения является тот факт, что у нас был относительно меньший тренировочный набор. У нас было 2000 документов, из которых 80% (1600) мы использовали для обучения. Однако в реальных сценариях могут быть миллионы документов. В таких случаях обучение алгоритмов может занять часы или даже дни (если у вас более медленные машины). Поэтому рекомендуется сохранить модель после ее обучения.
Мы можем сохранить нашу модель как объект pickle
в Python. Для этого выполните следующий сценарий:
with open('text_classifier', 'wb') as picklefile: pickle.dump(classifier,picklefile)
После выполнения описанного выше скрипта вы можете увидеть файл text_classifier
в своем рабочем каталоге. Мы сохранили нашу обученную модель и можем использовать ее позже для прямого предсказания, без обучения.
Для загрузки модели мы можем использовать следующий код:
with open('text_classifier', 'rb') as training_model: model = pickle.load(training_model)
Мы загрузили нашу обученную модель и сохранили ее в переменной model
. Давайте спрогнозируем настроение тестового набора с помощью нашей загруженной модели и посмотрим, сможем ли мы получить те же результаты. Выполните следующий сценарий:
y_pred2 = model.predict(X_test) print(confusion_matrix(y_test, y_pred2)) print(classification_report(y_test, y_pred2)) print(accuracy_score(y_test, y_pred2))
Вывод выглядит следующим образом:
[[180 28] [ 30 162]] precision recall f1-score support 0 0.86 0.87 0.86 208 1 0.85 0.84 0.85 192 avg / total 0.85 0.85 0.85 400 0.855
Результат похож на тот, который мы получили ранее, который показал, что мы успешно сохранили и загрузили модель.
Вывод
Классификация текста-одна из наиболее часто используемых задач НЛП. В этой статье мы видели простой пример того, как классификация текста может быть выполнена в Python. Мы провели сентиментальный анализ рецензий на фильмы.
Я бы посоветовал вам изменить какой-нибудь другой алгоритм машинного обучения, чтобы посмотреть, сможете ли вы улучшить его производительность. Кроме того, попробуйте изменить параметры класса CountVectorizer
, чтобы увидеть, сможете ли вы получить какие-либо улучшения.