当前位置:   article > 正文

Python有趣|中文文本情感分析

python文本情感分析0.6代表什么

640?wx_fmt=png

前言

前文给大家说了python机器学习的路径,这光说不练假把式,这次,罗罗攀就带大家完成一个中文文本情感分析的机器学习项目,今天的流程如下:

640?wx_fmt=png

数据情况和处理
数据情况

这里的数据为大众点评上的评论数据(王树义老师提供),主要就是评论文字和打分。我们首先读入数据,看下数据的情况:

 
 
  1. import numpy as np

  2. import pandas as pd

  3. data = pd.read_csv('data1.csv')

  4. data.head()

640?wx_fmt=png

情感划分

对star字段看唯一值,打分有1,2,4,5。

640?wx_fmt=png

中文文本情感分析属于我们的分类问题(也就是消极和积极),这里是分数,那我们设计代码,让分数小于3的为消极(0),大于3的就是积极(1)。

定义一个函数,然后用apply方法,这样就得到了一个新列(数据分析里的知识点)

 
 
  1. def make_label(star):

  2. if star > 3:

  3. return 1

  4. else:

  5. return 0

  6. data['sentiment'] = data.star.apply(make_label)

640?wx_fmt=png

工具包(snownlp)

我们首先不用机器学习方法,我们用一个第三库(snownlp),这个库可以直接对文本进行情感分析(记得安装),使用方法也是很简单。返回的是积极性的概率。

 
 
  1. from snownlp import SnowNLP

  2. text1 = '这个东西不错'

  3. text2 = '这个东西很垃圾'

  4. s1 = SnowNLP(text1)

  5. s2 = SnowNLP(text2)

  6. print(s1.sentiments,s2.sentiments)

  7. # result 0.8623218777387431 0.21406279508712744

这样,我们就定义大于0.6,就是积极的,同样的方法,就能得到结果。

 
 
  1. def snow_result(comemnt):

  2. s = SnowNLP(comemnt)

  3. if s.sentiments >= 0.6:

  4. return 1

  5. else:

  6. return 0

  7. data['snlp_result'] = data.comment.apply(snow_result)

640?wx_fmt=png

上面前五行的结果看上去很差(5个就2个是对的),那到底有多少是对的了?我们可以将结果与sentiment字段对比,相等的我就计数,这样在除以总样本,就能看大概的精度了。

 
 
  1. counts = 0

  2. for i in range(len(data)):

  3. if data.iloc[i,2] == data.iloc[i,3]:

  4. counts+=1

  5. print(counts/len(data))

  6. # result 0.763

朴素贝叶斯

前面利用第三库的方法,结果不是特别理想(0.763),而且这种方法存在一个很大的弊端:针对性差。

什么意思了?我们都知道,不同场景下,语言表达都是不同的,例如这个在商品评价中有用,在博客评论中可能就不适用了。

所以,我们需要针对这个场景,训练自己的模型。本文将使用sklearn实现朴素贝叶斯模型(原理在后文中讲解)。slearn小抄先送上(下文有高清下载地址)。

大概流程为:

  • 导入数据

  • 切分数据

  • 数据预处理

  • 训练模型

  • 测试模型

640?wx_fmt=png

jieba分词

首先,我们对评论数据分词。为什么要分词了?中文和英文不一样,例如:i love python,就是通过空格来分词的;我们中文不一样,例如:我喜欢编程,我们要分成我/喜欢/编程(通过空格隔开),这个主要是为了后面词向量做准备。

 
 
  1. import jieba

  2. def chinese_word_cut(mytext):

  3. return " ".join(jieba.cut(mytext))

  4. data['cut_comment'] = data.comment.apply(chinese_word_cut)

640?wx_fmt=png

划分数据集

分类问题需要x(特征),和y(label)。这里分词后的评论为x,情感为y。按8:2的比例切分为训练集和测试集。

 
 
  1. X = data['cut_comment']

  2. y = data.sentiment

  3. from sklearn.model_selection import train_test_split

  4. X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=22)

词向量(数据处理)

电脑是没法识别文字的,只能识别数字。那文本怎么处理了,最简单的就是词向量。什么是词向量,我们通过一个案例来说明下,下面是我们的文本:

 
 
  1. I love the dog

  2. I hate the dog

词向量处理后就是这样的:

640?wx_fmt=png

简单的说,词向量就是我们将整个文本出现的单词一一排列,然后每行数据去映射到这些列上,出现的就是1,没出现就是0,这样,文本数据就转换成了01稀疏矩阵(这也是上文中文分词的原因,这样一个词就是一个列)。

好在,sklearn中直接有这样的方法给我们使用。CountVectorizer方法常用的参数:

  • max_df:在超过这一比例的文档中出现的关键词(过于平凡),去除掉。

  • min_df:在低于这一数量的文档中出现的关键词(过于独特),去除掉。

  • token_pattern:主要是通过正则处理掉数字和标点符号。

  • stop_words:设置停用词表,这样的词我们就不会统计出来(多半是虚拟词,冠词等等),需要列表结构,所以代码中定义了一个函数来处理停用词表。

 
 
  1. from sklearn.feature_extraction.text import CountVectorizer

  2. def get_custom_stopwords(stop_words_file):

  3. with open(stop_words_file) as f:

  4. stopwords = f.read()

  5. stopwords_list = stopwords.split('\n')

  6. custom_stopwords_list = [i for i in stopwords_list]

  7. return custom_stopwords_list

  8. stop_words_file = '哈工大停用词表.txt'

  9. stopwords = get_custom_stopwords(stop_words_file)

  10. vect = CountVectorizer(max_df = 0.8,

  11. min_df = 3,

  12. token_pattern=u'(?u)\\b[^\\d\\W]\\w+\\b',

  13. stop_words=frozenset(stopwords))

如果想看到底出来的是什么数据,可通过下面代码查看。

 
 
  1. test = pd.DataFrame(vect.fit_transform(X_train).toarray(), columns=vect.get_feature_names())

  2. test.head()

640?wx_fmt=png

训练模型

训练模型,很简单,用的是朴素贝叶斯算法,结果为0.899,比之前的snownlp好很多了。

 
 
  1. from sklearn.naive_bayes import MultinomialNB

  2. nb = MultinomialNB()

  3. X_train_vect = vect.fit_transform(X_train)

  4. nb.fit(X_train_vect, y_train)

  5. train_score = nb.score(X_train_vect, y_train)

  6. print(train_score)

  7. # result 0.899375

测试数据

当然,我们需要测试数据来验证精确度了,结果为0.8275,精度还是不错的。

 
 
  1. X_test_vect = vect.transform(X_test)

  2. print(nb.score(X_test_vect, y_test))

  3. # result 0.8275

当然,我们也可以将结果放到data数据中:

 
 
  1. X_vec = vect.transform(X)

  2. nb_result = nb.predict(X_vec)

  3. data['nb_result'] = nb_result

640?wx_fmt=png

讨论和不足
  • 样本量少

  • 模型没调参

  • 没有交叉验证

今日互动

代码下载:https://github.com/panluoluo/crawler-analysis,下载完整数据和代码。

留言打卡:说说评论杠精那些事。公众号后台回复【入群】,加入学习交流群群,2019年一起搞事情。


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/72782
推荐阅读
相关标签
  

闽ICP备14008679号