nlp文字處理開源工具,及聊天機器人實現

u013378306發表於2017-02-15

原文地址:http://www.leiphone.com/news/201702/4OZau7OfcNO0v1u5.html

第一篇傳送門:聊天機器人的發展狀況與分類

第二篇傳送門:基於規則和檢索的聊天機器人引擎

本篇文章以這個開源專案為主線進行。

資料預處理

模型能聊的內容也取決於選取的語料。如果已經具備了原始聊天資料,可以用SQL通過關鍵字查詢一些對話,也就是從大庫裡選取出一個小庫來訓練。從一些論文上,很多演算法都是在資料預處理層面的,比如Mechanism-Aware Neural Machine for Dialogue Response Generation就介紹了,從大庫中抽取小庫,然後再進行融合,訓練出有特色的對話來。

如何利用深度學習技術訓練聊天機器人語言模型?

【圖 3-1】 語料預處理, Ref. #7

對於英語,需要了解NLTK,NLTK提供了載入語料,語料標準化,語料分類,PoS詞性標註,語意抽取等功能。

另一個功能強大的工具庫是CoreNLP,作為 Stanford開源出來的工具,特色是實體標註,語意抽取,支援多種語言。

下面主要介紹兩個內容:

中文分詞

現在有很多中文分詞的SDK,分詞的演算法也比較多,也有很多文章對不同SDK的效能做比較。做中文分詞的示例程式碼如下。

# coding:utf8
'''  
Segmenter with Chinese  
'''

import jieba  
import langid


def segment_chinese_sentence(sentence):  
   '''
   Return segmented sentence.
   '''
   seg_list = jieba.cut(sentence, cut_all=False)
   seg_sentence = u" ".join(seg_list)
   return seg_sentence.strip().encode('utf8')


def process_sentence(sentence):  
   '''
   Only process Chinese Sentence.
   '''
   if langid.classify(sentence)[0] == 'zh':
       return segment_chinese_sentence(sentence)
   return sentence

if __name__ == "__main__":  
   print(process_sentence('飛雪連天射白鹿'))
   print(process_sentence('I have a pen.'))

以上使用了langid先判斷語句是否是中文,然後使用jieba進行分詞。

在功能上,jieba分詞支援全切分模式,精確模式和搜尋引擎模式。

全切分:輸出所有分詞。

精確:概率上的最佳分詞。

所有引擎模式:對精確切分後的長句再進行分詞。

jieba分詞的實現

主要是分成下面三步:

1、載入字典,在記憶體中建立字典空間。

字典的構造是每行一個詞,空格,詞頻,空格,詞性

上訴書 3 n
上訴人 3 n
上訴期 3 b
上訴狀 4 n
上課 650 v

建立字典空間的是使用python的dict,採用字首陣列的方式。

使用字首陣列的原因是樹結構只有一層 - word:freq,效率高,節省空間。比如單詞"dog", 字典中將這樣儲存:

{
 "d": 0,
 "do": 0,
 "dog": 1 # value為詞頻
}

字典空間的主要用途是對輸入句子建立有向無環圖,然後根據演算法進行切分。演算法的取捨主要是根據模式 - 全切,精確還是搜尋。

2、對輸入的語句分詞,首先是建立一個有向無環圖。 
有向無環圖, Directed acyclic graph (音 /ˈdæɡ/)。

如何利用深度學習技術訓練聊天機器人語言模型?

【圖 3-2】 DAG

DAG對於後面計算最大概率路徑和使用HNN模型識別新詞有直接關係。

3、按照模式,對有向無環圖進行遍歷,比如,在精確模式下,便利就是求最大權重和的路徑,權重來自於在字典中定義的詞頻。對於沒有出現在詞典中的詞,連續的單個字元也許會構成新詞。然後用HMM模型和Viterbi演算法識別新詞。

精確模型切詞:使用動態規劃對最大概率路徑進行求解。

最大概率路徑:求route = (w1, w2, w3 ,.., wn),使得Σweight(wi)最大。Wi為該詞的詞頻。

更多的細節還需要讀一下jieba的原始碼

自定義字典

jieba分詞預設的字典是:1998人民日報的切分語料還有一個msr的切分語料和一些txt小說。開發者可以自行新增字典,只要符合字典構建的格式就行。

jieba分詞同時提供介面新增詞彙。

Word embedding

