本文是用機器學習打造聊天機器人系列的第三篇,經過閱讀本文你將對聊天機器人的實現有一個大體的思路。html
本項目基於chatterbot0.8.7來開發,但不只於此。讓咱們先對chatterbot作一個簡單的瞭解。python
ChatterBot是一個基於機器學習的口語式對話引擎,基於python編寫,能夠基於已有的會話集合返回匹配問題的響應。ChatterBot的非侵入式語言設計,使得咱們能夠在其上訓練任何語言的對話模型。程序員
首先,安裝chatterbot0.8.7版本:算法
pip install ChatterBot==0.8.7
建立一個chat bot實例:sql
from chatterbot import ChatBot chatbot = ChatBot("Ron Obvious")
訓練你的機器人:mongodb
from chatterbot.trainers import ListTrainer # 對話語料對,一問一答 conversation = [ "Hello", "Hi there!", "How are you doing?", "I'm doing great.", "That is good to hear", "Thank you.", "You're welcome."] trainer = ListTrainer(chatbot) trainer.train(conversation)
獲取響應,"Thanks!"在上面的語料對中是沒有的,可是其默認使用的Levenshtein distance算法能讓引擎從問答對中選出一個相近的回答:數據庫
response = chatbot.get_response("Thanks!") print(response) # 將輸出You're welcome.
ok,若是你也已經獲得了上面的正確輸出,你可能想說,就這麼簡單?其實若是從簡單體驗一下的角度來講,就是這麼簡單。可是若是你想作一個像那麼回事的聊天機器人出來,那麼還有一段路要走,好比Levenshtein distance算法其實過於簡單了,會致使一些答非所問的狀況,除此以外,還有一些其餘咱們須要完善的地方,具體會在下一個話題中討論。app
的確,這裏面是有一些問題的:框架
沒錯,咱們要解決的主要問題就是上面列出的2個問題,歸納來講就是2個方面,一個是性能,另外一個是智能。雖然問題只有2個,可是解決起來確是要花費一番功夫的。
首先,讓咱們來分析一下性能的問題:
一、chatterbot默認採用sqlite數據庫,sqlite是一個關係型數據庫,很是輕量,無需配置和部署,可是當數據量比較大的時候,寫性能相對mongodb等nosql數據庫仍是有差距的,對於咱們的場景,因爲不存在強事務要求,因此建議切換到mongodb數據庫,你會發現訓練速度會有較大的提高;
策略:chatterbot除了支持sqlite,還支持mongodb,因此能夠經過修改配置的方式切換到mongodb數據庫,示例以下:機器學習
chat = ChatBot( bot_name, database=bot_name, database_uri=current_app.config['DATABASE_URI'], storage_adapter="chatterbot.storage.MongoDatabaseAdapter")
二、chatterbot將全部問答對存儲在一塊兒,好比在mongodb中,是存儲在一個集合裏的,這樣匹配問題的時候,就要和全部的問答對數據比較一遍,若是數據量很大的話,效率確定是很慢的;
策略:將問答對分類存儲,好比在mongodb中,不一樣類型的問答對存儲在不一樣的集合裏,這一步稱爲意圖分類,因此咱們須要經過另外的算法來肯定輸入句子的意圖類別,而後在指定類別下去判斷句子和哪些問題更爲近似,而後返回對應的回答。這樣作的好處是方便維護,大致量的問答對被拆分到各個對應的類別下,分別匹配,體量天然會減小不少,而且某一類型的問答對的數據量增長,對其餘類型問答對的響應速度沒有直接的影響。
三、chatterbot區分問題和答案是根據句子是否出如今in_response_to屬性下的text屬性中來判斷的,這致使須要先查詢出in_response_to下的全部text,而後根據text再查出全部屬於問題的句子,這樣的查詢效率是很低的;
策略:在準備問答對語料的時候,分別對問題和答案進行標識,好比用Q和A作前綴,這樣存儲到數據庫中後,查詢的時候就能夠用Q來直接匹配出問題,而不須要屢次查詢數據庫。
四、chatterbot默認採用Levenshtein distance算法將當前輸入的問題和數據庫裏每個問答記錄進行比較,具體作法是先查出全部的問答句子,而後for循環進行一一比較,選擇出最類似的句子作爲響應返回,效率天然不會高。
策略:改成使用詞向量進行比較,具體在下面的智能度策略中有介紹。
ok,咱們再來聊聊如何提高chatterbot的智能度:
一、採用餘弦類似度算法代替Levenshtein distance算法
Levenshtein distance算法只是單純的計算一個句子變成另外一個句子須要通過的最小的編輯步驟,並無考慮句子中詞彙自己的含義,因此它並能識別出"蘋果"比起"香水"來講和"香蕉"在語義上靠的更近。而餘弦類似度是指比較兩個向量之間的餘弦類似度,向量固然分別是輸入句子的句向量和數據庫中全部問題句子的句向量,而句子轉爲向量的方式是採用的word2vec,該方法在後續講原理的部分會具體介紹,這裏咱們只須要知道詞向量模型能夠將詞轉爲對應的向量,這些向量在空間中呈現一種語義上的關係,好比用詞向量表示咱們的詞的時候,會發現 King的向量-Man的向量+Woman的向量=Queen的向量。
那麼句子又是怎麼轉成向量的呢?這裏咱們採用了平均向量的方法,就是先對句子分詞,而後將詞向量相加再除以向量的個數。至於爲何餘弦值能夠表示兩個向量的類似度,咱們一樣也會在原理的部分進行介紹。
二、採用向量化並行計算策略代替for循環比對
有了句子的向量表示後,咱們就能夠採用一些並行計算的方式來代替for循環,具體的操做是將全部數據放到一個矩陣中一塊兒計算,CPU雖然遠比不上GPU的並行計算速度,可是比起for循環的方式仍然能夠帶來幾十到幾百倍計算速度的提高。在此也體現了chatterbot的優秀設計,使得咱們能夠在不更改源代碼的狀況下就替換掉原有的匹配算法,具體見代碼篇的介紹。
到此,咱們解釋了爲何須要基於chatterbot再作一些事情,以及如何作,如今咱們來看看一個問題從輸入到給出回覆具體經歷了哪些步驟:
用戶提問後,由意圖推測組件接收問題,組件內部進行特徵提 取後,傳給意圖分類器去預測問題所屬的類別(好比:這是一個關於 「電影演員」的問題,或關於「電影上映時間」的問題),接着問題會傳遞到語義 理解模塊,並自動觸發合適的語義理解實例去嘗試匹配問題對應的 答案,這裏說的語義理解就是在指定的意圖分類下,去匹配具體的問題,好比「你以爲功夫類電影誰演的好?」,或者「愛情片什麼時間段上映比較合適?」等。整個過程主要是採用詞向量模型構造問題句子的特徵向量,經過貝葉斯算法進行意圖分類,以及 採用餘弦類似度算法計算問題和答案的匹配分數。此時引擎會根據 匹配分數結合閾值進行分析,從而決定是直接返回答案,仍是降級處理,因此有些場景下可能會返回多個候選答案,候選答案會根據分數降序排列。
前面說的都是如何根據輸入的問題給與合適的回覆,本篇主要討論如何調教機器人說你想聽的回覆,具體流程以下:
用戶提問後,若是系統沒能給出滿意的答案,用戶能夠經過新增問答對、修訂答案 2 種方式來進行反饋,當系統給出多個候選答 案,可是正確答案沒有排在首位時,用戶能夠經過標註最佳答案來 進行反饋。能夠按期讓問答引擎自主學習用戶的反饋,從新訓練意 圖分類器並更新問答語料庫,當用戶本身或其餘用戶再次問到相同 含義的問題時便可獲得相應的答案。
因爲咱們能夠本身調教機器人,因此你能夠將其調教成僅屬於你本身的獨一無二的性格😏。
下一篇《用機器學習打造聊天機器人(四) 代碼篇》將展現打造聊天機器人的相關代碼實現及說明。
ok,本篇就這麼多內容啦~,感謝閱讀O(∩_∩)O。
本博客內容來自公衆號「程序員一一滌生」,歡迎掃碼關注 o(∩_∩)o