一.背景
随着电商平台的蓬勃发展,用户数量逐渐增多,使得商品评价数目飙升。如何能高效、精确获得基于这些语料的相关信息,在此基础上进行分析研究逐渐成为了当前信息科学和技术领域中面临到的重大挑战。本文基于一份电商数据的评论数据,首先进行数据预处理:对其进行分词,去重,去除停用词操作;然后进行情感分析。
二.分析方法和过程
数据:爬取的京东热水器商品评论数据2000条。
分析步骤如下: 1.对评论文本数据进行预处理:文本去重、文本清洗、分词、去除停用词;词云绘制; 2.对预处理后的数据进行情感分析:将评论文本按照情感倾向分为正向评论数据、负面评论数据; 3.对于情感分类得到的正负样本,基于词云图,得到产品的闪光点和问题点。热水器的好评,有哪些方面;用户评论“坏”,究竟是哪一方面坏。
三.数据预处理
3.1去重复
根据中文语言的特点,不同购买者之间有价值的评论不会完全重复的,当评论重复出现次数太多,会对模型产生过多偏重。因此,尽可能避免这种影响的办法,就是先对数据进行去重处理。
import pandas as pd
import re
import jieba.posseg as psg
import numpy as np
reviews = pd.read_csv("data/reviews.csv")
reviews.head()
reviews_n = reviews.copy()
#去重
reviews_n[["content","content_type"]].drop_duplicates()
content = reviews_n["content"]
3.2数据清洗
通过观察数据发现,评论中夹杂许多数字、字母,这些内容并没有研究意义。另外,该数据来源于京东热水器的评论,“京东”,“京东商城”,“热水器”,“美的”,“电热水器”等词汇对分析目标没有作用。因此,需要在数据清洗中删除这些文本词汇。
# 去除去除英文、数字等
# 由于评论主要为京东美的电热水器的评论,因此去除这些词语
str_info = re.compile('[0-9a-zA-Z]|京东|美的|电热水器|热水器|')
content = content.apply(lambda x:str_info.sub('',x))
3.3 中文分词
自然语言处理领域,中文分词比较特殊,要结合词与词之间联系,目前的中文分词运用到的算法有词典法、统计法和文本挖掘相关理论与技术器学习等方法。本文采用python库中的jieba分词包,它是开源分词库,专门用于中文分词,其采用了三条基本原理:
a.基于trie树结构实现高效的词图扫描,生成句子中汉字所有可能成词的情况所构成的有向无环图。jieba分词自带了一个dict.text的词典,里面两万多条词,包含了词条出现的次数和词性(基于人民日报语料库训练所得)。
b.采用动态规划查找最大概率路径,找出基于词频的最大切分组合。先查找待分词句子中已经切分好的词语,再查找该词出现的频率,然后根据动态规划查找最大概率路径的方法,找到最大概率的切分组和。
c.对于未登录词汇,将中文词汇按照BEMS等四个状态标记。B代表begin,表示开始位置,E代表end,表示结束位置,M代表middle,表示中间位置,S代表single,表示单独成词的位置。
jieba库的安装,需要在cmd 中,pip install jieba。****
#分词
worker = lambda s: [(x.word, x.flag) for x in psg.cut(s)] # 自定义简单分词函数
seg_word = content.apply(worker)
切分后的评论内容如下:
3.4构建分词后的数据框
希望构建一个数据框的列为:所切分的词汇,词所在评论的id(reviews_n表),词语在该句子的位置,词性,词所在评论的内容类型(reviews_n表);
a.先看seg_word表中,每条评论词的个数;
b. 将嵌套的列表展开,作为词所在评论的id(来源于reviews_n的行,也是seg_word表的行标签加1);
n_content = [[x+1]*y for x,y in zip(list(seg_word.index), list(n_word))]
index_content = sum(n_content, []) # 将嵌套的列表展开,作为词所在评论的id
index_content
c.同理,需要得出单个词汇所在reviews_n表的content_type是积极还是消极;
content_type = [[x]*y for x,y in zip(list(reviews['content_type']), list(n_word))]
content_type = sum(content_type, []) # 评论类型
d.将seg_word表展开,单独的词作为一行;并将词语与词性分开;
e.构建目标数据框
3.5 删除标点符号,停用词;
jieba 关于词典的词性标记,采用 ICTCLAS 汉语词性标注集 ,其中,常见的有a表示形容词,d表示副词,n表示名词,p表示介词,v表示动词,x表示未知数、符号等。
a.观察数据,先将词性是标点符号的删除;result = result[result['nature'] != 'x']
b.删除停用词
停用词是指在信息检索中,为节省存储空间和提高搜索效率,在处理自然语言数据(或文本)之前或之后会自动过滤掉某些字或词,这些停用词都是人工输入、非自动化生成的,生成后的停用词会形成一个停用词表。
通常意义上,Stop Words大致为如下两类:1、应用十分广泛,在Internet上随处可见的词,比如“Web”一词,对这样的词搜索引擎无 法保证能够给出真正相关的搜索结果,难以帮助缩小搜索范围,同时还会降低搜索的效率;2、包括语气助词、副词、介词、连接词等,通常自身 并无明确的意义,只有将其放入一个完整的句子中才有一定作用,如常见的“的”、“在”之类。
在上一步构建的result数据框中,word这一列明显含有停用词。因此需要根据现有的停用词表stoplist.txt,将word这列词汇中的停用词删除。
上面已经定义过word = [x[0] for x in seg_word],在此处理
3.6 构建各词在在对应评论的位置列
如下图,现有result表中,来自第一条评论中所提取的词汇有14个,但是index_content只能表示这些词汇来自于第一条评论,现在尝试添加新列index_word,在第一条数据中,其表示第二个词的位置是2,第二个词的位置是3,以此类推...
在原有的reviews_n表中,每条评论所提取的词汇长度如下:
构建index_word列表;
展开index_word列表,表示词语在改评论的位置;合并评论id,评论中词的id,词,词性,评论类型;
3.7提取含有名词的评论
由于研究目标是对产品特性的优缺点进行分析,类似“很不错,继续支持”这样的评论,虽然表达了对产品的情感倾向,但是没有指出产品特性(大小,颜色,功能)的好坏,因此,需要在result表中,将含有名词的评论标注出来,供后续分析。
注意:是index_content这一条数据含有名词,不是去提取nature='n'的列;
3.8词云绘制
初步词云绘制,并导出result表,供进一步分析。
# 绘制词云
import matplotlib.pyplot as plt
from wordcloud import WordCloud
frequencies = result.groupby(by = ['word'])['word'].count()
frequencies = frequencies.sort_values(ascending = False)
backgroud_Image=plt.imread('data/pl.jpg')
wordcloud = WordCloud(font_path="simhei.ttf",#黑体,Windows常规字体
max_words=100,
background_color='white',
mask=backgroud_Image)
my_wordcloud = wordcloud.fit_words(frequencies)
plt.axis('off') #关闭轴
plt.imshow(my_wordcloud)
四.情感倾向分析
文本情感分析的一个基本步骤是对文本中的某段已知文字的两极性进行分类,这个分类可能是在句子级、功能级。分类的作用就是判断出此文字中表述的观点是积极的、消极的、还是中性的情绪。
一种判定情绪的方法是,当一个词普遍被认为跟消极、中性或是积极的情感有关联时,将这个词赋予一个-1到+1之中的数字级别,再将整条评论的词语权重加和,去判定消费者对一个文本(一条评论)的感情。
本次采用词典匹配的方法,对result_word表中的词汇进行情感词匹配,匹配的词典为知网发布“情感分析用词语集(beta版)”,www.keenage.com/html/c_inde…
4.1合并所下载的情感词表
读取分析三中保存的result_word.csv表,pos_comment为正面评价词语(中文).txt,neg_comment为负面评价词语(中文).txt,pos_emotion为正面情感词语(中文).txt,neg_emotion为负面情感词语(中文).txt;
合并情感词与评价词;
# 合并情感词与评价词
positive = set(pos_comment.iloc[:,0])|set(pos_emotion.iloc[:,0])
negative = set(neg_comment.iloc[:,0])|set(neg_emotion.iloc[:,0])
intersection = positive&negative # 正负面情感词表中相同的词语
positive = list(positive - intersection)
negative = list(negative - intersection)
将正面词语权重赋值1,负面词语权重赋值-1;赋值完成后,合并词表;
positive = pd.DataFrame({"word":positive,"weight":[1]*len(positive)})
negative = pd.DataFrame({"word":negative,"weight":[-1]*len(negative)})
posneg = positive.append(negative)
将result_word表与data_posneg表合并,只保留有情感值的词语,id作为位置标识(之后删除了控制)结果如下;
4.2修正情感倾向
分词过程中,有些否定词会使可能使得评论的倾向刚好相反。那选词的时候,我们就要把否定词也筛选进去,如果根据情感词判断为正面后,含有奇数个否定词情感倾向就相反,含有偶数个否定词,情感倾向就相同。
例如,存在某条评论为“这件东西并非不好”,刚才在分词并删除停用词后,只保留了“东西”“不好”两个词语,再经过情感词表的对比赋值,现在的weight值应该是-1,目前否定词修正,就是搜索其中的情感词语“不好”,按照汉语习惯,搜索每个情感词语前面的两个词语是否有否定词汇。前面一个否定词语,weight值应该修正为1;前面两个否定词语,weight值不变;
本次修正情感倾向的否定词表为not.csv;修正后的权重值用amend_weight表示;
4.3 计算每条评论的情感值
给情感值大于0的赋予评论类型(content_type)为pos,小于0的为neg
# 给情感值大于0的赋予评论类型(content_type)为pos,小于0的为neg
emotional_value['a_type'] = ''
emotional_value['a_type'][emotional_value['amend_weight'] > 0] = 'pos'
emotional_value['a_type'][emotional_value['amend_weight'] < 0] = 'neg'
修正后的情感倾向result_word表如下:
4.4 绘制词云
提取正负面评论信息
# 提取正负面评论信息
ind_pos = list(emotional_value[emotional_value['a_type'] == 'pos']['index_content'])
ind_neg = list(emotional_value[emotional_value['a_type'] == 'neg']['index_content'])
posdata = word[[i in ind_pos for i in word['index_content']]]
negdata = word[[i in ind_neg for i in word['index_content']]]
绘制正面、负面情感词词云;
正面情感评价
负面情感评价
(记于2020.1.18)