使用機器學習訓練的語言模型,網路演算法是使用數字進行計算,在輸入進行編碼,在輸出進行解碼。word embedding就是編解碼的手段。

如何利用深度學習技術訓練聊天機器人語言模型?

【圖 3-3】 word embedding, Ref. #7

word embedding是文字的數值化表示方法。表示法包括one-hot,bag of words,N-gram,分散式表示,共現矩陣等。

Word2vec

如何利用深度學習技術訓練聊天機器人語言模型?

近年來,word2vec被廣泛採用。Word2vec輸入文章或者其他語料,輸出語料中詞彙建設的詞向量空間。詳細可參考word2vec數學原理解析

  • 使用word2vec

安裝完成後,得到word2vec命令列工具。

word2vec -train "data/review.txt" \  
 -output "data/review.model" \
 -cbow 1 \
 -size 100 \
 -window 8 \
 -negative 25 \
 -hs 0 \
 -sample 1e-4 \
 -threads 20 \
 -binary 1 \
 -iter 15

-train "data/review.txt" 表示在指定的語料庫上訓練模型

-cbow 1 表示用cbow模型,設成0表示用skip-gram模型

-size 100 詞向量的維度為100

-window 8 訓練視窗的大小為8 即考慮一個單詞的前八個和後八個單詞

-negative 25 -hs 0 是使用negative sample還是HS演算法

-sample 1e-4 採用閾值

-threads 20 執行緒數

-binary 1 輸出model儲存成2進位制

-iter 15 迭代次數

在訓練完成後,就得到一個model,用該model可以查詢每個詞的詞向量,在詞和詞之間求距離,將不同詞放在數學公式中計算輸出相關性的詞。比如:

