1. 簡介python
如今情感分析有很普遍的應用,例如:git
評論分析與決策,經過對產品多維度評論觀點進行傾向性分析,給用戶提供該產品全方位的評價,方便用戶進行決策github
評論分類,經過對評論進行情感傾向性分析,將不一樣用戶對同一事件或對象的評論內容按情感極性予以分類展現json
輿情監控,經過對須要輿情監控的實時文字數據流進行情感傾向性分析,把握用戶對熱點信息的情感傾向性變化網絡
等等併發
百度針對情感分析也提供了多種解決方案,包括:app
百度情感傾向分析服務:對包含主觀信息的文本進行情感傾向性判斷,可支持在線訓練模型調優效果,爲口碑分析、話題監控、輿情分析等應用提供幫助。ide
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'))
三、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
四、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'])
五、功能評測:
選用不一樣的數據對情感分類的準確性進行測試。具體案例以下:
"這個賓館比較陳舊了,特價的房間也很通常。整體來講通常",
"交通方便;環境很好;服務態度很好 房間較小",
"稍微重了點,多是硬盤大的原故,還要再輕半斤就行了。" ,
"服務很不錯,下次還會來。" ,
"前臺接待太差,下次不會再選擇入住此店啦",
"菜作的很好,味道很不錯。" ,
"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.三、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
六、結論及建議
經過測試發現不論直接調用百度情感分析服務仍是使用百度ERINE模型,對情感分析都有很好、很準確的結果。百度情感分析服務調用起來更加的方便,不須要使用者掌握太多的深度學習方面的技術,適用於絕大多數的應用場景。
PaddleHub情感分析模型庫,是一個針對情感分析的模型庫,而且針對情感分析場景進行了預訓練,支持FineTune,不過即便沒有FineTune也能夠直接用於情感分析,調用起來比較方便。不過須要使用者掌握必定的深度學習方面的技術。
ERINE模型是一個通用模型給與用戶更大的靈活性,能夠根據本身的須要定製化的開發適合本身的引用,不過須要對深度學習及Paddle Paddle有比較深刻的瞭解。你們能夠根據本身的實際狀況選擇適合的技術。