天天看點

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

原文位址:http://www.leiphone.com/news/201702/4ozau7ofcno0v1u5.html

資料預處理

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

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

下面主要介紹兩個内容:

中文分詞

# 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.'))

在功能上,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、對輸入的語句分詞,首先是建立一個有向無環圖。 

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

【圖 3-2】 dag

dag對于後面計算最大機率路徑和使用hnn模型識别新詞有直接關系。

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

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

自定義字典

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

jieba分詞同時提供接口添加詞彙。

word embedding

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

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

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

word2vec

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

使用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("倫敦")"  

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

seq2seq

+ decoder -> target】的映射,在上面的論文中,清晰的介紹了實作方式。

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

【圖 3-4】 seq2seq, ref. #1

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

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

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

【圖 3-5】 rnn, ref. #6

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

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

【圖 3-6】 lstm, ref. #6

理由是,有人将lstm cell嘗試了多種其它方案傳遞狀态,結果也很好。

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

【圖 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。

預處理

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

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

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

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

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和對話對的數量而定。

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

saver是儲存model的,也可以用來恢複model。model就是執行個體化variable的session。

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

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

【圖 3-8】 tensorboard

model

model的建構要考慮輸入,狀态,softmax,輸出。

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

定義損耗函數,使用adamoptimizer進行疊代。

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

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

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

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

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

提供服務

在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"

使用腳本

對模型的評價

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

有待改進的地方

a. 建立models/rnn2.py, 使用dropout。目前deepqa中已經使用了drop.

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

d. 代碼支援多機多gpu運作。

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

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

最後

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

本系列完結。

references