文本挖掘&情感分析

大众点评评价情感分析~

先上结果:

糖水店的评论文本 模型预测的情感评分
‘糖水味道不错,滑而不腻,赞一个,下次还会来’ 0.91
‘味道一般,没啥特点’ 0.52
‘排队老半天,环境很差,味道一般般’ 0.05

模型的效果还可以的样子,yeah~接下来我们好好讲讲怎么做的哈,我们通过爬虫爬取了大众点评广州8家最热门糖水店的3W条评论信息以及评分作为训练数据,前面的分析我们得知样本很不均衡。接下来我们的整体思路就是:文本特征处理(分词、去停用词、TF-IDF)—机器学习建模—模型评价。

我们先不处理样本不均衡问题,直接建模后查看结果,接下来我们再按照两种方法处理样本不均衡,对比结果。

数据读入和探索

import pandas as pd
from matplotlib import pyplot as plt
import jieba
data = pd.read_csv('data.csv')
data.head()
cus_id comment_time comment_star cus_comment kouwei huanjing fuwu shopID stars year month weekday hour comment_len
0 迷糊泰迪 2018-09-20 06:48:00 sml-str40 南信 算是 广州 著名 甜品店 吧 好几个 时间段 路过 都 是 座无虚席 看着 餐单 上 ... 非常好 518986 4.0 2018 9 3 6 145.0
1 稱霸幼稚園 2018-09-22 21:49:00 sml-str40 中午 吃 完 了 所谓 的 早茶 回去 放下 行李 休息 了 会 就 来 吃 下午茶 了 服... 很好 很好 很好 518986 4.0 2018 9 5 21 255.0
2 爱吃的美美侠 2018-09-22 22:16:00 sml-str40 冲刺 王者 战队 吃遍 蓉城 战队 有 特权 五月份 和 好 朋友 毕业 旅行 来 了 广州... 很好 很好 很好 518986 4.0 2018 9 5 22 255.0
3 姜姜会吃胖 2018-09-19 06:36:00 sml-str40 都 说来 广州 吃 糖水 就要 来南信 招牌 姜撞奶 红豆 双皮奶 牛 三星 云吞面 一楼 ... 非常好 很好 很好 518986 4.0 2018 9 2 6 184.0
4 forevercage 2018-08-24 17:58:00 sml-str50 一直 很 期待 也 最 爱 吃 甜品 广州 的 甜品 很 丰富 很 多样 来 之前 就 一直... 非常好 很好 很好 518986 5.0 2018 8 4 17 255.0

构建标签值

大众点评的评分分为1-5分,1-2为差评,4-5为好评,3为中评,因此我们把1-2记为0,4-5记为1,3为中评,对我们的情感分析作用不大,丢弃掉这部分数据,但是可以作为训练语料模型的语料。我们的情感评分可以转化为标签值为1的概率值,这样我们就把情感分析问题转为文本分类问题了。

#构建label值
def zhuanhuan(score):
    if score > 3:
        return 1
    elif score < 3:
        return 0
    else:
        return None
    
