赞
踩
1. 简介
现在情感分析有很广泛的应用,例如:
评论分析与决策,通过对产品多维度评论观点进行倾向性分析,给用户提供该产品全方位的评价,方便用户进行决策
评论分类,通过对评论进行情感倾向性分析,将不同用户对同一事件或对象的评论内容按情感极性予以分类展示
舆情监控,通过对需要舆情监控的实时文字数据流进行情感倾向性分析,把握用户对热点信息的情感倾向性变化
等等
百度针对情感分析也提供了多种解决方案,包括:
百度情感倾向分析服务:对包含主观信息的文本进行情感倾向性判断,可支持在线训练模型调优效果,为口碑分析、话题监控、舆情分析等应用提供帮助。
ERINE模型:今年百度发布了知识增强的语义表示模型 ERNIE(Enhanced Representation from kNowledge IntEgration),并发布了基于 PaddlePaddle 的开源代码与模型,在语言推断、语义相似度、命名实体识别、情感分析、问答匹配等自然语言处理(NLP)各类中文任务上的验证显示,模型效果全面超越 BERT。
情感倾向分析(Sentiment Classification,简称Senta)针对带有主观描述的中文文本,可自动判断该文本的情感极性类别并给出相应的置信度,能够帮助企业理解用户消费习惯、分析热点话题和危机舆情监控,为企业提供有利的决策支持。PaddleHub现在这方面的模型有:senta_lstm,senta_gru,senta_cnn,senta_bow,senta_bilstm,emotion_detection_textcnn等。这些PaddleHub Module预训练数据集为百度自建数据集,支持预测和Fine-tune。
本文对使用百度情感倾向分析服务进行在线情感分析及使用百度ERINE模型、PaddleHub情感分析模型进行离线情感分析进行评测分析,并提供了详细的使用攻略及代码,方便大家使用。
2 情感倾向分析API调用攻略(Python3)
2.1 认证授权:
在开始调用任何API之前需要先进行认证授权,具体的说明请参考:
http://ai.baidu.com/docs#/Auth/top
具体Python3代码如下:
# -*- coding: utf-8 -*- #!/usr/bin/env python import urllib import json #client_id 为官网获取的AK, client_secret 为官网获取的SK client_id =【百度云应用的AK】 client_secret =【百度云应用的SK】 #获取token def get_token(): host = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=' + client_id + '&client_secret=' + client_secret request = urllib.request.Request(host) request.add_header('Content-Type', 'application/json; charset=UTF-8') response = urllib.request.urlopen(request) token_content = response.read() if token_content: token_info = json.loads(token_content) token_key = token_info['access_token'] return token_key
2.2 情感倾向分析接口调用:
详细说明请参考:http://ai.baidu.com/docs#/NLP-API/57b9b630
接口描述
情感倾向分析接口(通用版):自动对包含主观信息的文本进行情感倾向性判断(积极、消极、中性),并给出相应的置信度。为口碑分析、话题监控、舆情分析等应用提供基础技术支持,同时支持用户自行定制模型效果调优。
请求说明
HTTP方法: POST
请求URL: https://aip.baidubce.com/rpc/2.0/nlp/v1/sentiment_classify
URL参数:
参数 值
access_token 通过API Key和Secret Key获取的access_token,参考“Access Token获取”
Header如下:
参数 值
Content-Type application/json
Body请求示例:
{
"text": "苹果是一家伟大的公司"
}
请求参数
参数 类型 描述 是否必填
text string 文本内容,最大2048字节
返回说明
参数 说明 描述
log_id uint64 请求唯一标识码
sentiment int 表示情感极性分类结果,0:负向,1:中性,2:正向
confidence float 表示分类的置信度,取值范围[0,1]
positive_prob float 表示属于积极类别的概率 ,取值范围[0,1]
negative_prob float 表示属于消极类别的概率,取值范围[0,1]
Python3调用代码如下:
#调用情感分类接口 def get_classify(content): print (content) token=get_token() url = 'https://aip.baidubce.com/rpc/2.0/nlp/v1/sentiment_classify' params = dict() params['text'] = content params = json.dumps(params).encode('utf-8') access_token = token url = url + "?access_token=" + access_token request = urllib.request.Request(url=url, data=params) request.add_header('Content-Type', 'application/json') response = urllib.request.urlopen(request) content = response.read() if content: content=content.decode('gb2312') #print (content) data = json.loads(content) data=data['items'][0] sentiment=data['sentiment'] if sentiment==0: sentiment='负向' elif sentiment==1: sentiment='中性' else: sentiment='正向' print ('情感分类结果:',sentiment) print ('分类的置信度:',data['confidence']) print ('积极类别概率:',data['positive_prob']) print ('消极类别概率:',data['negative_prob']) test_list = [ "这个宾馆比较陈旧了,特价的房间也很一般。总体来说一般", "交通方便;环境很好;服务态度很好 房间较小", "稍微重了点,可能是硬盘大的原故,还要再轻半斤就好了。" , "服务很不错,下次还会来。" , "前台接待太差,下次不会再选择入住此店啦", "菜做的很好,味道很不错。" , "19天硬盘就罢工了,算上运来的一周都没用上15天,你说这算什么事呀", "现在是高峰期,人太多了,我们晚点来吧" ] import datetime print (datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')) for text in test_list: get_classify(text) print (datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
3、ERINE模型
ERNIE 通过建模海量数据中的词、实体及实体关系,学习真实世界的语义知识。相较于 BERT 学习原始语言信号,ERNIE 直接对先验语义知识单元进行建模,增强了模型语义表示能力,以 Transformer 为网络基本组件,以Masked Bi-Language Model和 Next Sentence Prediction 为训练目标,通过预训练得到通用语义表示,再结合简单的输出层,应用到下游的 NLP 任务。我们可以使用ERINE进行情感分类,具体步骤如下:
1,首先我们要在PaddleHub中选择ernie作为预训练模型,进行Fine-tune。ChnSentiCorp数据集是一个中文情感分类数据集。PaddleHub已支持加载该数据集。关于该数据集,详情请查看ChnSentiCorp数据集使用。
https://github.com/PaddlePaddle/PaddleHub/wiki/PaddleHub-API:-Dataset
2,生成Reader:接着生成一个文本分类的reader,reader负责将dataset的数据进行预处理,首先对文本进行切词,接着以特定格式组织并输入给模型进行训练。
ClassifyReader的参数有以下三个:
dataset: 传入PaddleHub Dataset;
vocab_path: 传入ERNIE/BERT模型对应的词表文件路径;
max_seq_len: ERNIE模型的最大序列长度,若序列长度不足,会通过padding方式补到max_seq_len, 若序列长度大于该值,则会以截断方式让序列长度为max_seq_len;
3,选择Fine-Tune优化策略,适用于ERNIE/BERT这类Transformer模型的迁移优化策略为AdamWeightDecayStrategy。详情请查看Strategy。
AdamWeightDecayStrategy的参数有以下三个:
learning_rate: 最大学习率
lr_scheduler: 有linear_decay和noam_decay两种衰减策略可选
warmup_proprotion: 训练预热的比例,若设置为0.1, 则会在前10%的训练step中学习率逐步提升到learning_rate
weight_decay: 权重衰减,类似模型正则项策略,避免模型overfitting
optimizer_name: 优化器名称,使用Adam
4,选择运行时配置
在进行Finetune前,我们可以设置一些运行时的配置,例如如下代码中的配置,表示:
use_cuda:设置为False表示使用CPU进行训练。如果您本机支持GPU,且安装的是GPU版本的PaddlePaddle,我们建议您将这个选项设置为True;
epoch:要求Finetune的任务只遍历1次训练集;
batch_size:每次训练的时候,给模型输入的每批数据大小为32,模型训练时能够并行处理批数据,因此batch_size越大,训练的效率越高,但是同时带来了内存的负荷,过大的batch_size可能导致内存不足而无法训练,因此选择一个合适的batch_size是很重要的一步;
log_interval:每隔10 step打印一次训练日志;
eval_interval:每隔50 step在验证集上进行一次性能评估;
checkpoint_dir:将训练的参数和数据保存到ernie_txt_cls_turtorial_demo目录中;
strategy:使用DefaultFinetuneStrategy策略进行finetune;
更多运行配置,请查看RunConfig
5,组建Finetune Task
有了合适的预训练模型和准备要迁移的数据集后,我们开始组建一个Task。
获取module的上下文环境,包括输入和输出的变量,以及Paddle Program;
从输出变量中找到用于情感分类的文本特征pooled_output;
在pooled_output后面接入一个全连接层,生成Task;
6,开始Finetune
选择finetune_and_eval接口来进行模型训练,这个接口在finetune的过程中,会周期性的进行模型效果的评估,以便我们了解整个训练过程的性能变化。
7,使用模型进行预测
当Finetune完成后,使用模型来进行预测
具体代码如下:
from paddle.fluid.framework import switch_main_program import paddlehub as hub import paddle.fluid as fluid module = hub.Module(name="ernie", version="1.0.1") dataset = hub.dataset.ChnSentiCorp() #生成Reader reader = hub.reader.ClassifyReader( dataset=dataset, vocab_path=module.get_vocab_path(), max_seq_len=128) #选择Fine-Tune优化策略 strategy = hub.AdamWeightDecayStrategy( weight_decay=0.01, warmup_proportion=0.1, learning_rate=5e-5, lr_scheduler="linear_decay", optimizer_name="adam") #选择运行时配置 config = hub.RunConfig( use_cuda=True, num_epoch=1, checkpoint_dir="ernie_txt_cls_turtorial_demo", batch_size=32, log_interval=10, eval_interval=50, strategy=strategy) #组建Finetune Task inputs, outputs, program = module.context( trainable=True, max_seq_len=128) # Use "pooled_output" for classification tasks on an entire sentence. pooled_output = outputs["pooled_output"] feed_list = [ inputs["input_ids"].name, inputs["position_ids"].name, inputs["segment_ids"].name, inputs["input_mask"].name, ] cls_task = hub.TextClassifierTask( data_reader=reader, feature=pooled_output, feed_list=feed_list, num_classes=dataset.num_labels, config=config) #开始Finetune cls_task.finetune_and_eval() #使用模型进行预测 # coding: utf-8 from __future__ import absolute_import from __future__ import division from __future__ import print_function import numpy as np import os import paddle import paddle.fluid as fluid import paddlehub as hub # loading Paddlehub ERNIE pretrained model module = hub.Module(name="ernie") inputs, outputs, program = module.context(max_seq_len=128) # Sentence classification dataset reader dataset = hub.dataset.ChnSentiCorp() reader = hub.reader.ClassifyReader( dataset=dataset, vocab_path=module.get_vocab_path(), max_seq_len=128) # Construct transfer learning network # Use "pooled_output" for classification tasks on an entire sentence. # Use "sequence_output" for token-level output. pooled_output = outputs["pooled_output"] # Setup feed list for data feeder # Must feed all the tensor of ERNIE's module need feed_list = [ inputs["input_ids"].name, inputs["position_ids"].name, inputs["segment_ids"].name, inputs["input_mask"].name, ] strategy = hub.AdamWeightDecayStrategy( weight_decay=0.01, warmup_proportion=0.1, learning_rate=5e-5, lr_scheduler="linear_decay", optimizer_name="adam") # Setup runing config for PaddleHub Finetune API config = hub.RunConfig( use_data_parallel=False, use_pyreader=False, use_cuda=True, batch_size=32, enable_memory_optim=False, checkpoint_dir="ernie_txt_cls_turtorial_demo", strategy=strategy) # Define a classfication finetune task by PaddleHub's API cls_task = hub.TextClassifierTask( data_reader=reader, feature=pooled_output, feed_list=feed_list, num_classes=dataset.num_labels, config=config) # Data to be prdicted data = [ ["这个宾馆比较陈旧了,特价的房间也很一般。总体来说一般"], ["交通方便;环境很好;服务态度很好 房间较小"], ["稍微重了点,可能是硬盘大的原故,还要再轻半斤就好了。" ], ["服务很不错,下次还会来。" ], ["前台接待太差,下次不会再选择入住此店啦"], ["菜做的很好,味道很不错。" ], ["19天硬盘就罢工了,算上运来的一周都没用上15天,你说这算什么事呀"], ["现在是高峰期,人太多了,我们晚点来吧"] ] index = 0 run_states = cls_task.predict(data=data) results = [run_state.run_results for run_state in run_states] for batch_result in results: # get predict index batch_result = np.argmax(batch_result, axis=2)[0] for result in batch_result: if result==1: result='正向' else: result='负向' print(data[index][0], result) index += 1
4、PaddleHub情感分析模型(以senta_bilstm为例)
模型概述
情感倾向分析(Sentiment Classification,简称Senta)针对带有主观描述的中文文本,可自动判断该文本的情感极性类别并给出相应的置信度,能够帮助企业理解用户消费习惯、分析热点话题和危机舆情监控,为企业提供有利的决策支持。该模型基于一个双向LSTM结构,情感类型分为积极、消极。该PaddleHub Module支持预测和Fine-tune。
参数:
data:dict类型,key为text,str类型;value为待预测文本,list类型。
返回:
results:list类型,每个元素为对应输入文本的预测结果。预测结果为dict类型,有以下字段:
text字段存放原输入待预测文本;
sentiment_label为情感分类结果对应的label;
sentiment_key表示分类结果为positive或是negative;
positive_probs为原输入文本对应positive的概率值;
negative_probs为原输入文本对应negative的概率值;
调用代码:
import paddlehub as hub senta = hub.Module(name="senta_bilstm") test_text = [ "这个宾馆比较陈旧了,特价的房间也很一般。总体来说一般", "交通方便;环境很好;服务态度很好 房间较小", "稍微重了点,可能是硬盘大的原故,还要再轻半斤就好了。" , "服务很不错,下次还会来。" , "前台接待太差,下次不会再选择入住此店啦", "菜做的很好,味道很不错。" , "19天硬盘就罢工了,算上运来的一周都没用上15天,你说这算什么事呀", "现在是高峰期,人太多了,我们晚点来吧" ] input_dict = {"text": test_text} results = senta.sentiment_classify(data=input_dict) for result in results: print(result['text']) print(result['sentiment_label']) print(result['sentiment_key']) print(result['positive_probs']) print(result['negative_probs'])
5、功能评测:
选用不同的数据对情感分类的准确性进行测试。具体案例如下:
"这个宾馆比较陈旧了,特价的房间也很一般。总体来说一般",
"交通方便;环境很好;服务态度很好 房间较小",
"稍微重了点,可能是硬盘大的原故,还要再轻半斤就好了。" ,
"服务很不错,下次还会来。" ,
"前台接待太差,下次不会再选择入住此店啦",
"菜做的很好,味道很不错。" ,
"19天硬盘就罢工了,算上运来的一周都没用上15天,你说这算什么事呀",
"现在是高峰期,人太多了,我们晚点来吧"
5.1 情感分析API结果:
这个宾馆比较陈旧了,特价的房间也很一般。总体来说一般
情感分类结果: 负向
分类的置信度: 0.943242
积极类别概率: 0.025541
消极类别概率: 0.974459
交通方便;环境很好;服务态度很好 房间较小
情感分类结果: 正向
分类的置信度: 0.890898
积极类别概率: 0.950904
消极类别概率: 0.049096
稍微重了点,可能是硬盘大的原故,还要再轻半斤就好了。
情感分类结果: 负向
分类的置信度: 0.0922925
积极类别概率: 0.408468
消极类别概率: 0.591532
服务很不错,下次还会来。
情感分类结果: 正向
分类的置信度: 0.990288
积极类别概率: 0.99563
消极类别概率: 0.00437049
前台接待太差,下次不会再选择入住此店啦
情感分类结果: 负向
分类的置信度: 0.980575
积极类别概率: 0.00874128
消极类别概率: 0.991259
菜做的很好,味道很不错。
情感分类结果: 正向
分类的置信度: 0.959412
积极类别概率: 0.981735
消极类别概率: 0.0182646
19天硬盘就罢工了,算上运来的一周都没用上15天,你说这算什么事呀
情感分类结果: 负向
分类的置信度: 0.366781
积极类别概率: 0.284949
消极类别概率: 0.715051
现在是高峰期,人太多了,我们晚点来吧
情感分类结果: 正向
分类的置信度: 0.400084
积极类别概率: 0.730038
消极类别概率: 0.269962
5.2 ERINE的结果:
这个宾馆比较陈旧了,特价的房间也很一般。总体来说一般 负向
交通方便;环境很好;服务态度很好 房间较小 正向
稍微重了点,可能是硬盘大的原故,还要再轻半斤就好了。 负向
服务很不错,下次还会来。 正向
前台接待太差,下次不会再选择入住此店啦 负向
菜做的很好,味道很不错。 正向
19天硬盘就罢工了,算上运来的一周都没用上15天,你说这算什么事呀 负向
现在是高峰期,人太多了,我们晚点来吧 负向
5.3、PaddleHub情感分析模型(以senta_bilstm为例)
这个宾馆比较陈旧了,特价的房间也很一般。总体来说一般
0
negative
0.0103
0.9897
交通方便;环境很好;服务态度很好 房间较小
1
positive
0.9374
0.0626
稍微重了点,可能是硬盘大的原故,还要再轻半斤就好了。
0
negative
0.2237
0.7763
服务很不错,下次还会来。
1
positive
0.9891
0.0109
前台接待太差,下次不会再选择入住此店啦
0
negative
0.0057
0.9943
菜做的很好,味道很不错。
1
positive
0.9714
0.0286
19天硬盘就罢工了,算上运来的一周都没用上15天,你说这算什么事呀
0
negative
0.0266
0.9734
现在是高峰期,人太多了,我们晚点来吧
1
positive
0.7662
0.2338
6、结论及建议
通过测试发现不论直接调用百度情感分析服务还是使用百度ERINE模型,对情感分析都有很好、很准确的结果。百度情感分析服务调用起来更加的方便,不需要使用者掌握太多的深度学习方面的技术,适用于绝大多数的应用场景。
PaddleHub情感分析模型库,是一个针对情感分析的模型库,并且针对情感分析场景进行了预训练,支持FineTune,不过即使没有FineTune也可以直接用于情感分析,调用起来比较方便。不过需要使用者掌握一定的深度学习方面的技术。
ERINE模型是一个通用模型给与用户更大的灵活性,可以根据自己的需要定制化的开发适合自己的引用,不过需要对深度学习及Paddle Paddle有比较深入的了解。大家可以根据自己的实际情况选择适合的技术。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。