基于LDA对电商商品评论进行情感分析

版权声明:转载请声明转自Juanlyjack https://blog.csdn.net/m0_38088359/article/details/83276856

数据是人工爬取自京东网站上的评论数据,该项目主要以美的产品作为分析。
下载连接:
链接:https://pan.baidu.com/s/1uyzEa6VJBkBLHMzxLxwwMw
提取码:bwfa

1、项目背景:
现在大众在进行网购之前都会先看下相关商品的评论,包括好评与差评,再综合衡量,最后才决定是否会购买相关的物品。甚至有的消费者已经不看商品的详情秒数页而是直接看评论,然后决定是否下单。商品评论已经是用户决策最为核心的考量因素了。
在本项目中要根据商品的好评与差评,提取出关键词,快速了解一件商品的好与不好的地方。

原始评论需要提炼:
商品虽然希望买家给好评,但是从数据挖掘的角度看,单纯的好拼价值不大,尤其是一些空洞的评价,并未能给未来潜在消费者提供有价值的参考信息。比如大部分消费者会这么说“质量不错”、“好评,下次买还是你家”等,但对于一个关心该产品安全性的消费者来说显然是没用的,当消费者没了解到他想了解的问题,很可能在头脑发热期过了之后就不会再考虑购买了。

2、项目需求:
对于一个指定的商品,生产商、卖家或消费者需要了解用户认同该商品的哪些优点,不认同该商品的哪些弱点或缺点。

3、项目输出:
(1)商品好评的若干个topic中,其关键词各是什么,以及每个关键词的权重。
(2)商品差评的若干个topic中,其关键词各是什么,以及每个关键词的权重。

4、需要安装的库:
snownlp – 用来处理情感分析
jieba – 分词
gensim – 构建词向量

5、LDA主题模型:
如果一篇文章有一个中心思想或主题,那么一些特定词语会更频繁地出现。一篇文章通常可以包含多种主题,每个主题所占比例各不相同。对于不同主题的文章而言,其不同的主题实际上构成了一个分布。
一篇文章有主题,那么对于一个文档集,我们也可以分析其主题分布。借此甚至可以看出我的阅读爱好是什么。如果按每五年来分析,可以回顾下过去我的阅读兴趣的变化。当然现实中对主题分布进行分析,更多是出于商业目的。

本质上主题模型是一个词袋模型,不考虑词的顺序。
(1)已知条件:给定一个文档,可以看到的每篇文档都是由哪些词构成。
(2)假设条件:LDA模型假设每篇文档都是在讲述若干个主题,至于具体几个主题,可以认为预先设定k值。
(3)求解:通过LDA模型,可以求出这k个主题(latent)中,每个主题到底长什么样子。

Documents–Topics–Words(Tokens)

LDA能做什么:
(1)能做:求解出k个主题长什么样子。
(2)不能做:不能认为设定是什么主题,比如不能认为设定为财经、体育的主题。因为LDA是无监督算法,模型训练结束后,每个主题长什么样子就是什么样子,和整个语料中的每篇文档的内容有关系。无法人为强求某个主题表示财经,某个主题表示体育等。

LDA优点:
(1)无监督:不用对训练数据打标签
(2)预处理简单:分词,去除停用词
(3)参数少:一般只需要设定主题数k

6、代码实现:
(1)读取数据

import pandas as pd

inputfile = 'huizong.csv'
outputfile = 'meidi_jd.txt'
data = pd.read_csv(inputfile,encoding='utf8')
#只提取与美的品牌产品有关的评论
data = data[data['品牌']=='美的']['评论']

(2)数据预处理

#除去NAN
data = data.dropna()
import numpy as np

#去重,比如差不多的评论考虑其中一条就可以
l1 = len(data)
data = pd.DataFrame(data.unique())
l2 = len(data)
print(u'删除了%s条评论.'%(l1-l2))