#特征值转换
data['target'] = data['stars'].map(lambda x:zhuanhuan(x))
data_model = data.dropna()
data_model
cus_id comment_time comment_star cus_comment kouwei huanjing fuwu shopID stars year month weekday hour comment_len target
0 迷糊泰迪 2018-09-20 06:48:00 sml-str40 南信 算是 广州 著名 甜品店 吧 好几个 时间段 路过 都 是 座无虚席 看着 餐单 上 ... 非常好 518986 4.0 2018 9 3 6 145.0 1.0
1 稱霸幼稚園 2018-09-22 21:49:00 sml-str40 中午 吃 完 了 所谓 的 早茶 回去 放下 行李 休息 了 会 就 来 吃 下午茶 了 服... 很好 很好 很好 518986 4.0 2018 9 5 21 255.0 1.0
2 爱吃的美美侠 2018-09-22 22:16:00 sml-str40 冲刺 王者 战队 吃遍 蓉城 战队 有 特权 五月份 和 好 朋友 毕业 旅行 来 了 广州... 很好 很好 很好 518986 4.0 2018 9 5 22 255.0 1.0
3 姜姜会吃胖 2018-09-19 06:36:00 sml-str40 都 说来 广州 吃 糖水 就要 来南信 招牌 姜撞奶 红豆 双皮奶 牛 三星 云吞面 一楼 ... 非常好 很好 很好 518986 4.0 2018 9 2 6 184.0 1.0
4 forevercage 2018-08-24 17:58:00 sml-str50 一直 很 期待 也 最 爱 吃 甜品 广州 的 甜品 很 丰富 很 多样 来 之前 就 一直... 非常好 很好 很好 518986 5.0 2018 8 4 17 255.0 1.0
6 superclampfa 2018-08-15 00:39:00 sml-str40 补发 点评 目前为止 吃 过 的 最 好吃 的 双皮奶 没有 之一 去 广州 一定 要 尝试... 非常好 很好 很好 518986 4.0 2018 8 2 0 255.0 1.0
8 初小正 2018-09-15 22:26:00 sml-str40 广州 很胖 人 忍不住 的 要 吃 糖水 甜品 南信 的 店面 很 好找 上下 九 旅游区 ... 非常好 很好 非常好 518986 4.0 2018 9 5 22 255.0 1.0
9 水芙蓉88 2018-09-06 16:06:00 sml-str40 位于 步行街 上 沿着 步行街 一直 走 就 可以 到达 去 的 时候 不用 排队 门口 有... 很好 很好 很好 518986 4.0 2018 9 3 16 255.0 1.0
10 滚淡小姐 2018-09-12 20:44:00 sml-str40 不 知道 算不算 网红 只是 在 很多 小伙伴 的 朋友圈 都 看到 过 自然 要 来 打卡... 很好 很好 很好 518986 4.0 2018 9 2 20 255.0 1.0
11 请叫我伊丽莎丸袁哥 2018-08-22 11:30:00 sml-str50 这家 店 可谓 是 人气 爆棚 小贴士 是 座位 先 让 同行 小伙伴 找 好 否则 买好 ... 非常好 非常好 非常好 518986 5.0 2018 8 2 11 255.0 1.0
12 Hugewood 2018-08-09 13:03:00 sml-str40 这次 是 特地 为了 南信 才 去 的 上下 九 真的 是 一家 很 任性 的 店 准点 九... 很好 518986 4.0 2018 8 3 13 255.0 1.0
13 360_执着的马 2018-08-29 02:02:00 sml-str50 睡 到 自然 醒 又 去 上下 九 步行街 的 南信 要 一份 姜撞奶 一份 莲子 伴 椰汁... 非常好 非常好 非常好 518986 5.0 2018 8 2 2 163.0 1.0
14 小昕子_17 2018-08-28 13:02:00 sml-str40 广州 的 老字号 不少 其中 招牌 中有 文字 的 就 有 好几家 每家 都 有 自己 的 ... 很好 518986 4.0 2018 8 1 13 255.0 1.0
15 lincolnsuper 2018-09-06 22:14:00 sml-str40 传统 的 广式 甜品店 就 应该 是 这个 样子 店面 不 大 店员 都 是 有点 年纪 的... 很好 518986 4.0 2018 9 3 22 255.0 1.0
16 肥牛佳 2018-09-05 22:50:00 sml-str50 老广 同事 极力推荐 的 店铺 在 宝华 面馆 吃 完 主食 一路 散步 过来 接着 战斗 ... 非常好 一般 一般 518986 5.0 2018 9 2 22 255.0 1.0
17 两活勿连 2018-09-11 13:18:00 sml-str40 上下 九 步行街 上 的 网红 甜品店 人气 爆棚 门口 有 一面 墙 的 各种 认证 获奖... 非常好 518986 4.0 2018 9 1 13 240.0 1.0
18 宝贝longan 2018-09-05 15:34:00 sml-str40 不是 周末 节假日 在 上下 九 步行街 的 南信 甜品店 也 是 人山人海 就算 肯 一起... 很好 518986 4.0 2018 9 2 15 255.0 1.0
19 柚chopyf 2018-09-13 11:37:00 sml-str40 我 为 代言 地址 荔灣區 第十 甫 路 号 近 宝华 路 人均 元 左右 在 广州 众多 ... 很好 很好 很好 518986 4.0 2018 9 3 11 255.0 1.0
20 suki_gb 2018-08-30 23:55:00 sml-str50 去 广州 玩 美食 当然 不能 辜负 住 在 上下 九 晚上 点 出来 觅食 上 看 了 别... 非常好 很好 518986 5.0 2018 8 3 23 255.0 1.0
21 几哩是块里脊_ 2018-09-24 09:32:00 sml-str40 来 了 广州 可以 说出 一系列 小吃 早茶 肠粉 烧腊 甜品 糖水 汤品 等 从 饮食文化... 非常好 518986 4.0 2018 9 0 9 255.0 1.0
23 树懒丹 2018-09-12 21:36:00 sml-str50 打卡 广州 上下 九 步行街 那条 类似 于 上海南京路 步行街 的 街 到处 琳琅满目 的... 非常好 非常好 非常好 518986 5.0 2018 9 2 21 255.0 1.0
24 忽忽_3307 2018-09-26 09:13:00 sml-str40 抱 着 很大 期望 去 的 人 真的 超级 多 买 的 门口 的 外带 双皮奶 和 杨枝 甘... 很好 一般 非常好 518986 4.0 2018 9 2 9 72.0 1.0
25 BerlinettaNNN 2018-09-25 23:37:00 sml-str10 超级 恶心 打包 了 三份 回家 吃 到 第二份 的 时候 直接 吃 出 不 知道 是 什么... 518986 1.0 2018 9 1 23 114.0 0.0
27 ShinyNikki 2018-09-25 22:44:00 sml-str50 周二 两天 打三卡 点评 都 不 推送 我 让 点评 了 哈哈 今天 去 了 北京路 晚上 ... 非常好 非常好 非常好 518986 5.0 2018 9 1 22 255.0 1.0
28 爱吃甜食得小吃兔 2018-09-25 22:06:00 sml-str50 依旧 那么 好吃 这次 去 竟然 可以 叫外卖 了 真 好 啊 坐在 酒店 里 就 能 吃 ... 非常好 非常好 非常好 518986 5.0 2018 9 1 22 146.0 1.0
29 C-zm_6372 2018-09-25 20:48:00 sml-str50 逛街 正好 经过 就 进去 了 椰汁 香芋 西米露 和 鲜虾 云吞面 也 很 好吃 推荐 推荐 非常好 非常好 非常好 518986 5.0 2018 9 1 20 47.0 1.0
30 ceciler 2018-09-25 16:30:00 sml-str50 朋友 强烈推荐 我来 的 吃 过 以后 也 就 这样 吧 一般 甜品店 都 做 得 出来 而... 非常好 非常好 非常好 518986 5.0 2018 9 1 16 255.0 1.0
31 张菜菜8 2018-09-25 15:49:00 sml-str50 这家 真的 是 很棒 了 是 在 广州 吃 到 最 喜欢 的 店 了 强推 酸辣 牛 三星 ... 非常好 非常好 非常好 518986 5.0 2018 9 1 15 176.0 1.0
32 兔子need肉 2018-09-25 12:17:00 sml-str50 旅游 必吃 的 一家 非常 好找 看 了 菜谱 感觉 啥 都 好吃 点 了 几个 大众 点评... 非常好 非常好 很好 518986 5.0 2018 9 1 12 255.0 1.0
33 C小姐觅食迹 2018-09-25 10:53:00 sml-str40 来 广州 必要 吃 南信 啦 一进 店面 人山人海 的 场景 真实 有 被 吓 到 位子 自... 非常好 一般 一般 518986 4.0 2018 9 1 10 255.0 1.0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
32445 lihuamama 2018-04-08 15:41:00 sml-str10 芋头 椰汁 西米露 芋头 是 酸 的 不 新鲜 521698 1.0 2018 4 6 15 23.0 0.0
32446 JJMiss~Z 2017-12-25 12:31:00 sml-str40 慕名而来 的 在 西华路 第一 津 里面 一问 好多 人 都 不 知道 有些 年 的 老铺 ... 很好 很好 很好 521698 4.0 2017 12 0 12 255.0 1.0
32447 Kary_BB_7754 2017-11-01 19:30:00 sml-str20 收银 阿姨 服务 超级 差多 问 一句 就 反 白眼 这么 不耐烦 就 不要 做 服务行业 ... 非常好 521698 2.0 2017 11 2 19 121.0 0.0
32448 涴世亦踯躅 2017-10-31 07:49:00 sml-str40 沙湾 小镇 以前 的 老 镇子 大都 是 住 在 这里 好多年 的 老 街坊邻居 学校 旁边... 非常好 521698 4.0 2017 10 1 7 255.0 1.0
32450 vivi2008 2017-10-01 16:00:00 sml-str50 龟苓膏 配 炼乳 芒果 双皮 特别 好吃 芒果 又 甜 又 新鲜 椰奶 红 豆沙 淡淡的 甜... 非常好 很好 很好 521698 5.0 2017 10 6 16 52.0 1.0
32452 不知道起什么名字好 2017-07-07 16:27:00 sml-str40 杏仁 炒奶糊 浓浓的 杏仁 味好 食 其他 地方 都 食 唔 道 特地来 食 很好 很好 很好 521698 4.0 2017 7 4 16 38.0 1.0
32453 mingmin9 2017-06-18 22:38:00 sml-str50 从 我 初中 时期 开 到 现在 店内 虽然 环境 不 大 可以 称得上 是 老字号 店 啦... 非常好 非常好 非常好 521698 5.0 2017 6 6 22 161.0 1.0
32454 henry_gzw 2016-11-14 15:13:00 sml-str40 位于 西华路 广州 有名 的 食街 这家 店 做 的 时间 应该 算是 数一数二 的 已 出... 非常好 521698 4.0 2016 11 0 15 204.0 1.0
32455 bre比 2016-07-02 01:46:00 sml-str50 从家 下楼 走 分钟 就 可以 吃 甜品 好 方便 这家 店 起码 在 我 初中 懂事 的 ... 非常好 非常好 非常好 521698 5.0 2016 7 5 1 255.0 1.0
32456 eaterp 2016-05-13 21:12:00 sml-str40 慕名而来 感觉 还是 挺不错 的 地方 虽然 不 大 但是 环境 不错 服务 一般 吧 不过... 很好 521698 4.0 2016 5 4 21 151.0 1.0
32457 丫琪_6831 2016-01-07 13:50:00 sml-str10 口味 好 一般 店员 态度 真的 好差 做生意 做成 这样 不会 再 去 了 521698 1.0 2016 1 3 13 38.0 0.0
32458 QI_285010384 2015-10-31 22:41:00 sml-str10 服务 太度 差 出品 慢 味道 比开 记差 521698 1.0 2015 10 5 22 21.0 0.0
32459 iiiookkk 2015-10-06 19:09:00 sml-str50 千里迢迢 跑过来 不 枉 此行 好吃 非常好 很好 非常好 521698 5.0 2015 10 1 19 18.0 1.0
32460 C+CL 2015-06-28 22:14:00 sml-str40 赞 味道 很 不错 双皮奶 很 好吃 就是 比较 贵 而且 分量 有点 少 非常好 很好 521698 4.0 2015 6 6 22 37.0 1.0
32461 dpuser_0178821948 2015-02-02 20:41:00 sml-str40 回 湖南 前 特别 想 吃 广州 的 甜品 为了 让 他 送外 卖点 了 五份 吃 的 好 ... 很好 很好 非常好 521698 4.0 2015 2 0 20 69.0 1.0
32462 Eblank造梦 2014-07-16 21:20:00 sml-str40 凤凰 炒奶 吃 到 最后 还有 一个 未熟 的 蛋黄 味道 很 好吃 过 都 说好 店面 有... 很好 521698 4.0 2014 7 2 21 59.0 1.0
32463 识事务者 2014-05-19 22:03:00 sml-str40 水准 还 可 不过 正如 网支 所 讲 有用 塑料产品 代替 有 些许 倒胃口 非常好 521698 4.0 2014 5 0 22 39.0 1.0
32464 睇我唔岛 2013-09-20 20:21:00 sml-str10 升价后 太少 人 去 食 食物 唔 新鲜 今晚 打包 个 芝麻 胡翻 屋企 食一食 落口 一... 一般 521698 1.0 2013 9 4 20 68.0 0.0
32465 CarolLokyee 2013-08-01 21:11:00 sml-str20 外卖 好像 要 买 五碗 才 送 有时候 多人 连 电话 也 不 听 态度 极差 到 店面 ... 一般 521698 2.0 2013 8 3 21 70.0 0.0
32466 小琼豆豆 2013-08-01 12:23:00 sml-str40 店面 很 不起眼 在 西华路 里面 以前 价钱 很 划算 现在 升价 了 就 比较 少 吃 了 很好 很好 很好 521698 4.0 2013 8 3 12 47.0 1.0
32467 withdraw 2013-05-09 18:33:00 sml-str40 甜品 老店 每次 来 这里 就 要点 一碗 红豆 双皮奶 奶香 红豆 料足 吃 起来 很 舒... 很好 很好 很好 521698 4.0 2013 5 3 18 97.0 1.0
32468 台狼棒会 2013-05-02 18:40:00 sml-str40 今天 专门 去 西华路 美食 之旅 所以 也 来 了 这家 店 早上 点多 去 的 还 没 ... 很好 很好 521698 4.0 2013 5 3 18 108.0 1.0
32469 我就是一只蛙 2013-04-24 23:20:00 sml-str50 好 好吃 真的 不错 一级 推介 苏 上门 吃 过 不过 就系 服务态度 有点 差 接受 到... 很好 521698 5.0 2013 4 2 23 62.0 1.0
32470 与猫看日落 2013-01-25 17:53:00 sml-str50 甜品 的话 这家 已经 很 好 了 老城区 好 有 广州 格调 街坊 生意 做 得 非常 好... 非常好 非常好 非常好 521698 5.0 2013 1 4 17 79.0 1.0
32471 lilycat10 2013-01-25 17:42:00 sml-str50 真的 是 起沙 的 红 豆沙 非常 好 价钱 便宜 附近 的 邻居 有福 了 推荐 非常好 非常好 非常好 521698 5.0 2013 1 4 17 41.0 1.0
32472 木頭woodwood 2012-02-22 04:27:00 sml-str10 年前 啱 搬 嚟 呢 頭 嘅 時 候 呢 間 嘢 喺 我 逢 星期五 嘅 宵夜 朋友 嚟 都... 一般 一般 521698 1.0 2012 2 2 4 190.0 0.0
32473 mj19910916 2011-12-30 18:44:00 sml-str50 这里 好吃 得 太 离谱 了 吧 简直 就是 惊艳 曾经 冒名 去过 北京路 和 东 山口 ... 非常好 非常好 非常好 521698 5.0 2011 12 4 18 216.0 1.0
32480 winny311111 2018-05-14 03:09:00 sml-str50 第二次 来 好吃 第二次 来 好吃 第二次 来 好吃 非常好 非常好 非常好 521698 5.0 2018 5 0 3 26.0 1.0
32481 Polykat_年嫿 2018-04-28 02:33:00 sml-str50 兒時 的 味道 兒時 的 味道 兒時 的 味道 非常好 很好 521698 5.0 2018 4 5 2 23.0 1.0
32482 不瘦到120斤不换ID 2018-04-09 01:22:00 sml-str50 好喝 好喝 好喝 好喝 好喝 好喝 好喝 好喝 好喝 好喝 好喝 好喝 好喝 好喝 好喝 好... 非常好 非常好 非常好 521698 5.0 2018 4 0 1 56.0 1.0

