Вступление
Классификация текстов - одна из важнейших задач обработки естественного языка . Это процесс классификации текстовых строк или документов по различным категориям в зависимости от содержимого строк. Классификация текста имеет множество приложений, таких как определение настроения пользователей из твита, классификация электронной почты как спама или ветчины, классификация сообщений в блогах по различным категориям, автоматическая пометка запросов клиентов и т. Д.
В этой статье мы увидим реальный пример классификации текста. Мы обучим модель машинного обучения, способную предсказывать положительный или отрицательный отзыв о фильме. Это классический пример сентиментального анализа, когда чувства людей по отношению к определенной сущности классифицируются по разным категориям.
Набор данных
Набор данных, который мы собираемся использовать в этой статье, можно загрузить в Cornell Natural Language Processing Group . Набор данных состоит из 2000 документов. Половина документов содержит положительные отзывы о фильме, а оставшаяся половина - отрицательные. Более подробную информацию о наборе данных можно найти по этой ссылке .
Разархивируйте или извлеките набор данных после его загрузки. Откройте папку «txt_sentoken». В папке есть две подпапки: «neg» и «pos». Если вы откроете эти папки, вы увидите текстовые документы, содержащие обзоры фильмов.
Анализ настроений с помощью Scikit-Learn
Теперь, когда мы загрузили данные, пора посмотреть на некоторые действия. В этом разделе мы выполним ряд шагов, необходимых для прогнозирования настроений на основе обзоров различных фильмов. Эти шаги можно использовать для любой задачи классификации текста. Мы будем использовать библиотеку Python Scikit-Learn для машинного обучения, чтобы обучить модель классификации текста.
Ниже приведены шаги, необходимые для создания модели классификации текста в 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
автоматически делит набор данных на наборы данных и целевые наборы.
Например, в нашем случае мы передадим ему путь к каталогу
«txt_sentoken». load_files
будет рассматривать каждую папку внутри
папки «txt_sentoken» как одну категорию, и всем документам внутри этой
папки будет назначена соответствующая категория.
Выполните следующий сценарий, чтобы увидеть в load_files
функцию
load_files:
movie_data = load_files(r"D:\txt_sentoken")
X, y = movie_data.data, movie_data.target
В приведенном выше load_files
функция load_files загружает данные из
папок «neg» и «pos» в X
, в то время как целевые категории хранятся в
y
. Здесь X
- это список из 2000 элементов строкового типа, каждый
из которых соответствует просмотру одного пользователя. Точно так же y
- это numpy-массив размером 2000. Если вы напечатаете
y
на экране, вы увидите массив из единиц и нулей. Это связано с тем, что для каждой категорииload_files
добавляет число в целевой массив numpy. У нас есть две категории: «neg» и «pos», поэтому в целевой массив были добавлены единицы и нули.
Предварительная обработка текста
После того, как набор данных импортирован, следующим шагом будет предварительная обработка текста. Текст может содержать числа, специальные символы и нежелательные пробелы. В зависимости от проблемы, с которой мы сталкиваемся, нам может потребоваться или не нужно удалять эти специальные символы и числа из текста. Однако для пояснения мы удалим все специальные символы, числа и нежелательные пробелы из нашего текста. Выполните следующий сценарий для предварительной обработки данных:
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)
В приведенном выше скрипте мы используем Regex Expressions из библиотеки Python re для выполнения различных задач предварительной обработки. Мы начинаем с удаления всех символов, отличных от слов, таких как специальные символы, числа и т. Д.
Далее мы удаляем все одиночные символы. Например, когда мы удаляем знак
препинания из «David's» и заменяем его пробелом, мы получаем «David» и
единственный символ «s», который не имеет значения. Чтобы удалить такие
одиночные символы, мы используем \s+[a-zA-Z]\s+
которое заменяет все
одиночные символы, имеющие пробелы с обеих сторон, одним пробелом.
Затем мы используем \^[a-zA-Z]\s+
чтобы заменить один символ из начала
документа одним пробелом. Замена отдельных символов одним пробелом может
привести к появлению нескольких пробелов, что не идеально.
Мы снова используем регулярное выражение \s+
для замены одного или
нескольких пробелов одним пробелом. Если у вас есть набор данных в
байтовом формате, буква алфавита «b» добавляется перед каждой строкой.
Регулярное выражение ^b\s+
удаляет "b" из начала строки. Следующим
шагом является преобразование данных в нижний регистр, чтобы слова,
которые на самом деле являются одними и теми же, но в разных регистрах,
можно было обрабатывать одинаково.
Последний шаг предварительной обработки - лемматизация . При лемматизации мы приводим слово к словарной корневой форме. Например, «коты» превращаются в «кошки». Лемматизация выполняется, чтобы избежать создания функций, которые семантически похожи, но синтаксически различаются. Например, нам не нужны две разные функции с именами «кошки» и «кошка», которые семантически похожи, поэтому мы выполняем лемматизацию.
Преобразование текста в числа
Машины, в отличие от людей, не могут понять исходный текст. Машины могут видеть только числа. В частности, статистические методы, такие как машинное обучение, могут иметь дело только с числами. Следовательно, нам нужно преобразовать наш текст в числа.
Существуют разные подходы к преобразованию текста в соответствующую числовую форму. Модель «мешок слов» и « модель вложения слов» - два наиболее часто используемых подхода. В этой статье мы будем использовать модель мешка слов для преобразования нашего текста в числа.
Мешок слов
Следующий скрипт использует модель мешка слов для преобразования текстовых документов в соответствующие числовые функции:
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% всех документов. Слова, которые
встречаются почти в каждом документе, обычно не подходят для
классификации, потому что они не предоставляют какой-либо уникальной
информации о документе.
Наконец, мы удаляем
стоп-слова из нашего текста,
поскольку в случае анализа тональности стоп-слова могут не содержать
никакой полезной информации. Чтобы удалить стоп - слова мы передаем
stopwords
объект из nltk.corpus
библиотеки в stop_words
параметр.
fit_transform
функция CountVectorizer
класса преобразует текстовые
документы в соответствующие числовые функции.
Поиск TFIDF
Подход с использованием набора слов отлично подходит для преобразования текста в числа. Однако у него есть один недостаток. Он присваивает оценку слову на основе его появления в конкретном документе. При этом не учитывается тот факт, что это слово может также часто встречаться в других документах. TFIDF решает эту проблему, умножая частоту термина слова на обратную частоту документа. TF означает «Term Frequency», а IDF - «Inverse Document Frequency».
Частота термина рассчитывается как:
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 для слова в конкретном документе выше, если частота встречаемости этого слова выше в этом конкретном документе, но ниже во всех других документах.
Чтобы преобразовать значения, полученные с помощью модели мешка слов, в значения TFIDF, выполните следующий скрипт:
from sklearn.feature_extraction.text import TfidfTransformer
tfidfconverter = TfidfTransformer()
X = tfidfconverter.fit_transform(X).toarray()
Примечание:
Вы также можете напрямую преобразовать текстовые документы в значения функций TFIDF (без предварительного преобразования документов в функции набора слов), используя следующий скрипт:
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% обучающий набор.
Модель классификации обучающего текста и прогнозирование настроения
Мы разделили наши данные на набор для обучения и тестирования. Пришло время увидеть настоящие действия. Мы будем использовать алгоритм случайного леса для обучения нашей модели. Вы можете использовать любую другую модель по вашему выбору.
Для обучения нашей модели машинного обучения с использованием алгоритма
случайного леса мы будем использовать класс RandomForestClassifier
из
библиотеки 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
чтобы
увидеть, сможете ли вы добиться каких-либо улучшений.