Классификация текста с помощью Python и Scikit-Learn

Введение Классификация текстов - одна из наиболее важных задач в обработке естественного языка [/ what-is-natural-language-processing /]. Это процесс классификации текстовых строк или документов по различным категориям в зависимости от содержимого строк. Классификация текста имеет множество приложений, таких как определение настроений пользователей из твита, классификация электронной почты как спама или ветчины, классификация сообщений в блогах по различным категориям, автоматическая пометка запросов клиентов и т. Д.

Вступление

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

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

Набор данных

Набор данных, который мы собираемся использовать в этой статье, можно загрузить в Cornell Natural Language Processing Group . Набор данных состоит из 2000 документов. Половина документов содержит положительные отзывы о фильме, а оставшаяся половина - отрицательные. Более подробную информацию о наборе данных можно найти по этой ссылке .

Разархивируйте или извлеките набор данных после его загрузки. Откройте папку «txt_sentoken». В папке есть две подпапки: «neg» и «pos». Если вы откроете эти папки, вы увидите текстовые документы, содержащие обзоры фильмов.

Анализ настроений с помощью Scikit-Learn

Теперь, когда мы загрузили данные, пора посмотреть на некоторые действия. В этом разделе мы выполним ряд шагов, необходимых для прогнозирования настроений на основе обзоров различных фильмов. Эти шаги можно использовать для любой задачи классификации текста. Мы будем использовать библиотеку Python Scikit-Learn для машинного обучения, чтобы обучить модель классификации текста.

Ниже приведены шаги, необходимые для создания модели классификации текста в Python:

  1. Импорт библиотек
  2. Импорт набора данных
  3. Предварительная обработка текста
  4. Преобразование текста в числа
  5. Наборы для обучения и тестирования
  6. Модель классификации обучающего текста и прогнозирование настроения
  7. Оценка модели
  8. Сохранение и загрузка модели

Импорт библиотек

Выполните следующий сценарий, чтобы импортировать необходимые библиотеки:

 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 чтобы увидеть, сможете ли вы добиться каких-либо улучшений.

comments powered by Disqus