'''
压缩词,也就是对句子内冗长的部分进行压缩
'''
def cutword(strs,reverse=False):
    s1 = []
    s2 = []
    s = []
    if reverse:
        strs = strs[::-1]
    s1.append(strs[0])
    for i in strs[1:]:
        if i == s1[0]:
            if len(s2)==0:
                s2.append(i)
            else:
                if s1 == s2:
                    s2 = []
                    s2.append(i)
                else:
                    s = s+s1+s2
                    s1 = []
                    s2 = []
                    s1.append(i)
        else:
            if s1 == s2 and len(s1)>=2 and len(s2)>=2:
                s = s+s1
                s1 = []
                s2 = []
                s1.append(i)
            else:
                if len(s2)==0:
                    s1.append(i)
                else:
                    s2.append(i)
    if s1 == s2:
        s = s+s1
    else:
        s = s+s1+s2
    if reverse :
        return ''.join(s[::-1])
    else:
        return ''.join(s)

data2 = data.iloc[:,0].apply(cutword)

#短句过滤
data3 = data2[data2.apply(len)>=4]

(3)LDA模型训练
使用snownlp库中的SnowNLP类进行情感分析。
该类接收一个句子文本,然后使用该类的sentiments属性产生一个概率值,概率表示该句子是积极的概率,越接近于1表示越积极,越接近于0表示越负面。
举个例子:

from snownlp import SnowNLP
s = SnowNLP(u'这个东西真心很赞')
s.words # [u'这个', u'东西', u'真心',
# u'很', u'赞']
s.tags # [(u'这个', u'r'), (u'东西', u'n'),
# (u'真心', u'd'), (u'很', u'd'),
# (u'赞', u'Vg')]
s.sentiments # 0.9769663402895832 positive的概率

回到数据集,由于数据集是一个DataFrame格式,直接使用apply()函数进行对所有行句子的情感分析。得到的coms是一个Series类型数据,只有一列,并且都是概率值。

from snownlp import SnowNLP

coms = data3.apply(lambda x:SnowNLP(x).sentiments)
coms

输出如下:

0        9.827906e-01
1        8.398297e-01
2        9.995530e-01
             ...     
53043    8.272506e-01
53044    4.341055e-01
53045    1.220829e-01
53046    7.864625e-01
53047    9.859058e-01
Name: 0, Length: 52426, dtype: float64

对积极评论与负面评论进行分类分析。

#coms的值越接近1,表示越positive,越接近0表示越negative
data_positive = data3[coms>=0.6]
data_negative = data3[coms<0.4]

接着进行分词:

import jieba
#进行分词
data_positive = data_positive.apply(lambda x:' '.join(jieba.cut(x)))
data_negative = data_negative.apply(lambda x:' '.join(jieba.cut(x)))

with open('stoplist.txt',encoding='utf8') as file:
    stop = file.readlines()

stop = [x.strip('\n') for x in stop]
stop.append('')
data_positive_split = data_positive.apply(lambda x:x.split(' '))
data_positive = data_positive_split.apply(lambda x:[i for i in x if i not in stop])
data_negative_split = data_negative.apply(lambda x:x.split(' '))
data_negative = data_negative_split.apply(lambda x:[i for i in x if i not in stop])

在处理完以上数据格式之后,还不能讲数据喂给lda模型,必须要再进一步处理。因为list中有些词是重复的,而且缺少每个词的词频信息,为了让模型可以运行,还需要先用doc2bow这个函数将数据转换成恰当的格式。

如何转换?
使用gensim库中corpora.Dictionary()类进行存储,然后通过调用它的函数doc2bow()进行转换。

from gensim import corpora,models

neg_dict = corpora.Dictionary(data_negative)
neg_dict.id2token

输出示例:

{0: '再',
 1: '早上',
 2: '晚上',
 3: '水方',
 4: '洗',
 5: '满意',
 6: '热',
 7: '50',
 8: '不到',
 9: '买',
      ...}

接着让文档中的所有句子中的词都映射称为(id,frequency)元组来表示,frequency表示的是词在句子中出现的频率。其中如果出现一个新句子,且存在新词,那么新词是没有元组替代表示的。
这里使用corpora.Dictionary类的方法doc2bow()来转换。
注意这里是对整个文档进行转换,进而整个文档变成了一个语料库,作为Ida模型的corpus的输入。

