Sklearn 点评文本情感分析

一、准备工作

1、数据导入

import numpy as np
import pandas as pd
data = pd.read_csv('/Users/liming/Downloads/review_star.csv')
print(data.shape)
data.head()
(10000, 3)
reviewid reviewbody star
0 661655779 感谢大众点评的vip会员卷。很多好吃的都打折。去天河城吃饭顺便把喝的换了。两杯茶才9.9。简... 40
1 661662037 (9月26日就餐)这家的服务态度真是很奇葩了:在等餐时看到服务员在端豆浆上桌前,突然在碗里发... 5
2 661662167 除了贵 没毛病 35
3 661674219 亲民,家门口,味道可以,主要是在家附近,吃点家常菜还是比较方便的,不做饭就在这里吃点,做的也... 45
4 661677846 之前在会展中心店按过,觉得很不错,说上梅林也有一家店,刚好在附近办事,所以来了这里,装修风格... 50

2、情感划分

# 查看 star 字段唯一值
print(pd.unique(data['star']))
[40  5 35 45 50 20 30 25 10  4 15]

我们的目的是分析文本的情感:积极或消极。 因此,这里设置阈值为30:star 小于30的为消极(0)、大于等于30的为积极(1)。

# 定义函数:根据用户评的星级来估计sentiment(情感)
def make_label(star):
    if star >=30:
        return 1
    else:
        return 0
# 运用 apply 方法得到新列
data["sentiment"] = data.star.apply(make_label)
data.head()
reviewid reviewbody star sentiment
0 661655779 感谢大众点评的vip会员卷。很多好吃的都打折。去天河城吃饭顺便把喝的换了。两杯茶才9.9。简... 40 1
1 661662037 (9月26日就餐)这家的服务态度真是很奇葩了:在等餐时看到服务员在端豆浆上桌前,突然在碗里发... 5 0
2 661662167 除了贵 没毛病 35 1
3 661674219 亲民,家门口,味道可以,主要是在家附近,吃点家常菜还是比较方便的,不做饭就在这里吃点,做的也... 45 1
4 661677846 之前在会展中心店按过,觉得很不错,说上梅林也有一家店,刚好在附近办事,所以来了这里,装修风格... 50 1
data["reviewbody"] = data["reviewbody"].astype(str)
data.head()
reviewid reviewbody star sentiment
0 661655779 感谢大众点评的vip会员卷。很多好吃的都打折。去天河城吃饭顺便把喝的换了。两杯茶才9.9。简... 40 1
1 661662037 (9月26日就餐)这家的服务态度真是很奇葩了:在等餐时看到服务员在端豆浆上桌前,突然在碗里发... 5 0
2 661662167 除了贵 没毛病 35 1
3 661674219 亲民,家门口,味道可以,主要是在家附近,吃点家常菜还是比较方便的,不做饭就在这里吃点,做的也... 45 1
4 661677846 之前在会展中心店按过,觉得很不错,说上梅林也有一家店,刚好在附近办事,所以来了这里,装修风格... 50 1

二、朴素贝叶斯方法

接下来使用sklearn实现朴素贝叶斯模型来进行情感分析。

1、分词

# 首先对评论数据进行分词
import jieba

def chinese_word_cut(mytext):
 return " ".join(jieba.cut(mytext))

data['cut_comment'] = data["reviewbody"].apply(chinese_word_cut)
data.head()
Building prefix dict from the default dictionary ...
Loading model from cache /var/folders/zd/qhg48cw17_ncqf0rl48wz5rh0000gp/T/jieba.cache
Loading model cost 0.552 seconds.
Prefix dict has been built successfully.
reviewid reviewbody star sentiment cut_comment
0 661655779 感谢大众点评的vip会员卷。很多好吃的都打折。去天河城吃饭顺便把喝的换了。两杯茶才9.9。简... 40 1 感谢 大众 点评 的 vip 会员 卷 。 很多 好吃 的 都 打折 。 去 天河城 吃饭 ...
1 661662037 (9月26日就餐)这家的服务态度真是很奇葩了:在等餐时看到服务员在端豆浆上桌前,突然在碗里发... 5 0 ( 9 月 26 日 就餐 ) 这家 的 服务态度 真是 很 奇葩 了 : 在 等 餐时 看...
2 661662167 除了贵 没毛病 35 1 除了 贵 没 毛病
3 661674219 亲民,家门口,味道可以,主要是在家附近,吃点家常菜还是比较方便的,不做饭就在这里吃点,做的也... 45 1 亲民 , 家门口 , 味道 可以 , 主要 是 在家 附近 , 吃点 家常菜 还是 比较 方...
4 661677846 之前在会展中心店按过,觉得很不错,说上梅林也有一家店,刚好在附近办事,所以来了这里,装修风格... 50 1 之前 在 会展中心 店 按 过 , 觉得 很 不错 , 说 上 梅林 也 有 一家 店 , ...

