情感倾向分析针对带有主观描述的中文文本,可自动判断该文本的情感极性类别并给出相应的置信度。情感类型分为积极、消极、 中性。情感倾向分析能够帮助企业理解用户消费习惯、分析热点话题和危机舆情监控,为企业提供有力的决策支持。
上一次的 介绍 中我们讲解了情感分析的作用以及应用场景,技术难点以及百度 Senta 系统对这些问题的解决方法以及核心技术。本次的介绍我们则侧重于实践,即利用百度深度学习框架 PaddlePaddle Fluid, 实战 Senta 系统。
Senta 是百度开源的情感分析 (Sentiment Analysis) 系统,项目的 github 地址是 (https://github.com/baidu/Senta) ,Senta 也为百度 AI 开放平台(http://ai.baidu.com/tech/nlp/... 提供了情感倾向分析模块,供用户直接使用。
此次我们将讲解如何本地构建 Senta, 利用 PaddlePaddle Fluid深度学习框架来实现情感分析模型的训练和部署。
实验环境准备:安装 PaddlePaddle Fluid
运行本目录下的程序示例需要使用 PaddlePaddle Fluid v1.1/1.2 版本。
使用 pip 安装最新稳定版
Linux CPU
pip install paddlepaddle
Linux GPU cuda9cudnn7
pip install paddlepaddle-gpu
Linux GPU cuda8cudnn7
pip install paddlepaddle-gpu==1.1.0.post87
Linux GPU cuda8cudnn5
pip install paddlepaddle-gpu==1.1.0.post85
更详细的 whl 包列表也可以参见 whl 包列表.
源码编译安装
如果需要安装最新的开发版,请按照安装文档 中的说明更新PaddlePaddle Fluid 版本。
Senta 代码结构
Senta 项目的代码结构以及简介如下, 本文重点介绍如何利用 Fluid Python API 完成模型的构建和训练,关于如何利用Fluid C-API 进行模型的在线部署,可以参考该项目的说明文档。
Senta
├── C-API/ # 模型预测C-API接口
├── data/ # 数据集
│ ├── test_data/
│ │ └── corpus.test
│ ├── train_data/
│ │ └── corpus.train
│ └── train.vocab
├── eval.sh # 模型评价脚本
├── infer.sh # 模型预测脚本
├── nets.py # 本例中涉及的各种网络结构均定义在此文件中,│ # 若进一步修改模型结构,请查看此文件
├── README.md # 说明文档
├── sentiment_classify.py # 情感倾向分析主函数,包括训练、预估、预测 │ # 部分
├── train.sh # 模型训练脚本
└── utils.py # 定义通用的函数,例如加载词典,读入数据等
模型概览
nets.py 中包含以下几个模型:
• bow_net:Bow(Bag Of Words) 模型,是一个非序列模型。使用基本的全连接结构。
• cnn_net:浅层 CNN 模型,是一个基础的序列模型,能够处理变长的序列输入,提取一个局部区域之内的特征。
• gru_net:单层 GRU 模型,序列模型,能够较好地解序列文本中长距离依赖的问题。
• lstm_net:单层 LSTM 模型,序列模型,能够较好地解决序列文本中长距离依赖的问题。
• bilstm_net:双向单层 LSTM 模型,序列模型,通过采用双向lstm结构,更好地捕获句子中的语义特征。百度 AI 平台上情感倾向分析模块采用此模型进行训练和预测。
数据准备
数据格式
训练数据格式是制表符分隔值 (tsv) 的格式,每一行代表一条训练数据,以制表符作为分割符分为两个字段。第一个字段是情感倾向,取值为 0 或 1,分别代表消极和积极情感倾向;第二个字段是文本的内容。文本已经经过分词处理,词与词之间用空格分隔。示例训练样本如下:
0 方向盘 向 左 稍 有 偏斜 - - - - 上 四轮 定位 调整 两次 OK 。 价格 80元 , 4S 要 300多元 , 立马 和 他 说
0 人 非常 多 , 团购 的 平日 票 , 本来 以为 人 会 少 点 , 没想到 人山人海 。 有些 项目 小孩 不能 玩 , 小孩 对 造浪池 比较 感兴趣 , 其它 真 没 什么
可 玩 的 。
0 环境 口味 我 都 很满意 , 可是 那 服务态度 还 真 不能 让 人 恭维 ! 生意 好 也 不能 降低 服务态度 ! 味道 再 美味 我 消费 的 时候 还要 受气 的 话 我 也 不会 再 去 消费 了 !
1 国耻 , 不忘 历史 。
测试数据以同样的方式进行分隔,但在情感类别标签方面和训练数据有一些差别。测试数据中情感倾向共有三类,取值为 0, 1, 2, 分别代表消极,中性,积极。在模型的预测阶段,我们利用模型输出样例为积极和消极的概率,如果用于二分类,只要积极的概率比消极的概率高,就归入积极;而如果用于三分类,则在中间加入了中性,分类的依据是,样例为积极的概率小于 45% 则为消极,大于 55% 则为积极,介于二者之间则为中性,用户也可以根据需要调整中型情感的概率阈值。示例测试样本如下所示:
2 空间 是 可以 了 , 后面 坐 三个 170斤 的 人 也 不 嫌 挤 , 但 矮 了 点 , 后备箱 给力
1 满分 是 10分 的 话 , 性价比 给 8.5分 吧 ! 综合 油耗 偏高 , 如果 开市区 的 就 不太 合算 了 。
0 后排 中间 的 突起 太 高 , 中间 坐 人 不好 放 脚 。
1 一般 , 家用 还 可以 。
训练数据词典构建
因为深度学习模型的需要,需要把每一个词对应地转化为一个整数,为此要根据训练数据构建一个词典。而且还可以根据词典对词典的大小进行限制。这里使用的词典文件格式非常简单,每行代表词典中的一个词。以下是词典的示例:
喜欢
特
脏兮兮
...
注:我们在data目录下,提供了示例词典数据,详见 data/train.vocab.
关于词典构建的功能,参见 utils.py 中的 prepare_data(data_path, word_dict_path, batch_size, mode) 函数,词典加载的功能,参见 utils.py 中的 load_vocab(file_path) 函数。
使用自定义数据
因为实际使用的数据比较大,github 项目中仅自带了一份小的示例数据,如果需要使用自定义的数据, 将训练和测试需要用的语料处理成符合上述要求的格式,存放为 data/train_data/corpus.train 和 data/test_data/corpus.test 即可。
模型训练与预测
模型的训练,评价和预测都集成在 sentiment_classify.py 文件里,默认使用的模型是 bilstm_net 双向 LSTM 模型。默认使用 cpu 进行模型训练,但还可以支持使用 gpu, 通过 --use_gpu True 打开。另外,训练还支持并行,通过 --is_parallel参数设置。
具体支持的参数可以通过 python sentisentiment_classify.py --help 查看。
模型训练
python sentiment_classify.py \
--train_data_path ./data/train_data/corpus.train \ # 训练数据路径
--word_dict_path ./data/train.vocab \ # 词典路径
--mode train \ # train模式
--model_path ./models # 模型保存路径
使用 GPU 的训练脚本
export CUDA_VISIBLE_DEVICES=0,1 # 指定可用的 GPU 序号
python sentiment_classify.py \
--train_data_path ./data/train_data/corpus.train \ # 训练数据路径
--word_dict_path ./data/train.vocab \ # 词典路径
--mode train \ # train模式
--model_path ./models # 模型保存路径
--use_gpu True # 使用 GPU 训练模型
--is_parallel True # 使用并行
执行后可以看到如下的输出:一共对训练语料进行了 10 次迭代,并且输出了在测试数据集上的准确率和平均 cost.
也可以直接使用目录下的 train.sh 根据需要进行修改。
模型评价
python sentiment_classify.py \
--test_data_path ./data/test_data/corpus.test \ # 测试数据路径
--word_dict_path ./data/train.vocab \ # 词典路径
--mode eval \ # eval模式
--model_path ./models/epoch9/ # 预测模型路径
可以看到类似如下的输出
[test info] model_path: ./models/epoch9/, class2_acc: 0.828402, class3_acc: 0.710000
说明模型能够完成情感分类任务,只是因为示例数据集太小,过拟合比较明显,在训练数据集上准确率可以达到 99.9%, 而测试数据集上的二分类准确率只有 82.8%. 用户可以通过使用自定义的更大的数据集,以及调整模型超参数以获得更好的效果。
模型预测
python sentiment_classify.py \
--test_data_path ./data/test_data/corpus.test \ # 测试数据路径
--word_dict_path ./data/train.vocab \ # 词典路径
--mode infer \ # infer模式
--model_path ./models/epoch9/ # 预测模型路径
即可执行预测,可以得到类似如下的输出
predict label: 0, pos_prob: 0.004343, neg_prob: 0.995657
predict label: 2, pos_prob: 0.798888, neg_prob: 0.201112
predict label: 0, pos_prob: 0.000564, neg_prob: 0.999436
predict label: 0, pos_prob: 0.024923, neg_prob: 0.975077
predict label: 2, pos_prob: 0.999526, neg_prob: 0.000474
predict label: 2, pos_prob: 0.994914, neg_prob: 0.005086
predict label: 0, pos_prob: 0.065424, neg_prob: 0.934576
predict label: 0, pos_prob: 0.000119, neg_prob: 0.999881
predict label: 0, pos_prob: 0.000709, neg_prob: 0.999291
predict label: 2, pos_prob: 0.986198, neg_prob: 0.013802
.......
可以观察模型对于每一个样例的预测结果和详细情况。
扩展:处理未经加工的原始语料
上述的实验中,使用的训练和测试语料都已经经过分词处理,并且都被人工标了情感极性标签,用于训练和评价模型的能力,但是在实际应用中,面对的语料都是生语料,比如线上商品的评价信息,并没有经过分词之类的处理。这种情况下需要预先对语料进行加工处理,百度也开源了词法分析提供工具 LAC。
在本工程目录的 C-API 目录下,就有调用 LAC 进行分词并且结合上述模型完成情感分析所需的文件,将分词处理和情感分析集成在一起。具体的使用方法,可以进一步参考 Senta 项目的 说明文档, 以及 LAC 项目的 说明文档.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。