Учитесь, создав конвейер для классификации отзывов
Сегодня мы строим конвейер без излишеств, чтобы классифицировать, является ли обзор фильма положительным или нет. Это задача булевой контролируемой классификации.
Этапы:
1. Загрузите набор данных
2. Загрузите набор данных в память
3. Разделите данные на обучающие и тестовые наборы
4. Сопоставьте и преобразуйте data
5. Обучить классификатор
6. Предсказать результаты набора тестов
7. Оценить результаты
8. Подведение итогов
1. Скачать набор данных
Загрузите набор данных по ссылке ниже и поместите его в тот же каталог
, что и ваш блокнот ipython. Данные содержат 300 положительных и
300 отрицательных отзывов о фильмах.
http://www.cs.cornell.edu/people/pabo/movie-review-data/review_polarity.tar.gz
Структура данных:
--review_polarity |-- txt_sentoken |-- pos |-- cv999_13106.txt |-- cv998_14111.txt |-- ... |-- neg |-- cv999_14636.txt |-- cv998_15691.txt |-- ...
2. Загрузить набор данных в память
import os # intialize X and y to store review text and sentiment X = [] y = [] # create lists of files in /pos and /neg directories pos_review_filenames = os.listdir('review_polarity/txt_sentoken/pos') new_review_filenames = os.listdir('review_polarity/txt_sentoken/neg') # add text from positive reviews to X and label 1 for filename in pos_review_filenames: file = open('review_polarity/txt_sentoken/pos/' + filename) text = file.read() # remove line breaks, '/n' string = ' '.join(text.split('\n')) # add to X X.append(string) # these reviews are all positive so label them, 1 y.append(1) # do the same with negative reviews and label 0 for filename in new_review_filenames: file = open('review_polarity/txt_sentoken/neg/' + filename) text = file.read() # remove line breaks, '/n' string = ' '.join(text.split('\n')) # add to X X.append(string) # these reviews are not positive so label this data, 0 y.append(0)
3. Разделить данные на обучающие и тестовые наборы
Теперь разделим данные на отдельные группы для обучения и тестирования. Обучение научит нашу модель классифицировать данные, а тестирование проверит ее на данных, не используемых для обучения.
В идеале оба набора разбиваются случайным образом, но сохраняют одинаковые пропорции классов. StratifiedShuffleSplit делает именно это (http://scikit-learn.org/stable/modules/generated/sklearn.model_selection.StratifiedShuffleSplit.html).
Теперь определите функцию для разделения данных.
from sklearn.model_selection import StratifiedShuffleSplit import numpy as np def split_data(contents, labels): splitter = StratifiedShuffleSplit(n_splits=1, test_size=0.3, random_state=0) for train_index, test_index in splitter.split(contents, labels): # Notice we're not splitting at a specific index but passing an array withindices were assigning to each set # '_pre_vectorize' here reminds me this data has not yet been converted into tf-idf features X_train_pre_vectorize, X_test_pre_vectorize = X[train_index], X[test_index] y_train, y_test = y[train_index], y[test_index] return X_train_pre_vectorize, y_train, X_test_pre_vectorize, y_test
И разделить данные.
# convert the X and y to arrays as this allows us to extract multiple elements via list of indices X = np.array(X) y = np.array(y) X_train_pre_vectorize, y_train, X_test_pre_vectorize, y_test = split_data(X, y)
4. Подгонка и преобразование данных
Это преобразует данные в матрицу оценок tf-idf на основе модели набора слов. Числовой вывод будет передан нашему классификатору, который не может обрабатывать слова самостоятельно.
from sklearn.feature_extraction.text import TfidfVectorizer # initialize instance of TfidfVectorizer vectorizer = TfidfVectorizer() # note we .fit_transform train, but only transform test, so all features are learned from train X_train = vectorizer.fit_transform(X_train_pre_vectorize) X_test = vectorizer.transform(X_test_pre_vectorize)
5. Классификатор поездов
Я выбрал классификатор, который в целом работает хорошо, но в реальном проекте я бы поэкспериментировал с несколькими классификаторами.
from sklearn.ensemble import RandomForestClassifier # initialize an instance of RandomForestClassifier classifier = RandomForestClassifier() # train the classifier classifier.fit(X_train, y_train)
6. Прогнозирование результатов набора тестов
И вуаля! Наша модель предсказывает метку на основе матриц tf-idf, полученных из исходных текстов обзоров.
y_pred = classifier.predict(X_test)
7. Оцените результаты
Давайте посмотрим, как поступила наша модель.
from sklearn.metrics import classification_report print(classification_report(y_test, y_pred))
Результаты:
precision recall f1-score support 0 0.64 0.83 0.72 300 1 0.76 0.53 0.63 300 avg / total 0.70 0.68 0.67 600
8. Подведение итогов
Результаты показывают, что наш классификатор «хорошо» классифицирует отзывы как положительные. Хотя со взвешенной оценкой f1 0,67 я бы не поставил эту модель близко к серийному производству.
Тем не менее, это зависит от последствий ложноположительных и ложноотрицательных результатов в каждом уникальном варианте использования.
Несколько быстрых способов, которыми мы могли бы попытаться улучшить результаты:
i) использование диапазона ngram в нашем векторизаторе
ii) удаление стоп-слов
iii) создание корневого или лемматизирующего текста отзыва
iv) экспериментировать с другими классификаторами