2、划分数据集

这里的特征X为分词后的评论数据 cut_comment,目标y为情感数据 sentiment。按8:2的比例切分为训练集和测试集。

X = data['cut_comment']
y = data['sentiment']

from sklearn.model_selection import train_test_split
# 划分测试集和训练集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=22)

3、词向量(数据处理)

电脑是没法识别文字的,只能识别数字。下面利用sklearn中的CountVectorizer方法将文本转化为词向量。

CountVectorizer(潜在语义分析方法)方法常用的参数:

  • max_df:在超过这一比例的文档中出现的关键词(过于平凡),去除掉。
  • min_df:在低于这一数量的文档中出现的关键词(过于独特),去除掉。
  • token_pattern:主要是通过正则处理掉数字和标点符号。
  • stop_words:设置停用词表,这样的词我们就不会统计出来(多半是虚拟词,冠词等等),需要列表结构,所以代码中定义了一个函数来处理停用词表。
from sklearn.feature_extraction.text import CountVectorizer

def get_custom_stopwords(stop_words_file):
    with open(stop_words_file, encoding="ISO-8859-1") as f:
        stopwords = f.read()
    stopwords_list = stopwords.split('\n')
    custom_stopwords_list = [i for i in stopwords_list]
    return custom_stopwords_list

stop_words_file = '/Users/liming/Downloads/哈工大停用词表.txt'
stopwords = get_custom_stopwords(stop_words_file)

vect = CountVectorizer(max_df = 0.8,
                       min_df = 3,
                       token_pattern=u'(?u)\\b[^\\d\\W]\\w+\\b',
                       stop_words=frozenset(stopwords))

通过以下代码查看得到的数据:

# 不输出warning
import warnings
warnings.filterwarnings('ignore')
# 查看 vect
test = pd.DataFrame(vect.fit_transform(X_train).toarray(), columns=vect.get_feature_names())
test.head()
and app a座 b1 b2 bar bb bbq brunch bug ... 齐全 龙之梦 龙凤 龙利 龙利鱼 龙头 龙岗 龙湖 龙虾 龙门
0 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
2 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
3 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
4 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0

5 rows × 8223 columns

4、模型训练(朴素贝叶斯算法)

from sklearn.naive_bayes import MultinomialNB
nb = MultinomialNB() # 构建朴素贝叶斯模型框架

X_train_vect = vect.fit_transform(X_train) # 将训练数据转化为词向量
nb.fit(X_train_vect, y_train) # 训练模型
train_score = nb.score(X_train_vect, y_train)# 计算准确率
print(train_score)
0.9715

5、模型测试

X_test_vect = vect.transform(X_test)
print(nb.score(X_test_vect, y_test))
0.958

将结果放入到data数据中:

X_vec = vect.transform(X)
nb_result = nb.predict(X_vec)
data['nb_result'] = nb_result
data.head()
reviewid reviewbody star sentiment cut_comment nb_result
0 661655779 感谢大众点评的vip会员卷。很多好吃的都打折。去天河城吃饭顺便把喝的换了。两杯茶才9.9。简... 40 1 感谢 大众 点评 的 vip 会员 卷 。 很多 好吃 的 都 打折 。 去 天河城 吃饭 ... 1
1 661662037 (9月26日就餐)这家的服务态度真是很奇葩了:在等餐时看到服务员在端豆浆上桌前,突然在碗里发... 5 0 ( 9 月 26 日 就餐 ) 这家 的 服务态度 真是 很 奇葩 了 : 在 等 餐时 看... 0
2 661662167 除了贵 没毛病 35 1 除了 贵 没 毛病 1
3 661674219 亲民,家门口,味道可以,主要是在家附近,吃点家常菜还是比较方便的,不做饭就在这里吃点,做的也... 45 1 亲民 , 家门口 , 味道 可以 , 主要 是 在家 附近 , 吃点 家常菜 还是 比较 方... 1
4 661677846 之前在会展中心店按过,觉得很不错,说上梅林也有一家店,刚好在附近办事,所以来了这里,装修风格... 50 1 之前 在 会展中心 店 按 过 , 觉得 很 不错 , 说 上 梅林 也 有 一家 店 , ... 1

三、讨论和不足

  • 模型没调参
  • 没有交叉验证