vector("法國") - vector("巴黎) + vector("英國") = vector("倫敦")"  

對於訓練不同的語料庫,可以單獨的訓練詞向量模型,可以利用已經訓練好的模型。

其它訓練詞向量空間工具推薦:Glove

Seq2Seq

2014年,Sequence to Sequence Learning with Neural Networks提出了使用深度學習技術,基於RNN和LSTM網路訓練翻譯系統,取得了突破,這一方法便應用在更廣泛的領域,比如問答系統,影象字幕,語音識別,撰寫詩詞等。Seq2Seq完成了【encoder + decoder -> target】的對映,在上面的論文中,清晰的介紹了實現方式。

如何利用深度學習技術訓練聊天機器人語言模型?

【圖 3-4】 Seq2Seq, Ref. #1

也有很多文章解讀它的原理。在使用Seq2Seq的過程中,雖然也研究了它的結構,但我還不認為能理解和解釋它。下面談兩點感受:

a. RNN儲存了語言順序的特點,這和CNN在處理帶有形狀的模型時如出一轍,就是數學模型的設計符合物理模型。

如何利用深度學習技術訓練聊天機器人語言模型?

【圖 3-5】 RNN, Ref. #6

b. LSTM Cell的複雜度對應了自然語言處理的複雜度。

如何利用深度學習技術訓練聊天機器人語言模型?

【圖 3-6】 LSTM, Ref. #6

理由是,有人將LSTM Cell嘗試了多種其它方案傳遞狀態,結果也很好。

如何利用深度學習技術訓練聊天機器人語言模型?

【圖 3-7】 GRU, Ref. #6

LSTM的一個替代方案:GRU。只要RNN的Cell足夠複雜,它就能工作的很好。

使用DeepQA2訓練語言模型

準備工作,下載專案:

git clone https://github.com/Samurais/DeepQA2.git  
cd DeepQA2  
open README.md # 根據README.md安裝依賴包  

DeepQA2將工作分成三個過程:

  • 資料預處理:從語料庫到資料字典。

  • 訓練模型:從資料字典到語言模型。

  • 提供服務:從語言模型到RESt API。

預處理

DeepQA2使用Cornell Movie Dialogs Corpus作為demo語料庫。

原始資料就是movie_lines.txt 和movie_conversations.txt。這兩個檔案的組織形式參考README.txt

deepqa2/dataset/preprocesser.py是將這兩個檔案處理成資料字典的模組。

如何利用深度學習技術訓練聊天機器人語言模型?

train_max_length_enco就是問題的長度,train_max_length_deco就是答案的長度。在語料庫中,大於該長度的部分會被截斷。

程式執行後,會生成dataset-cornell-20.pkl檔案,它載入到python中是一個字典:

如何利用深度學習技術訓練聊天機器人語言模型?

word2id儲存了{word: id},其中word是一個單詞,id是int數字,代表這個單詞的id。

id2word儲存了{id: word}。

trainingSamples儲存了問答的對話對。

比如 [[[1,2,3],[4,5,6]], [[7,8,9], [10, 11, 12]]]

1,2,3 ... 12 都是word id。

[1,2,3] 和 [4,5,6] 構成一個問答。 [7,8,9] 和 [10, 11, 12] 構成一個問答。

開始訓練

cp config.sample.ini config.ini # modify keys  
python deepqa2/train.py  

config.ini是配置檔案, 根據config.sample.ini進行修改。訓練的時間由epoch,learning rate, maxlength和對話對的數量而定。

deepqa2/train.py大約100行,完成資料字典載入、初始化tensorflow的session,saver,writer、初始化神經元模型、根據epoch進行迭代,儲存模型到磁碟。

session是網路圖,由placeholder, variable, cell, layer, output 組成。

saver是儲存model的,也可以用來恢復model。model就是例項化variable的session。

writer是檢視loss fn或者其他開發者感興趣的資料的收集器。writer的結果會被saver儲存,然後使用tensorboard檢視。

如何利用深度學習技術訓練聊天機器人語言模型?

【圖 3-8】 TensorBoard

Model

Model的構建要考慮輸入,狀態,softmax,輸出。

如何利用深度學習技術訓練聊天機器人語言模型?

定義損耗函式,使用AdamOptimizer進行迭代。

如何利用深度學習技術訓練聊天機器人語言模型?

最後,參考一下訓練的loop部分。

如何利用深度學習技術訓練聊天機器人語言模型?

每次訓練,model會被儲存在 save路徑下,資料夾的命名根據機器的hostname,時間戳生成。

如何利用深度學習技術訓練聊天機器人語言模型?

提供服務

在TensorFlow中,提供了標準的serving模組 - tensorflow serving。但研究了很久,還專門看了一遍 《C++ Essentials》,還沒有將它搞定,社群也普遍抱怨tensorflow serving不好學,不好用。訓練結束後,使用下面的指令碼啟動服務,DeepQA2的serve部分還是呼叫TensorFlow的python api。

cd DeepQA2/save/deeplearning.cobra.vulcan.20170127.175256/deepqa2/serve  
cp db.sample.sqlite3 db.sqlite3  
python manage.py runserver 0.0.0.0:8000  

測試

POST /api/v1/question HTTP/1.1  
Host: 127.0.0.1:8000  
Content-Type: application/json  
Authorization: Basic YWRtaW46cGFzc3dvcmQxMjM=  
Cache-Control: no-cache

{"message": "good to know"}

response  
{
 "rc": 0,
 "msg": "hello"
}

serve的核心程式碼在serve/api/chatbotmanager.py中。

使用指令碼

scripts/start_training.sh 啟動訓練

scripts/start_tensorboard.sh 啟動Tensorboard

scripts/start_serving.sh 啟動服務

對模型的評價

目前程式碼具有很高的維護性,這也是從DeepQA專案進行重構的原因,更清晰的資料預處理、訓練和服務。有新的變更可以新增到deepqa2/models中,然後在train.py和chatbotmanager.py變更一下。

有待改進的地方

a. 新建models/rnn2.py, 使用dropout。目前DeepQA中已經使用了Drop.

b. tensorflow rc0.12.x中已經提供了seq2seq network,可以更新成tf版本.

c. 融合訓練,目前model只有一個庫,應該是設計一個新的模型,支援一個大庫和小庫,不同權重進行,就如Mechanism-Aware Neural Machine for Dialogue Response Generation的介紹。

d. 程式碼支援多機多GPU執行。

e. 目前訓練的結果都是QA對,對於一個問題,可以有多個答案。

f. 目前沒有一個方法進行accuracy測試,一個思路是在訓練中就提供干擾項,因為當前只有正確的答案,如果提供錯誤的答案(而且越多越好),就可以使用recall_at_k方法進行測試。

最後

歡迎聯絡我,尤其是業內人士,給予指正,一起優化。

本系列完結。

References

1. A Neural Conversational Model

2. Sequence to Sequence Learning with Neural Networks

3. DeepQA Project

4. Efficient Estimation of Word Representations in Vector Space

5. jieba分詞分析

6. Tensorflow and deep learning - without a PhD by Martin Görner

7. Pragmatic NLP by Matt Fortier

相關文章