neg_corpus = [neg_dict.doc2bow(i) for i in data_negative]

此外模型还需要词与id的映射关系作为输出的转换,也就是刚刚的neg_dict,当然还要人工选择一个主题的数量。这里选择3。

#放进gensim.models中的lda模型进行训练
neg_lda = models.LdaModel(corpus=neg_corpus,num_topics=3,id2word=neg_dict)

print(neg_lda.print_topics(3))

输出如下:

[(0, '0.031*"安装" + 0.023*"好" + 0.020*"加热" + 0.013*"热水器" + 0.011*"不错" + 0.011*"京东" + 0.009*"问题" + 0.009*"送货" + 0.009*"师傅" + 0.008*"使用"'), (1, '0.081*"安装" + 0.027*"师傅" + 0.017*"好" + 0.016*"热水器" + 0.015*"不错" + 0.013*"美的" + 0.011*"售后" + 0.011*"东西" + 0.011*"安装费" + 0.010*"收费"'), (2, '0.030*"买" + 0.015*"热水器" + 0.014*"安装" + 0.012*"美的" + 0.009*"遥控" + 0.009*"一个" + 0.009*"n" + 0.008*"好" + 0.006*"价格" + 0.006*"60"')]

同理对积极评论的内容也进行同样的转换以便分析:

pos_dict = corpora.Dictionary(data_positive)
pos_corpus = [pos_dict.doc2bow(i) for i in data_positive]
pos_lda = models.LdaModel(corpus=pos_corpus,num_topics=3,id2word=pos_dict)

print(pos_lda.print_topics(3))

输出如下:

[(0, '0.073*"好" + 0.040*"不错" + 0.028*"很快" + 0.028*"价格" + 0.027*"质量" + 0.025*"速度" + 0.023*"送货" + 0.022*"实惠" + 0.021*"安装" + 0.020*"加热"'), (1, '0.095*"不错" + 0.062*"安装" + 0.028*"使用" + 0.019*"感觉" + 0.019*"外观" + 0.018*"送货" + 0.014*"师傅" + 0.013*"热水器" + 0.011*"漂亮" + 0.010*"美的"'), (2, '0.108*"好" + 0.062*"不错" + 0.049*"买" + 0.029*"京东" + 0.028*"东西" + 0.025*"热水器" + 0.022*"美的" + 0.022*"挺" + 0.021*"满意" + 0.020*"值得"')]

注释:以上输出的结果是对应的三个主题的积极评论以及负面评论,在每个主题里面按照主题的相关性排序,越靠前的表示该主题越突出。

负面评论分析:
会发现在负面评价当中出现了’好’,'不错’等这些正面的词,这并不奇怪,原因是京东的客户评价还是以好评为主,
当然这也与电商倾向于保留正面评价有关.
在第0个主题当中,安装的比重最大,说明该主题与安装相关,而’有点’是倾向于负面的评论,又出现了师傅的字眼,
可以反应出可能安装中出现师傅服务态度不好等一些负面问题,还有加热等问题.
在第1个主题当中,安装的比重也是最大,但是出现安装费主题,可以从这里看出一点端倪,可能安装费太贵了
可能会发现大多数都是好评,.
在第2个主题中,不仅有安装,还有送货字眼.综上可能大部分差评与师傅服务态度,配送费贵,安装费贵,送货快慢等原因有关.

正面评论分析:
好评当中第一个主题出现了送货,安装,很快,满意等字眼,那说明有人认可该送货速度和安装速度或服务的.
第二个主题出现了值得,信赖,品牌,满意等字眼,那可能就有人比较信赖牌子,认可美的这个品牌
第三个主题特别提到了京东,可能有人比较信任不仅美的,同时发现出现价格,高,性价比,实惠等主题出现,
又因为这是好评,所以可能是与价格实惠有关,性价比高.

猜你喜欢

转载自blog.csdn.net/m0_38088359/article/details/83276856