21691 rows × 15 columns

文本特征处理

中文文本特征处理,需要进行中文分词,jieba分词库简单好用。接下来需要过滤停用词,网上能够搜到现成的。最后就要进行文本转向量,有词库表示法、TF-IDF、word2vec等,这篇文章作了详细介绍,推荐一波 https://zhuanlan.zhihu.com/p/44917421

这里我们使用sklearn库的TF-IDF工具进行文本特征提取。

#切分测试集、训练集
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(data_model['cus_comment'], data_model['target'], random_state=3, test_size=0.25)

#引入停用词
infile = open("stopwords.txt",encoding='utf-8')
stopwords_lst = infile.readlines()
stopwords = [x.strip() for x in stopwords_lst]

#中文分词
def fenci(train_data):
    words_df = train_data.apply(lambda x:' '.join(jieba.cut(x)))
    return words_df
 
x_train[:5]
26328    冲着 老字号 去 的 但 真的 不 咋 地 所有 的 东西 都 不是 先 做 的 点 了 煎...
3457                 名过其实 味道 一般 全是 人 价格 也 贵 感觉 碗碟 都 洗 不 干净
17834    香芋 西米 以前 系 北京路 个边 上班 落 左班 都 会同 同事 去 吃糖 上个星期 去 ...
7904     南信 的 双皮奶 非常 滑 不是 很甜 可是 很嫩 非常 美味 还有 鲜虾 肠有 好多好多 ...
3258     环境 真的 是 一般 可能 是 老店 的 关系 但 很 传统 双皮奶 奶味重 甜度 适中 粥...
Name: cus_comment, dtype: object
#使用TF-IDF进行文本转向量处理
from sklearn.feature_extraction.text import TfidfVectorizer
tv = TfidfVectorizer(stop_words=stopwords, max_features=3000, ngram_range=(1,2))
tv.fit(x_train)
C:\Users\Administrator\Anaconda3\lib\site-packages\sklearn\feature_extraction\text.py:300: UserWarning: Your stop_words may be inconsistent with your preprocessing. Tokenizing the stop words generated tokens ['ain', 'aren', 'couldn', 'didn', 'doesn', 'don', 'hadn', 'hasn', 'haven', 'isn', 'lex', 'll', 'mon', 'null', 'shouldn', 've', 'wasn', 'weren', 'won', 'wouldn', '12', 'li', 'zxfitl'] not in stop_words.
  'stop_words.' % sorted(inconsistent))





