PaddlePaddle Fluid實戰:使用百度 Senta 情感分析
情感傾向分析針對帶有主觀描述的中文文字,可自動判斷該文字的情感極性類別並給出相應的置信度。情感型別分為積極、消極、 中性。情感傾向分析能夠幫助企業理解使用者消費習慣、分析熱點話題和危機輿情監控,為企業提供有力的決策支援。
上一次的 介紹 中詳細講解了情感分析的作用以及應用場景,技術難點以及百度 Senta 系統對這些問題的解決方法以及核心技術。本次的介紹我們則側重於實踐,即利用百度深度學習框架 PaddlePaddle Fluid, 實戰 Senta 系統。
Senta 是百度開源的情感分析 (Sentiment Analysis) 系統,專案的 github 地址是 (https://github.com/baidu/Senta) ,Senta 也為百度 AI 開放平臺(https://ai.baidu.com/tech/nlp/sentiment_classify) 提供了情感傾向分析模組,供使用者直接使用。
此次我們將講解如何本地構建 Senta, 利用 PaddlePaddle Fluid深度學習框架來實現情感分析模型的訓練和部署。
實驗環境準備:安裝 PaddlePaddle Fluid
執行本目錄下的程式示例需要使用 PaddlePaddle Fluid v1.1/1.2 版本。
使用 pip 安裝最新穩定版
# Linux CPUpip install paddlepaddle# Linux GPU cuda9cudnn7pip install paddlepaddle-gpu# Linux GPU cuda8cudnn7pip install paddlepaddle-gpu==1.1.0.post87# Linux GPU cuda8cudnn5pip 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 info]: pass_id: 0, avg_acc: 0.821615, avg_cost: 0.388542[train info]: pass_id: 1, avg_acc: 0.960837, avg_cost: 0.122814[train info]: pass_id: 2, avg_acc: 0.987280, avg_cost: 0.052349[train info]: pass_id: 3, avg_acc: 0.994591, avg_cost: 0.024470[train info]: pass_id: 4, avg_acc: 0.997796, avg_cost: 0.012553[train info]: pass_id: 5, avg_acc: 0.998197, avg_cost: 0.008723[train info]: pass_id: 6, avg_acc: 0.999599, avg_cost: 0.003929[train info]: pass_id: 7, avg_acc: 0.999700, avg_cost: 0.002423[train info]: pass_id: 8, avg_acc: 0.999900, avg_cost: 0.001672[train info]: pass_id: 9, avg_acc: 0.999900, avg_cost: 0.001001
也可以直接使用目錄下的 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.995657predict label: 2, pos_prob: 0.798888, neg_prob: 0.201112predict label: 0, pos_prob: 0.000564, neg_prob: 0.999436predict label: 0, pos_prob: 0.024923, neg_prob: 0.975077predict label: 2, pos_prob: 0.999526, neg_prob: 0.000474predict label: 2, pos_prob: 0.994914, neg_prob: 0.005086predict label: 0, pos_prob: 0.065424, neg_prob: 0.934576predict label: 0, pos_prob: 0.000119, neg_prob: 0.999881predict label: 0, pos_prob: 0.000709, neg_prob: 0.999291predict label: 2, pos_prob: 0.986198, neg_prob: 0.013802.......
可以觀察模型對於每一個樣例的預測結果和詳細情況。
擴充套件:處理未經加工的原始語料
上述的實驗中,使用的訓練和測試語料都已經經過分詞處理,並且都被人工標了情感極性標籤,用於訓練和評價模型的能力,但是在實際應用中,面對的語料都是生語料,比如線上商品的評價資訊,並沒有經過分詞之類的處理。這種情況下需要預先對語料進行加工處理,百度也開源了詞法分析提供工具 LAC。