爱数课实验 | 第五期-基于机器学习方法的商品评论情感判定

2022-06-27 18:21:05 浏览数 (3)

爱数课:idatacourse.cn

领域:消费

简介:商品评论可以帮助购买用户更加了解产品,做出更优的购买决策,也可以帮助商家获知商品的优缺点,获取消费者的喜好。本次实验我们将学习中文商品情感判定,通过构建高斯朴素贝叶斯模型和SVM模型和对商品评论进行分类。

数据:

./dataset/data.csv

./dataset/stopwords.txt

目录

任何行业,用户对产品的评价都显得尤为重要。用户在电商平台上面发表的产品评价中包含着用户的偏好信息,所以通过用户评论,可以得到用户的情感倾向以及对产品属性的偏好。

互联网的发展极大提高了每个人的参与度,人们可以通过网络购物或点外卖。在购买商品时,也会着重考虑其他用户的评价。对于用户来说,参考评论能够更全面的去了解商品,做出更优的购买决策;对于商家来说,通过用户的评论可以获知商品优缺点,进一步改良产品;对购物平台而言,通过分析用户评论可以进一步利用智能推荐系统向用户推荐他们更喜欢的产品,以增加用户的黏性,挖掘一些潜在的利润。

下图为某电商平台上针对某款手机的评论:

代码语言:javascript复制
# 载入必要库
import jieba
import numpy as np
import pandas as pd
import sklearn
import matplotlib
import matplotlib.pyplot as plt 
import pyecharts.options as opts
from pyecharts.charts import WordCloud
from pyecharts.charts import Bar
import re
#logging
import warnings
warnings.filterwarnings('ignore')

1. 数据读取

1.1 读取数据

某款手机的商品评论信息数据集,包含2个字段,共计8186个样本。数据集描述如下:

列名

说明

类型

示例

Comment

对该款手机的评论

String

客服特别不负责,明明备注了也不看,发错了东西。

Class

该评论的情感倾向: -1 ------ 差评 0 ------ 中评 1 ------ 好评

Int

-1

本实验所用数据集可在爱数科平台下载:http://idatascience.cn/dataset-detail?table_id=100936

使用Pandas库中的read_csv函数读取csv格式的数据集文件,结果会保存为一个DataFrame或Series对象,使用DataFrame或Series对象的head()方法查看前n行数据,默认为5。查看数据可以了解各个字段取值的具体情况,字段的名称等等,对数据有一个基础的了解。

代码语言:javascript复制
#读入数据集
data = pd.read_csv('./dataset/data.csv')
data.head(10)

1.2 查看数据基本信息

使用shape()方法查看数据集的行数及列数,了解数据集的大小。使用info()方法打印DataFrame对象的摘要,包括列的数据类型dtype、名称以及有无缺失值,占用的内存等信息。

代码语言:javascript复制
# 数据集的大小
data.shape

(8186, 2)

代码语言:javascript复制
# 数据集的基本信息
data.info()

数据集大小为8186行,2列。从数据集的基本信息可以看到Comment列有缺失值,但缺失数量极少。在后续进行数据预处理时,需要考虑对缺失值进行删除。

2. 数据预处理

在中文文本分析和情感分析的工作中,数据预处理的内容主要是分词,去除停用词。英文分词比较简单,见到空格和标点符号就说明是一个词汇,而中文分词就是将一句话拆分成一些词语,在Python中有专门的中文分词库jieba库,使用jieba库的cut()函数对指定的文本内容进行分词。

2.1 去除缺失值

代码语言:javascript复制
# 移除含有缺失值的行
data.dropna(axis=0,inplace=True)
代码语言:javascript复制
#查看去除缺失值后的行和列
data.shape

(8185, 2)

2.2 分词

首先,我们去除Comment列文本中的标点符号、数字、字母。然后通过jieba库,对文本进行中文分词。只有经过分词处理后的文本数据集才可以进行下一步的向量化操作,满足输入模型的条件。