TfidfVectorizer(analyzer='word', binary=False, decode_error='strict',
        dtype=<class 'numpy.float64'>, encoding='utf-8', input='content',
        lowercase=True, max_df=1.0, max_features=3000, min_df=1,
        ngram_range=(1, 2), norm='l2', preprocessor=None, smooth_idf=True,
        stop_words=['!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '--', '.', '..', '...', '......', '...................', './', '.一', '记者', '数', '年', '月', '日', '时', '分', '秒', '/', '//', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', '://', '::', ';', '<', '=', '>', '>>', '?', '@'...3', '94', '95', '96', '97', '98', '99', '100', '01', '02', '03', '04', '05', '06', '07', '08', '09'],
        strip_accents=None, sublinear_tf=False,
        token_pattern='(?u)\\b\\w\\w+\\b', tokenizer=None, use_idf=True,
        vocabulary=None)

机器学习建模

特征和标签已经准备好了,接下来就是建模了。这里我们使用文本分类的经典算法朴素贝叶斯算法,而且朴素贝叶斯算法的计算量较少。特征值是评论文本经过TF-IDF处理的向量,标签值评论的分类共两类,好评是1,差评是0。情感评分为分类器预测分类1的概率值。

#计算分类效果的准确率
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import roc_auc_score, f1_score
classifier = MultinomialNB()
classifier.fit(tv.transform(x_train), y_train)
classifier.score(tv.transform(x_test), y_test)
0.9275308869629356
#计算分类器的AUC值
y_pred = classifier.predict_proba(tv.transform(x_test))[:,1]
roc_auc_score(y_test,y_pred)
0.889712635344161
#计算一条评论文本的情感评分
def ceshi(model,strings):
    strings_fenci = fenci(pd.Series([strings]))
    return float(model.predict_proba(tv.transform(strings_fenci))[:,1])
#从大众点评网找两条评论来测试一下
test1 = '很好吃,环境好,所有员工的态度都很好,上菜快,服务也很好,味道好吃,都是用蒸馏水煮的,推荐,超好吃' #5星好评
test2 = '糯米外皮不绵滑,豆沙馅粗躁,没有香甜味。12元一碗不值。' #1星差评
print('好评实例的模型预测情感得分为{}\n差评实例的模型预测情感得分为{}'.format(ceshi(classifier,test1),ceshi(classifier,test2)))
Building prefix dict from the default dictionary ...
Loading model from cache C:\Users\ADMINI~1\AppData\Local\Temp\jieba.cache
Loading model cost 1.330 seconds.
Prefix dict has been built succesfully.


好评实例的模型预测情感得分为0.824812345120737
差评实例的模型预测情感得分为0.7751377818748739

可以看出,准确率和AUC值都非常不错的样子,但点评网上的实际测试中,5星好评模型预测出来了,1星差评缺预测错误。为什么呢?我们查看一下混淆矩阵

from sklearn.metrics import confusion_matrix
y_predict = classifier.predict(tv.transform(x_test))
cm = confusion_matrix(y_test, y_predict)
cm
array([[  44,  387],
       [   6, 4986]], dtype=int64)

可以看出,负类的预测非常不准,433单准确预测为负类的只有15.7%,应该是由于数据不平衡导致的,模型的默认阈值为输出值的中位数。比如逻辑回归的输出范围为[0,1],当某个样本的输出大于0.5就会被划分为正例,反之为反例。在数据的类别不平衡时,采用默认的分类阈值可能会导致输出全部为正例,产生虚假的高准确度,导致分类失败。

处理样本不均衡问题的方法,首先可以选择调整阈值,使得模型对于较少的类别更为敏感,或者选择合适的评估标准,比如ROC或者F1,而不是准确度(accuracy)。另外一种方法就是通过采样(sampling)来调整数据的不平衡。其中欠采样抛弃了大部分正例数据,从而弱化了其影响,可能会造成偏差很大的模型,同时,数据总是宝贵的,抛弃数据是很奢侈的。另外一种是过采样,下面我们就使用过采样方法来调整。

过采样(单纯复制)

单纯的重复了反例,因此会过分强调已有的反例。如果其中部分点标记错误或者是噪音,那么错误也容易被成倍的放大。因此最大的风险就是对反例过拟合。

data['target'].value_counts()
1.0    19916
0.0     1779
Name: target, dtype: int64
#把0类样本复制10次,构造训练集
index_tmp = y_train==0
y_tmp = y_train[index_tmp]
x_tmp = x_train[index_tmp]
x_train2 = pd.concat([x_train,x_tmp,x_tmp,x_tmp,x_tmp,x_tmp,x_tmp,x_tmp,x_tmp,x_tmp,x_tmp])
y_train2 = pd.concat([y_train,y_tmp,y_tmp,y_tmp,y_tmp,y_tmp,y_tmp,y_tmp,y_tmp,y_tmp,y_tmp])
#使用过采样样本(简单复制)进行模型训练,并查看准确率
clf2 = MultinomialNB()
clf2.fit(tv.transform(x_train2), y_train2)
y_pred2 = clf2.predict_proba(tv.transform(x_test))[:,1]
roc_auc_score(y_test,y_pred2)
0.899220190820394
#查看此时的混淆矩阵
y_predict2 = clf2.predict(tv.transform(x_test))
cm = confusion_matrix(y_test, y_predict2)
cm
array([[ 326,  105],
       [ 654, 4338]], dtype=int64)

可以看出,即使是简单粗暴的复制样本来处理样本不平衡问题,负样本的识别率大幅上升了,变为77%,满满的幸福感呀~我们自己写两句评语来看看

ceshi(clf2,'排队人太多,环境不好,口味一般')
0.352913902404629

可以看出把0类别的识别出来了,太棒了~

过采样(SMOTE算法)

SMOTE(Synthetic minoritye over-sampling technique,SMOTE),是在局部区域通过K-近邻生成了新的反例。相较于简单的过采样,SMOTE降低了过拟合风险,但同时运算开销加大

对SMOTE感兴趣的同学可以看下这篇文章https://www.jianshu.com/p/ecbc924860af

#使用SMOTE进行样本过采样处理
from imblearn.over_sampling import SMOTE
oversampler=SMOTE(random_state=0)
x_train_vec = tv.transform(x_train)
x_resampled, y_resampled = oversampler.fit_sample(x_train_vec, y_train)
#原始的样本分布
y_train.value_counts()
1.0    14920
0.0     1348
Name: target, dtype: int64
#经过SMOTE算法过采样后的样本分布情况
pd.Series(y_resampled).value_counts()
1.0    14920
0.0    14920
dtype: int64

我们经过插值,把0类数据也丰富为14923个数据了,这时候正负样本的比例为1:1,接下来我们用平衡后的数据进行训练,效果如何呢,好期待啊~

#使用过采样样本(SMOTE)进行模型训练,并查看准确率
clf3 = MultinomialNB()
clf3.fit(x_resampled, y_resampled)
y_pred3 = clf3.predict_proba(tv.transform(x_test))[:,1]
roc_auc_score(y_test,y_pred3)
0.9010351597358558
#查看此时的准确率
y_predict3 = clf3.predict(tv.transform(x_test))
cm = confusion_matrix(y_test, y_predict3)
cm
array([[ 326,  105],
       [ 613, 4379]], dtype=int64)
#到网上找一条差评来测试一下情感评分的预测效果
test3 = '糯米外皮不绵滑,豆沙馅粗躁,没有香甜味。12元一碗不值。'
ceshi(clf3,test3)
0.22919320383366565

可以看出,使用SMOTE插值与简单的数据复制比起来,AUC率略有提高,实际预测效果也挺好

模型评估测试

接下来我们把3W条数据都拿来训练,数据量变多了,模型效果应该会更好

#词向量训练
tv2 = TfidfVectorizer(stop_words=stopwords, max_features=3000, ngram_range=(1,2))
tv2.fit(data_model['cus_comment'])

#SMOTE插值
X_tmp = tv2.transform(data_model['cus_comment'])
y_tmp = data_model['target']
sm = SMOTE(random_state=0)
X,y = sm.fit_sample(X_tmp, y_tmp)

clf = MultinomialNB()
clf.fit(X, y)

def fenxi(strings):
    strings_fenci = fenci(pd.Series([strings]))
    return float(clf.predict_proba(tv2.transform(strings_fenci))[:,1])
C:\Users\Administrator\Anaconda3\lib\site-packages\sklearn\feature_extraction\text.py:300: UserWarning: Your stop_words may be inconsistent with your preprocessing. Tokenizing the stop words generated tokens ['ain', 'aren', 'couldn', 'didn', 'doesn', 'don', 'hadn', 'hasn', 'haven', 'isn', 'lex', 'll', 'mon', 'null', 'shouldn', 've', 'wasn', 'weren', 'won', 'wouldn', '12', 'li', 'zxfitl'] not in stop_words.
  'stop_words.' % sorted(inconsistent))
#到网上找一条差评来测试一下
fenxi('糯米外皮不绵滑,豆沙馅粗躁,没有香甜味。12元一碗不值。')
0.2723496698366991

只用到了简单的机器学习,就做出了不错的情感分析效果,知识的力量真是强大呀,666~

后续优化方向

  • 使用更复杂的机器学习模型如神经网络、支持向量机等
  • 模型的调参
  • 行业词库的构建
  • 增加数据量
  • 优化情感分析的算法
  • 增加标签提取等
  • 项目部署到服务器上,更好地分享和测试模型的效果

猜你喜欢

转载自blog.csdn.net/weixin_40903057/article/details/89706111