Постановка задачи
Проблема двоичной классификации с выводом либо 0: отрицательный отзыв, либо 1: положительный отзыв. Ввод представляет собой текст: Обзоры фильмов IMDB, что делает этот проект подпадающим под действие подмножества обработки естественного языка (NLP), называемого анализом настроений. Цель состоит в том, чтобы предсказать количество положительных и отрицательных отзывов на основе настроений с использованием различных моделей классификации.
Импортировать необходимые библиотеки
import numpy as np import pandas as pd import seaborn as sns import matplotlib.pyplot as plt import nltk from sklearn.feature_extraction.text import CountVectorizer from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.preprocessing import LabelBinarizer from nltk.corpus import stopwords from nltk.stem.porter import PorterStemmer from wordcloud import WordCloud,STOPWORDS from nltk.stem import WordNetLemmatizer from nltk.tokenize import word_tokenize,sent_tokenize from bs4 import BeautifulSoup import spacy import re,string,unicodedata from nltk.tokenize.toktok import ToktokTokenizer from nltk.stem import LancasterStemmer,WordNetLemmatizer from sklearn.linear_model import LogisticRegression,SGDClassifier from sklearn.naive_bayes import MultinomialNB from sklearn.svm import SVC from textblob import TextBlob from textblob import Word from sklearn.metrics import classification_report,confusion_matrix,accuracy_score
Загрузить данные
Загрузите данные с: https://www.kaggle.com/datasets/lakshmi25npathi/imdb-dataset-of-50k-movie-reviews и поместите файл CSV в каталог с именем \Data относительно пути к блокноту. .
imdb_data=pd.read_csv('Data/IMDB Dataset.csv') print(imdb_data.shape) imdb_data.head(10)
Разделение обучающего набора данных
#train dataset train_reviews=imdb_data.review[:40000] train_sentiments=imdb_data.sentiment[:40000] #test dataset test_reviews=imdb_data.review[40000:] test_sentiments=imdb_data.sentiment[40000:]
Нормализация текста
#Tokenization of text nltk.download('stopwords') tokenizer=ToktokTokenizer() #Setting English stopwords stopword_list=nltk.corpus.stopwords.words('english')
Удаление полос HTML и шумового текста
#Removing the html strips def strip_html(text): soup = BeautifulSoup(text, "html.parser") return soup.get_text() #Removing the square brackets def remove_between_square_brackets(text): return re.sub('\[[^]]*\]', '', text) #Removing the noisy text def denoise_text(text): text = strip_html(text) text = remove_between_square_brackets(text) return text #Apply function on review column imdb_data['review']=imdb_data['review'].apply(denoise_text)
Удаление специальных символов
#Removing special characters def remove_special_characters(text, remove_digits=True): pattern=r'[^a-zA-z0-9\s]' text=re.sub(pattern,'',text) return text #Apply function on review column imdb_data['review']=imdb_data['review'].apply(remove_special_characters)
Вывод текста
#Stemming the text def simple_stemmer(text): ps=nltk.porter.PorterStemmer() text= ' '.join([ps.stem(word) for word in text.split()]) return text #Apply function on review column imdb_data['review']=imdb_data['review'].apply(simple_stemmer)
Удаление стоп-слов
set stopwords to english stop=set(stopwords.words('english')) print(stop) #removing the stopwords def remove_stopwords(text, is_lower_case=False): tokens = tokenizer.tokenize(text) tokens = [token.strip() for token in tokens] if is_lower_case: filtered_tokens = [token for token in tokens if token not in stopword_list] else: filtered_tokens = [token for token in tokens if token.lower() not in stopword_list] filtered_text = ' '.join(filtered_tokens) return filtered_text #Apply function on review column imdb_data['review']=imdb_data['review'].apply(remove_stopwords)
Нормализованные обзоры поездов и тестов
#Normalized train reviews norm_train_reviews=imdb_data.review[:40000] norm_train_reviews[0] #Normalized test reviews norm_test_reviews=imdb_data.review[40000:] norm_test_reviews[45005]
Сумки словесной модели
Он используется для преобразования текстовых документов в числовые векторы или набор слов.
#Count vectorizer for bag of words cv=CountVectorizer(min_df=0,max_df=1,binary=False,ngram_range=(1,3)) #transformed train reviews cv_train_reviews=cv.fit_transform(norm_train_reviews) #transformed test reviews cv_test_reviews=cv.transform(norm_test_reviews) print('BOW_cv_train:',cv_train_reviews.shape) print('BOW_cv_test:',cv_test_reviews.shape) #vocab=cv.get_feature_names()-toget feature names
Термин частотно-обратная частотная модель документа (TFIDF)
Он используется для преобразования текстовых документов в матрицу функций tfidf.
#Tfidf vectorizer tv=TfidfVectorizer(min_df=0,max_df=1,use_idf=True,ngram_range=(1,3)) #transformed train reviews tv_train_reviews=tv.fit_transform(norm_train_reviews) #transformed test reviews tv_test_reviews=tv.transform(norm_test_reviews) print('Tfidf_train:',tv_train_reviews.shape) print('Tfidf_test:',tv_test_reviews.shape)
Маркировка текста настроений
#labeling the sentient data lb=LabelBinarizer() #transformed sentiment data sentiment_data=lb.fit_transform(imdb_data['sentiment']) print(sentiment_data.shape)
Разделите данные о настроениях
#Spliting the sentiment data train_sentiments=sentiment_data[:40000] test_sentiments=sentiment_data[40000:] print(train_sentiments) print(test_sentiments)
Моделирование набора данных
Давайте построим модель логистической регрессии как для набора слов, так и для функций tfidf.
#training the model lr=LogisticRegression(penalty='l2',max_iter=500,C=1,random_state=42) #Fitting the model for Bag of words lr_bow=lr.fit(cv_train_reviews,train_sentiments) print(lr_bow) #Fitting the model for tfidf features lr_tfidf=lr.fit(tv_train_reviews,train_sentiments) print(lr_tfidf)
Производительность модели логистической регрессии в тестовом наборе данных
#Predicting the model for bag of words lr_bow_predict=lr.predict(cv_test_reviews) print(lr_bow_predict) ##Predicting the model for tfidf features lr_tfidf_predict=lr.predict(tv_test_reviews) print(lr_tfidf_predict)
Точность модели
#Accuracy score for bag of words lr_bow_score=accuracy_score(test_sentiments,lr_bow_predict) print("lr_bow_score :",lr_bow_score) #Accuracy score for tfidf features lr_tfidf_score=accuracy_score(test_sentiments,lr_tfidf_predict) print("lr_tfidf_score :",lr_tfidf_score)
Распечатать отчет о классификации
#Classification report for bag of words lr_bow_report=classification_report(test_sentiments,lr_bow_predict,target_names=['Positive','Negative']) print(lr_bow_report) #Classification report for tfidf features lr_tfidf_report=classification_report(test_sentiments,lr_tfidf_predict,target_names=['Positive','Negative']) print(lr_tfidf_report) Output: precision recall f1-score support Positive 0.75 0.75 0.75 4993 Negative 0.75 0.75 0.75 5007 accuracy 0.75 10000 macro avg 0.75 0.75 0.75 10000 weighted avg 0.75 0.75 0.75 10000 precision recall f1-score support Positive 0.74 0.77 0.75 4993 Negative 0.76 0.73 0.75 5007 accuracy 0.75 10000 macro avg 0.75 0.75 0.75 10000 weighted avg 0.75 0.75 0.75 10000
Матрица путаницы
#confusion matrix for bag of words cm_bow=confusion_matrix(test_sentiments,lr_bow_predict,labels=[1,0]) print(cm_bow) #confusion matrix for tfidf features cm_tfidf=confusion_matrix(test_sentiments,lr_tfidf_predict,labels=[1,0]) print(cm_tfidf) [[3768 1239] [1249 3744]] [[3663 1344] [1156 3837]]
Стохастический градиентный спуск или линейные опорные векторные машины для набора слов и функций tfidf
#training the linear svm svm=SGDClassifier(loss='hinge',max_iter=500,random_state=42) #fitting the svm for bag of words svm_bow=svm.fit(cv_train_reviews,train_sentiments) print(svm_bow) #fitting the svm for tfidf features svm_tfidf=svm.fit(tv_train_reviews,train_sentiments) print(svm_tfidf)
Производительность модели на тестовых данных
#Predicting the model for bag of words svm_bow_predict=svm.predict(cv_test_reviews) print(svm_bow_predict) #Predicting the model for tfidf features svm_tfidf_predict=svm.predict(tv_test_reviews) print(svm_tfidf_predict)
Точность модели
#Accuracy score for bag of words svm_bow_score=accuracy_score(test_sentiments,svm_bow_predict) print("svm_bow_score :",svm_bow_score) #Accuracy score for tfidf features svm_tfidf_score=accuracy_score(test_sentiments,svm_tfidf_predict) print("svm_tfidf_score :",svm_tfidf_score) svm_bow_score : 0.5829 svm_tfidf_score : 0.5112
Распечатать отчет о классификации
#Classification report for bag of words svm_bow_report=classification_report(test_sentiments,svm_bow_predict,target_names=['Positive','Negative']) print(svm_bow_report) #Classification report for tfidf features svm_tfidf_report=classification_report(test_sentiments,svm_tfidf_predict,target_names=['Positive','Negative']) print(svm_tfidf_report) precision recall f1-score support Positive 0.94 0.18 0.30 4993 Negative 0.55 0.99 0.70 5007 accuracy 0.58 10000 macro avg 0.74 0.58 0.50 10000 weighted avg 0.74 0.58 0.50 10000 precision recall f1-score support Positive 1.00 0.02 0.04 4993 Negative 0.51 1.00 0.67 5007 accuracy 0.51 10000 macro avg 0.75 0.51 0.36 10000 weighted avg 0.75 0.51 0.36 10000
Распечатайте матрицу путаницы
#confusion matrix for bag of words cm_bow=confusion_matrix(test_sentiments,svm_bow_predict,labels=[1,0]) print(cm_bow) #confusion matrix for tfidf features cm_tfidf=confusion_matrix(test_sentiments,svm_tfidf_predict,labels=[1,0]) print(cm_tfidf) [[4948 59] [4112 881]] [[5007 0] [4888 105]]
Полиномиальный наивный байесовский набор слов и функции tfidf
#training the model mnb=MultinomialNB() #fitting the svm for bag of words mnb_bow=mnb.fit(cv_train_reviews,train_sentiments) print(mnb_bow) #fitting the svm for tfidf features mnb_tfidf=mnb.fit(tv_train_reviews,train_sentiments)
Производительность модели на тестовых данных
#Predicting the model for bag of words mnb_bow_predict=mnb.predict(cv_test_reviews) print(mnb_bow_predict) #Predicting the model for tfidf features mnb_tfidf_predict=mnb.predict(tv_test_reviews) print(mnb_tfidf_predict)
Точность модели
#Accuracy score for bag of words mnb_bow_score=accuracy_score(test_sentiments,mnb_bow_predict) print("mnb_bow_score :",mnb_bow_score) #Accuracy score for tfidf features mnb_tfidf_score=accuracy_score(test_sentiments,mnb_tfidf_predict) print("mnb_tfidf_score :",mnb_tfidf_score) mnb_bow_score : 0.751 mnb_tfidf_score : 0.7509
Распечатать отчет о классификации
#Classification report for bag of words mnb_bow_report=classification_report(test_sentiments,mnb_bow_predict,target_names=['Positive','Negative']) print(mnb_bow_report) #Classification report for tfidf features mnb_tfidf_report=classification_report(test_sentiments,mnb_tfidf_predict,target_names=['Positive','Negative']) print(mnb_tfidf_report) precision recall f1-score support Positive 0.75 0.76 0.75 4993 Negative 0.75 0.75 0.75 5007 accuracy 0.75 10000 macro avg 0.75 0.75 0.75 10000 weighted avg 0.75 0.75 0.75 10000 precision recall f1-score support Positive 0.75 0.76 0.75 4993 Negative 0.75 0.74 0.75 5007 accuracy 0.75 10000 macro avg 0.75 0.75 0.75 10000 weighted avg 0.75 0.75 0.75 10000
Распечатайте матрицу путаницы
#confusion matrix for bag of words cm_bow=confusion_matrix(test_sentiments,mnb_bow_predict,labels=[1,0]) print(cm_bow) #confusion matrix for tfidf features cm_tfidf=confusion_matrix(test_sentiments,mnb_tfidf_predict,labels=[1,0]) print(cm_tfidf) [[3736 1271] [1219 3774]] [[3729 1278] [1213 3780]]
Давайте посмотрим положительные и отрицательные слова с помощью WordCloud.
Облако слов для слов положительного отзыва
#word cloud for positive review words plt.figure(figsize=(10,10)) positive_text=norm_train_reviews[1] WC=WordCloud(width=1000,height=500,max_words=500,min_font_size=5) positive_words=WC.generate(positive_text) plt.imshow(positive_words,interpolation='bilinear') plt.show
Давайте посмотрим положительные и отрицательные слова с помощью WordCloud.
Облако слов для слов положительного отзыва
#word cloud for positive review words plt.figure(figsize=(10,10)) positive_text=norm_train_reviews[1] WC=WordCloud(width=1000,height=500,max_words=500,min_font_size=5) positive_words=WC.generate(positive_text) plt.imshow(positive_words,interpolation='bilinear') plt.show
Облако слов для отрицательных отзывов
#Word cloud for negative review words plt.figure(figsize=(10,10)) negative_text=norm_train_reviews[8] WC=WordCloud(width=1000,height=500,max_words=500,min_font_size=5) negative_words=WC.generate(negative_text) plt.imshow(negative_words,interpolation='bilinear') plt.show