代码语言:javascript复制
def remove_url(src):
    # 去除标点符号、数字、字母
    vTEXT = re.sub('[a-zA-Z0-9’!"#$%&'()* ,-./:;<=>?@,。?★、…【】╮  ̄ ▽  ̄ ╭\~⊙%;①():《》?“”‘’![\]^_`{|}~s] ', "", src)
    return vTEXT
代码语言:javascript复制

cutted = []
for row in data.values:
        text = remove_url(str(row[0])) #去除文本中的标点符号、数字、字母
        raw_words = (' '.join(jieba.cut(text)))#分词,并用空格进行分隔
        cutted.append(raw_words)

cutted_array = np.array(cutted)

# 生成新数据文件,Comment字段为分词后的内容
data_cutted = pd.DataFrame({
    'Comment': cutted_array,
    'Class': data['Class']
})
代码语言:javascript复制
data_cutted.head()#查看分词后的数据集

data_cutted为进行分词之后的数据集,可以看到每条评论已经进行了分词。

2.3 查看关键词

此步骤我们先读取停用词文件,查看前100个停用词。其次使用jieba.analyse中的set_stop_words函数设置停用词。使用jieba.analyse中的extract_tags函数,提取句子中的关键词,显示好评、中评、差评中前30个关键词,可以帮助我们对各类评论有更好的理解,更直观的显示各类评论用户的情感倾向。

代码语言:javascript复制
with open('./dataset/stopwords.txt', 'r', encoding='utf-8') as f:#读停用词表
    stopwords = [item.strip() for item in f] #通过列表推导式的方式获取所有停用词
    
for i in stopwords[:100]:#读前100个停用词
    print(i,end='')
代码语言:javascript复制
#设定停用词文件,在统计关键词的时候,过滤停用词
import jieba.analyse
jieba.analyse.set_stop_words('./dataset/stopwords.txt')

设置停用词之后,分别提取各类评论的关键词。

代码语言:javascript复制
data_cutted['Comment'][data_cutted['Class'] == 1]
代码语言:javascript复制
# 好评关键词
keywords_pos = jieba.analyse.extract_tags(''.join(data_cutted['Comment'][data_cutted['Class'] == 1]),withWeight = True,topK=30)
for item in keywords_pos:
    print(item[0],end=' ')

#中评关键词 keywords_med = jieba.analyse.extract_tags(''.join(data_cutted['Comment'][data_cutted['Class'] == 0]),withWeight = True,topK=30) for item in keywords_med: print(item[0],end=' ')

代码语言:javascript复制
#差评关键词
keywords_neg = jieba.analyse.extract_tags(''.join(data_cutted['Comment'][data_cutted['Class'] == -1]),withWeight = True,topK=30)

for item in keywords_neg:
    print (item[0],end=' ')

3. 可视化分析

在本环节中,我们将通过Python中的绘图库Pyecharts,利用一系列可视化的手段,通过绘制柱状图的方式展示各类评论的取值分布,通过绘制词云图的方式展示好评、中评、差评的关键词。

3.1 好评、中评、差评数量柱状图

代码语言:javascript复制
data_cutted['Class'].value_counts()
代码语言:javascript复制

# 不同类别数据记录的统计
x_label = ['好评','差评','中评']
class_num = (
    Bar()
    #设置x轴的值
    .add_xaxis(x_label) 
    #设置y轴数据
    .add_yaxis("",data_cutted['Class'].value_counts().to_list(),color=['#4c8dae'])
    #设置title
    .set_global_opts(title_opts=opts.TitleOpts(title="好评、中评、差评数量柱状图"))
)
class_num.render_notebook()

从柱状图可以看出好评,共3042人,差评,共2657人,中评,共2486人。好评人数最多,中评人数最少。数据集中好评、中评、差评的人数相差并不大,取值分布较为均衡。

3.2 好评关键词词云图

对好评中的关键词通过绘制词云图的方式进行展示,查看好评用户对商品的评价。

代码语言:javascript复制
wordcloud_pos = (
        WordCloud()
        #data_pair:要绘制词云图的数据
        .add(series_name="", data_pair=keywords_pos[:], word_size_range=[10, 66])
        .set_global_opts(
            title_opts=opts.TitleOpts(
                #设置词云图标题和标题字号
                title="好评关键词词云图", title_textstyle_opts=opts.TextStyleOpts(font_size=23)
            ),
            tooltip_opts=opts.TooltipOpts(is_show=True))     
)
wordcloud_pos.render_notebook()

好评用户指出商品是正品、有赠品、很漂亮、手机运行流畅、快递速度较快等。总体来说好评用户感觉商品不错,对商品很满意,很喜欢。其中好评用户最常提到的是感觉商品不错和商品是正品。

3.3 中评关键词词云图

代码语言:javascript复制
wordcloud_med = (
        WordCloud()
        #data_pair:要绘制词云图的数据
        .add(series_name="", data_pair=keywords_med[:], word_size_range=[10, 66])
        .set_global_opts(
            title_opts=opts.TitleOpts(
            #设置词云图标题和标题字号
            title="中评关键词词云图", title_textstyle_opts=opts.TextStyleOpts(font_size=23)
            ),
            tooltip_opts=opts.TooltipOpts(is_show=True))     
)
wordcloud_med.render_notebook()

总体来说中评用户对商品的评价有好有坏,觉得商品不错,但同时指出商品存在发热等问题。

3.4 差评关键词词云图

代码语言:javascript复制
wordcloud_neg = (
        WordCloud()
        #data_pair:要绘制词云图的数据
        .add(series_name="", data_pair=keywords_neg[:], word_size_range=[10, 66])
        .set_global_opts(
            title_opts=opts.TitleOpts(
                #设置词云图标题和标题字号
                title="差评关键词词云图", title_textstyle_opts=opts.TextStyleOpts(font_size=23)
            ),
            tooltip_opts=opts.TooltipOpts(is_show=True))     
)
wordcloud_neg.render_notebook()

差评用户对商品售后服务,以及退换货服务等感到不满意。同时也提到了充电等问题。

通过分析用户的评论,我们可以发现,对于网购来说,商品本身的质量是非常关键的,对于手机来说人们关注手机的发热问题、流畅性、以及充电问题等,但同时售后服务,快递速度等也是人们关心的重要问题。

4. 文本向量化

经过分词之后的文本数据集要先进行向量化之后才能输入到分类模型中进行运算。TF-IDF算法是常用的文本向量化算法。

TF-IDFTerm Frequency-Inverse Document Frequency的缩写,即“词频-逆文本频率”。它由两部分组成,TFIDFTF-IDF是一种统计方法,用以评估一个词对于一个文件集或一个语料库中的一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。

text{词频(TF)}=frac{某个词在文章中的出现次数}{文章总词数}
text{逆文档频率(IDF)}=text{log}(frac{文章总数}{包含该词的文章数 1})

(分母加1,为了避免分母为0)

text{TF-IDF}=text{TF}*text{IDF}

我们使用sklearn库中的TfidfVectorizer实现tf-idf文本向量化。

代码语言:javascript复制
# 实现向量化方法
from sklearn.feature_extraction.text import TfidfVectorizer

vectorizer = TfidfVectorizer(stop_words = stopwords,max_df=2000,min_df=6)

#将文本向量化后的数据赋给data_transform
data_transform = vectorizer.fit_transform(data_cutted['Comment'].values.tolist()) 
代码语言:javascript复制
#文本的词汇表
vectorizer.get_feature_names()
代码语言:javascript复制
#调用toarray()方法查看文本向量化后的数据
data_transform.toarray()
代码语言:javascript复制
data_transform.shape

(8185, 2029)

5. 高斯朴素贝叶斯模型

5.1 数据集划分

使用sklearn.model_selection模块的train_test_split()函数划分训练集和测试集。训练集:80%;测试集:20%。训练集用于训练模型,测试集用于评估模型性能。

代码语言:javascript复制
from sklearn.model_selection import train_test_split #数据集划分

X_train, X_test, y_train, y_test = train_test_split(data_transform, data_cutted['Class'], 
                                                   random_state=10,test_size=0.2)

5.2 构建高斯朴素贝叶斯模型

sklearn.naive_bayes中导入GaussianNB类,使用GaussianNB类初始化一个模型对象,命名为gnb,对gnb调用fit方法,带入训练集X_train,y_train进行训练。

代码语言:javascript复制
from sklearn.naive_bayes import GaussianNB
代码语言:javascript复制
gnb = GaussianNB()
gnb_model = gnb.fit(X_train.toarray(),y_train)

5.3 高斯朴素贝叶斯模型评估

训练高斯朴素贝叶斯模型后,可以使用模型在测试集X_test上作出预测。从sklearn.metrics中导入classification_report分类报告用于模型评估,可以通过分类报告查看模型对于各类别的分类精确率、召回率、f1-score等。

代码语言:javascript复制
from sklearn.metrics import classification_report
代码语言:javascript复制
gnb_prelabel = gnb_model.predict(X_test.toarray())

print(classification_report(y_true=y_test,y_pred=gnb_prelabel))
text{Accuracy} = frac{text{TP} text{TN}}{text{TP} text{FP} text{TN} text{FN}}
text{Precision} = frac{text{TP}}{text{TP} text{FP}}

,全部预测为正类的样本中被预测正确的比例

text{Recall}= frac{text{TP}}{text{TP} text{FN}}

,实际为正类的样本中被预测正确的比例

从分类报告来看,差评的精确率为0.67,召回率为0.48,中评的精确率为0.52,召回率为0.39。好评的精确率为0.62,召回率为0.90。模型最终的准确率为0.61。

6. SVM模型构建

6.1 构建SVM模型

sklearn.svm中导入SVC类,使用SVC类初始化一个模型对象,命名为svc,对svc调用fit方法,带入训练集X_trainy_train进行训练。

代码语言:javascript复制
from sklearn.svm import SVC

#设置kernel为‘rbf’高斯核,C=1
svc = SVC(kernel='rbf', C=1)
svc_model = svc.fit(X_train,y_train) 

训练模型后,可以使用模型在测试集X_test上作出预测。通过分类报告查看模型对于各类别的分类精确率、召回率、f1-score等。

6.2 SVM模型评估

代码语言:javascript复制
svc_prelabel = svc_model.predict(X_test)
print(classification_report(y_true=y_test,y_pred=svc_prelabel))

从分类报告来看,差评的精确率为0.71,召回率为0.74,中评的精确率为0.62,召回率为0.57。好评的精确率为0.85,召回率为0.86。模型最终的准确率为0.74。从分类报告可以看出对于中评的分类效果较差。是由于人在评论时,除非有问题否则一般都会打好评,如果打了中评说明对产品有不满意之处,在情感的表达上就会趋向于负向情感,同时评论具有很大主观性,很多中评会将其归为差评,但数据集中却认为是中评。因此,将一条评论分类为好评、中评、差评是不够客观,中评与差评之间的边界很模糊,因此识别率较低。

通过将SVM模型与构建的高斯朴素贝叶斯模型分类结果比较,可以看出SVM在分类的精确率、召回率,以及模型的准确率上都优于高斯朴素贝叶斯模型。因此情感分析更推荐SVM模型。

爱数课(iDataCourse)是一个面向院校的大数据和人工智能课程和资源平台。平台提供权威的课程资源、数据资源、案例实验资源,助力院校大数据和人工智能专业建设,课程建设和师资能力建设。

1 人点赞