基于NLP的文本分类异构集成及影评情感分析
1. 文本分类模型构建与评估
在文本分类任务中,我们使用多种算法构建模型,并分别应用于计数数据(Count Data)和TF - IDF数据。具体步骤如下:
1.
导入必要库并读取数据
:导入所需的库,使用UTF8编码读取数据集,检查数据集中垃圾邮件和正常邮件的比例。
2.
文本向量化
:使用
CountVectorizer
和
TfidfVectorizer
模块将文本分别转换为向量和TF - IDF向量。
3.
构建模型
:按照以下顺序构建模型:
- 基于计数数据的朴素贝叶斯模型
- 基于TF - IDF数据的朴素贝叶斯模型
- 基于计数数据的带RBF核的支持向量机(SVM)模型
- 基于TF - IDF数据的带RBF核的支持向量机(SVM)模型
- 基于计数数据的随机森林模型
- 基于TF - IDF数据的随机森林模型
以下是构建模型的详细步骤:
-
朴素贝叶斯模型
:
- 基于计数数据构建模型,使用
classification_report()
检查性能指标,调用
plot_confusion_matrix()
绘制混淆矩阵。
- 基于TF - IDF数据构建模型并评估性能。
-
支持向量机模型
:
- 基于计数数据训练SVM模型(使用RBF核),使用
GridSearchCV
寻找最佳参数,评估性能并绘制混淆矩阵。
- 基于TF - IDF数据重复上述步骤。
-
随机森林模型
:
- 基于计数数据使用网格搜索训练随机森林模型,设置
gini
和
entropy
作为标准超参数,设置多个参数值,如
min_samples_split
、
max_depth
和
min_samples_leaf
,评估模型性能。
- 基于TF - IDF数据训练随机森林模型,使用
predic_proba()
函数获取测试数据的类概率,绘制带有AUC分数注释的ROC曲线,比较模型性能。
- 平均从计数数据和TF - IDF数据模型中得到的概率,绘制集成结果的ROC曲线。
- 绘制每个模型在计数数据和TF - IDF数据上的测试准确率。
# 示例代码:计算预测值的众数进行最大投票
# Using mode on the array, we get the max vote for each observation
predicted_array = mode(predicted_array)
# Check the array
print(predicted_array)
print("The accuracy for test")
accuracy_score(Y_test, predicted_array[0][0])
2. 影评情感分析
情感分析是自然语言处理(NLP)中广泛研究的领域,我们以互联网电影数据库(IMDb)的影评数据为例,将影评分为积极和消极两类。
2.1 数据集准备
我们有1000条积极影评和1000条消极影评,分别存储在
.txt
文件中,分为
positive
和
negative
两个文件夹。具体步骤如下:
1.
导入必要库
:
import os
import glob
import pandas as pd
- 设置工作文件夹 :
os.chdir("/.../Chapter 11/CS - IMDB Classification")
os.getcwd()
- 读取积极影评 :
path="/.../Chapter 11/CS - IMDB Classification/txt_sentoken/pos/*.txt"
files = glob.glob(path)
text_pos = []
for p in files:
file_read = open(p, "r")
to_append_pos = file_read.read()
text_pos.append(to_append_pos)
file_read.close()
df_pos = pd.DataFrame({'text':text_pos,'label':'positive'})
df_pos.head()
- 读取消极影评 :
path="/Users/Dippies/CODE PACKT - EML/Chapter 11/CS - IMDB Classification/txt_sentoken/neg/*.txt"
files = glob.glob(path)
text_neg = []
for n in files:
file_read = open(n, "r")
to_append_neg = file_read.read()
text_neg.append(to_append_neg)
file_read.close()
df_neg = pd.DataFrame({'text':text_neg,'label':'negative'})
df_neg.head()
- 合并数据 :
df_moviereviews=pd.concat([df_pos, df_neg])
- 数据打乱 :
from sklearn.utils import shuffle
df_moviereviews=shuffle(df_moviereviews)
df_moviereviews.head(10)
- 验证数据维度 :
df_moviereviews.shape
- 保存为CSV文件 :
df_moviereviews.to_csv("/.../Chapter 11/CS - IMDB Classification/Data_IMDB.csv")
- 查看正负影评比例 :
df_moviereviews["label"].value_counts().plot(kind='pie')
plt.tight_layout(pad=1,rect=(0, 0, 0.7, 1))
plt.text(x=-0.9,y=0.1, s=(np.round(((df_moviereviews["label"].value_counts()[0])/(df_moviereviews["label"].value_counts()[0] + df_moviereviews["label"].value_counts()[1])),2)))
plt.text(x=0.4,y=-0.3, s=(np.round(((df_moviereviews["label"].value_counts()[1])/(df_moviereviews["label"].value_counts()[0] + df_moviereviews["label"].value_counts()[1])),2)))
plt.title("% Share of the Positive and Negative reviews in the dataset")
-
标签替换
:将
positive标签替换为1,negative标签替换为0。
df_moviereviews.loc[df_moviereviews["label"]=='positive',"label"]=1
df_moviereviews.loc[df_moviereviews["label"]=='negative',"label"]=0
-
数据预处理
:
- 转换所有文本为小写
- 去除标点符号
- 去除停用词
- 词干提取
- 分词
import string
from nltk.corpus import stopwords
from nltk.stem import WordNetLemmatizer
lemmatizer = WordNetLemmatizer()
def process_text(text):
nopunc = [char for char in text if char not in string.punctuation]
nopunc = ''.join(nopunc)
clean_words = [word.lower() for word in nopunc.split() if word.lower() not in stopwords.words('english')]
clean_words = [lemmatizer.lemmatize(lem) for lem in clean_words]
clean_words = " ".join(clean_words)
return clean_words
df_moviereviews['text'] = df_moviereviews['text'].apply(process_text)
3. 构建基础学习器并评估集成结果
3.1 导入剩余库
import os
import numpy as np
import pandas as pd
import itertools
import warnings
import string
import matplotlib.pyplot as plt
from nltk.corpus import stopwords
from nltk.stem import WordNetLemmatizer
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import confusion_matrix
from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report
from sklearn.metrics import roc_auc_score as auc
from sklearn.metrics import roc_curve
from sklearn.metrics import accuracy_score
from scipy.stats import mode
3.2 分离目标变量和预测变量
X = df_moviereviews.loc[:,'text']
Y = df_moviereviews.loc[:,'label']
Y = Y.astype('int')
3.3 数据划分
X_train,X_test,y_train,y_test = train_test_split(X, Y, test_size=.3, random_state=1)
3.4 文本向量化
count_vectorizer = CountVectorizer()
count_train = count_vectorizer.fit_transform(X_train)
count_test = count_vectorizer.transform(X_test)
tfidf = TfidfVectorizer()
tfidf_train = tfidf.fit_transform(X_train)
tfidf_test = tfidf.transform(X_test)
3.5 训练基础学习器
- 随机森林模型(计数数据) :
rf_params = {"criterion":["gini","entropy"],
"min_samples_split":[2,3],
"max_depth":[None,2,3],
"min_samples_leaf":[1,5],
"max_leaf_nodes":[None],
"oob_score":[True]}
rf = RandomForestClassifier()
warnings.filterwarnings("ignore")
rf_count = GridSearchCV(rf, rf_params, cv=5)
rf_count.fit(count_train, y_train)
rf_count_predicted_values = rf_count.predict(count_test)
rf_count_probabilities = rf_count.predict_proba(count_test)
rf_count_train_accuracy = rf_count.score(count_train, y_train)
rf_count_test_accuracy = rf_count.score(count_test, y_test)
print('The accuracy for the training data is {}'.format(rf_count_train_accuracy))
print('The accuracy for the testing data is {}'.format(rf_count_test_accuracy))
- 随机森林模型(TF - IDF数据) :
rf_params = {"criterion":["gini","entropy"],"min_samples_split":[2,3],"max_depth":[None,2,3],"min_samples_leaf":[1,5],"max_leaf_nodes":[None],"oob_score":[True]}
rf = RandomForestClassifier()
warnings.filterwarnings("ignore")
rf_tfidf = GridSearchCV(rf, rf_params, cv=5)
rf_tfidf.fit(tfidf_train, y_train)
rf_tfidf_predicted_values = rf_tfidf.predict(tfidf_test)
rf_tfidf_probabilities = rf_tfidf.predict_proba(tfidf_test)
rf_train_accuracy = rf_tfidf.score(tfidf_train, y_train)
rf_test_accuracy = rf_tfidf.score(tfidf_test, y_test)
print('The accuracy for the training data is {}'.format(rf_train_accuracy))
print('The accuracy for the testing data is {}'.format(rf_test_accuracy))
- 朴素贝叶斯模型(计数数据) :
nb_count = MultinomialNB()
nb_count.fit(count_train, y_train)
nb_count_predicted_values = nb_count.predict(count_test)
nb_count_probabilities = nb_count.predict_proba(count_test)
nb_train_accuracy = nb_count.score(count_train, y_train)
nb_test_accuracy = nb_count.score(count_test, y_test)
print('The accuracy for the training data is {}'.format(nb_train_accuracy))
print('The accuracy for the testing data is {}'.format(nb_test_accuracy))
- 朴素贝叶斯模型(TF - IDF数据) :
nb_tfidf = MultinomialNB()
nb_tfidf.fit(tfidf_train, y_train)
nb_tfidf_predicted_values = nb_tfidf.predict(tfidf_test)
nb_tfidf_probabilities = nb_tfidf.predict_proba(tfidf_test)
nb_train_accuracy = nb_tfidf.score(tfidf_train, y_train)
nb_test_accuracy = nb_tfidf.score(tfidf_test, y_test)
print('The accuracy for the training data is {}'.format(nb_train_accuracy))
print('The accuracy for the testing data is {}'.format(nb_test_accuracy))
- 支持向量机模型(计数数据) :
from sklearn.svm import SVC
svc_count = SVC(kernel='linear',probability=True)
svc_params = {'C':[0.001, 0.01, 0.1, 1, 10]}
svc_gcv_count = GridSearchCV(svc_count, svc_params, cv=5)
svc_gcv_count.fit(count_train, y_train)
svc_count_predicted_values = svc_gcv_count.predict(count_test)
svc_count_probabilities = svc_gcv_count.predict_proba(count_test)
svc_count_train_accuracy = svc_gcv_count.score(count_train, y_train)
svc_count_test_accuracy = svc_gcv_count.score(count_test, y_test)
print('The accuracy for the training data is {}'.format(svc_count_train_accuracy))
print('The accuracy for the testing data is {}'.format(svc_count_test_accuracy))
- 支持向量机模型(TF - IDF数据) :
svc_tfidf = SVC(kernel='linear',probability=True)
svc_params = {'C':[0.001, 0.01, 0.1, 1, 10]}
svc_gcv_tfidf = GridSearchCV(svc_tfidf, svc_params, cv=5)
svc_gcv_tfidf.fit(tfidf_train, y_train)
svc_tfidf_predicted_values = svc_gcv_tfidf.predict(tfidf_test)
svc_tfidf_probabilities = svc_gcv_tfidf.predict_proba(tfidf_test)
svc_tfidf_train_accuracy = svc_gcv_tfidf.score(tfidf_train, y_train)
svc_tfidf_test_accuracy = svc_gcv_tfidf.score(tfidf_test, y_test)
print('The accuracy for the training data is {}'.format(svc_tfidf_train_accuracy))
print('The accuracy for the testing data is {}'.format(svc_tfidf_test_accuracy))
3.6 绘制ROC曲线
fpr, tpr, thresholds = roc_curve(y_test, rf_count_probabilities[:,1])
roc_auc = auc(y_test, rf_count_probabilities[:,1])
plt.title('ROC Random Forest Count Data')
plt.plot(fpr, tpr, 'b',label='AUC = %0.3f'% roc_auc)
plt.legend(loc='lower right')
plt.plot([0,1],[0,1],'r--')
plt.xlim([-0.1,1.0])
plt.ylim([-0.1,1.01])
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
3.7 集成结果处理
predicted_values_count = np.array([rf_count_predicted_values,
nb_count_predicted_values,
svc_count_predicted_values])
predicted_values_tfidf = np.array([rf_tfidf_predicted_values,
nb_tfidf_predicted_values,
svc_tfidf_predicted_values])
predicted_values_count = mode(predicted_values_count)
predicted_values_tfidf = mode(predicted_values_tfidf)
3.8 绘制测试准确率
count = np.array([rf_count_test_accuracy,
nb_count_test_accuracy,
svc_count_test_accuracy,
accuracy_score(y_test, predicted_values_count[0][0])])
tfidf = np.array([rf_tfidf_test_accuracy,
nb_tfidf_test_accuracy,
svc_tfidf_test_accuracy,
accuracy_score(y_test, predicted_values_tfidf[0][0])])
label_list = ["Random Forest", "Naive_Bayes", "SVM_Linear", "Ensemble"]
plt.plot(count)
plt.plot(tfidf)
plt.xticks([0,1,2,3],label_list)
for i in range(4):
plt.text(x=i,y=(count[i]+0.001), s=np.round(count[i],4))
for i in range(4):
plt.text(x=i,y=tfidf[i]-0.003, s=np.round(tfidf[i],4))
plt.legend(["Count","TFIDF"])
plt.title("Test accuracy")
plt.tight_layout(pad=1,rect=(0, 0, 2.5, 2))
plt.show()
通过以上步骤,我们完成了文本分类和影评情感分析的任务,使用多种模型和集成方法提高了分类的准确性。
总结
本文详细介绍了基于NLP的文本分类异构集成方法以及影评情感分析的具体实现步骤。通过构建多种模型并应用于计数数据和TF - IDF数据,我们能够更全面地评估模型性能。同时,在影评情感分析中,我们从数据集准备到模型训练和评估,展示了一个完整的NLP项目流程。这些方法和步骤可以为相关领域的研究和实践提供有价值的参考。
流程图
graph LR
A[导入必要库] --> B[读取数据集]
B --> C[文本向量化]
C --> D[构建模型]
D --> E[训练模型]
E --> F[评估模型]
F --> G[绘制ROC曲线]
G --> H[集成结果处理]
H --> I[绘制测试准确率]
表格:模型构建顺序
| 序号 | 模型 | 数据类型 |
|---|---|---|
| 1 | 朴素贝叶斯 | 计数数据 |
| 2 | 朴素贝叶斯 | TF - IDF数据 |
| 3 | 支持向量机(RBF核) | 计数数据 |
| 4 | 支持向量机(RBF核) | TF - IDF数据 |
| 5 | 随机森林 | 计数数据 |
| 6 | 随机森林 | TF - IDF数据 |
基于NLP的文本分类异构集成及影评情感分析
4. 模型评估指标分析
在训练和评估模型的过程中,我们使用了多种评估指标来衡量模型的性能,这些指标能够从不同角度反映模型的优劣。以下是对主要评估指标的详细分析:
-
准确率(Accuracy)
:准确率是分类模型中最常用的指标之一,它表示模型正确预测的样本数占总样本数的比例。在我们的实验中,通过
score()
方法计算训练集和测试集的准确率,例如随机森林模型在计数数据上的训练准确率和测试准确率分别通过
rf_count.score(count_train, y_train)
和
rf_count.score(count_test, y_test)
计算得到。
-
精确率(Precision)、召回率(Recall)和F1分数(F1 - score)
:这些指标可以通过
classification_report()
函数输出。精确率是指模型预测为正类的样本中实际为正类的比例;召回率是指实际为正类的样本中被模型正确预测为正类的比例;F1分数是精确率和召回率的调和平均数,它综合考虑了精确率和召回率。
-
AUC - ROC曲线
:ROC曲线(Receiver Operating Characteristic Curve)以假正率(False Positive Rate)为横轴,真正率(True Positive Rate)为纵轴,展示了模型在不同阈值下的性能表现。AUC(Area Under the Curve)是ROC曲线下的面积,它衡量了模型的整体性能,AUC值越接近1,说明模型的性能越好。在我们的实验中,通过
roc_curve()
和
auc()
函数绘制ROC曲线并计算AUC值,例如随机森林模型在计数数据上的ROC曲线和AUC值的计算代码如下:
fpr, tpr, thresholds = roc_curve(y_test, rf_count_probabilities[:,1])
roc_auc = auc(y_test, rf_count_probabilities[:,1])
plt.title('ROC Random Forest Count Data')
plt.plot(fpr, tpr, 'b',label='AUC = %0.3f'% roc_auc)
plt.legend(loc='lower right')
plt.plot([0,1],[0,1],'r--')
plt.xlim([-0.1,1.0])
plt.ylim([-0.1,1.01])
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
5. 集成方法的优势
在本实验中,我们使用了集成方法来提高模型的性能。集成方法通过组合多个基础学习器的预测结果,能够减少单个模型的偏差和方差,从而提高整体的预测准确率。具体来说,我们使用了最大投票法(Max - Voting)来集成多个模型的预测结果,步骤如下:
1. 收集各个基础学习器在测试集上的预测结果,例如随机森林、朴素贝叶斯和支持向量机模型在计数数据和TF - IDF数据上的预测结果。
2. 对每个样本的预测结果进行最大投票,即选择出现次数最多的类别作为最终的预测类别。代码如下:
predicted_values_count = np.array([rf_count_predicted_values,
nb_count_predicted_values,
svc_count_predicted_values])
predicted_values_tfidf = np.array([rf_tfidf_predicted_values,
nb_tfidf_predicted_values,
svc_tfidf_predicted_values])
predicted_values_count = mode(predicted_values_count)
predicted_values_tfidf = mode(predicted_values_tfidf)
-
计算集成结果的准确率,通过
accuracy_score()函数比较集成预测结果和真实标签,例如:
accuracy_count = accuracy_score(y_test, predicted_values_count[0][0])
accuracy_tfidf = accuracy_score(y_test, predicted_values_tfidf[0][0])
通过集成方法,我们可以综合多个模型的优势,提高模型在不同数据集上的泛化能力和预测准确性。
6. 数据预处理的重要性
在自然语言处理任务中,数据预处理是非常重要的一步,它能够提高数据的质量,减少噪声的干扰,从而提高模型的性能。在我们的影评情感分析任务中,数据预处理包括以下几个步骤:
1.
转换为小写
:将所有文本转换为小写,这样可以避免大小写对模型的影响,例如将
"Great Movie!"
转换为
"great movie!"
。
2.
去除标点符号
:标点符号在文本分类任务中通常没有实际的语义信息,去除标点符号可以减少数据的维度,例如将
"This is a great movie!"
转换为
"This is a great movie"
。
3.
去除停用词
:停用词是指在文本中频繁出现但没有实际语义信息的词语,如
"the"
、
"is"
、
"a"
等。去除停用词可以减少数据的噪声,提高模型的训练效率,例如将
"This is a great movie"
转换为
"great movie"
。
4.
词干提取
:词干提取是将词语还原为其词干形式,例如将
"running"
、
"runs"
还原为
"run"
,这样可以减少词汇的多样性,提高模型的泛化能力。
5.
分词
:将文本分割成单个的词语,例如将
"great movie"
分割为
["great", "movie"]
,方便后续的特征提取和模型训练。
以下是实现数据预处理的代码:
import string
from nltk.corpus import stopwords
from nltk.stem import WordNetLemmatizer
lemmatizer = WordNetLemmatizer()
def process_text(text):
nopunc = [char for char in text if char not in string.punctuation]
nopunc = ''.join(nopunc)
clean_words = [word.lower() for word in nopunc.split() if word.lower() not in stopwords.words('english')]
clean_words = [lemmatizer.lemmatize(lem) for lem in clean_words]
clean_words = " ".join(clean_words)
return clean_words
df_moviereviews['text'] = df_moviereviews['text'].apply(process_text)
通过这些预处理步骤,我们可以提高数据的质量,从而提高模型的性能。
7. 模型选择与参数调优
在本实验中,我们使用了多种模型进行文本分类和情感分析,包括随机森林、朴素贝叶斯和支持向量机。不同的模型具有不同的特点和适用场景,因此在实际应用中需要根据具体情况选择合适的模型。
-
随机森林(Random Forest)
:随机森林是一种集成学习方法,它通过组合多个决策树来提高模型的性能。随机森林具有较好的泛化能力和抗过拟合能力,适用于处理高维数据和复杂的分类问题。在本实验中,我们使用
GridSearchCV
进行参数调优,通过设置不同的参数组合,如
criterion
、
min_samples_split
、
max_depth
等,找到最优的参数组合。
-
朴素贝叶斯(Naive Bayes)
:朴素贝叶斯是一种基于贝叶斯定理的分类算法,它假设特征之间相互独立。朴素贝叶斯算法具有计算简单、训练速度快的优点,适用于文本分类任务。在本实验中,我们使用
MultinomialNB
进行文本分类,它适用于处理离散特征。
-
支持向量机(Support Vector Machine)
:支持向量机是一种强大的分类算法,它通过寻找最优的超平面来划分不同的类别。支持向量机在处理高维数据和非线性分类问题时具有较好的性能。在本实验中,我们使用
SVC
并设置线性核,通过
GridSearchCV
对
C
参数进行调优,找到最优的参数值。
通过模型选择和参数调优,我们可以提高模型的性能,使其更好地适应不同的数据集和任务。
流程图
graph LR
A[数据预处理] --> B[特征提取]
B --> C[模型选择]
C --> D[参数调优]
D --> E[模型训练]
E --> F[模型评估]
F --> G{是否满足要求}
G -- 是 --> H[集成方法]
G -- 否 --> D
H --> I[最终结果]
表格:不同模型的特点和适用场景
| 模型 | 特点 | 适用场景 |
|---|---|---|
| 随机森林 | 泛化能力强,抗过拟合,可处理高维数据 | 复杂分类问题,数据维度高 |
| 朴素贝叶斯 | 计算简单,训练速度快 | 文本分类,特征独立假设 |
| 支持向量机 | 处理高维数据和非线性分类问题能力强 | 数据维度高,非线性分类 |
总结
本文全面介绍了基于NLP的文本分类异构集成方法以及影评情感分析的完整流程。从数据预处理到模型选择、参数调优,再到集成方法的应用,我们详细阐述了每个步骤的重要性和具体实现方法。通过使用多种评估指标对模型进行评估,我们能够更全面地了解模型的性能。实验结果表明,集成方法和数据预处理能够显著提高模型的泛化能力和预测准确性。这些方法和技术可以为自然语言处理领域的相关研究和实践提供有价值的参考,帮助我们更好地处理文本分类和情感分析任务。
超级会员免费看
1889

被折叠的 条评论
为什么被折叠?



