實戰 | 讓機器人替你聊天,還不被人看出破綻?來,手把手教你訓練一個克隆版的你

AI科技大本營發表於2017-08-23

實戰 | 讓機器人替你聊天,還不被人看出破綻?來,手把手教你訓練一個克隆版的你


編譯 | AI科技大本營(rgznai100)

參與 | 史天

  


聊天機器人到底是什麼呢?說白了,就是計算機程式通過聽覺或文字方法進行對話。

當今最流行的四個對話機器人是:蘋果的Siri、微軟Cortana、谷歌助理、亞馬遜的Alexa。他們能夠幫你查比分、打電話,當然,偶爾他們也會出錯。

本文,我們主要會詳細介紹聊天機器人在文字方面的運作。

在這篇文章中,我們將看到如何使用深度學習模型訓練聊天機器人用我們所希望的方式在社交媒體上進行對話。


                                                               意圖&深度學習

  

如何訓練一個高水平的聊天機器人呢?

高水平的工作聊天機器人是應當對任何給定的訊息給予最佳反饋。這種“最好”的反應應該滿足以下要求:

  • 回答對方問題

  • 反饋相關資訊

  • 問後續問題或用現實方法繼續對話

這三個方面是機器人表現出來的內容,而隱含其中沒有表現出來的則是一系列流程:理解傳送者的意圖,確定反饋資訊的型別(問一個後續問題,或者直接反應等),並遵循正確的語法和詞法規則。

請注意,“意圖”二字至關重要。只有明確意圖,才能保證在後續流程的順利進行。對於“意圖”,讀者通過本篇文章,將會看到,深度學習是最有效的解決“意圖”問題的方法之一。

  

                                                         深度學習的方法

  

聊天機器人使用的深度學習模型幾乎都是 Seq2Seq。2014年,Ilya Sutskever, Oriol Vinyals, and Quoc Le 發表了《Sequence to Sequence Learning with Neural Networks》一文。摘要顯示,儘管機器翻譯已經做的很好,但Seq2Seq卻模型能更好的完成各種各樣的NLP的任務。

實戰 | 讓機器人替你聊天,還不被人看出破綻?來,手把手教你訓練一個克隆版的你

Seq2Seq模型由兩個主要部件組成,一個是編碼器RNN,另一個是解碼器RNN。從高層次上來說,編碼器的工作是將輸入文字資訊生成固定的表示。解碼器則是接收這個表示,並生成一個可變長度的文字,以響應它。

實戰 | 讓機器人替你聊天,還不被人看出破綻?來,手把手教你訓練一個克隆版的你

讓我們來看看它是如何在更詳細的層次上工作的。

正如我們所熟知的,編碼器RNN包含了許多隱藏的狀態向量,它們每個都表示從上一次時間步驟中獲取的資訊。例如,在第3步序中的隱藏狀態向量是前三個單詞的函式。通過這個邏輯,編碼器RNN的最終隱藏狀態向量可以被認為是對整個輸入文字的一種相當精確的表示。

而解碼器RNN負責接收編碼器的最後隱藏狀態向量,並使用它來預測輸出應答的單詞。讓我們看看第一個單元。該單元的工作是使用向量表示v,並決定其詞彙表中哪個單詞是最適合輸出響應的。從數學上講,這就意味著我們計算詞彙中的每一個單詞的概率,並選擇值的極大似然。

第二單元是向量表示v的函式,也是先前單元的輸出。LSTM的目標是估計以下條件概率。

實戰 | 讓機器人替你聊天,還不被人看出破綻?來,手把手教你訓練一個克隆版的你

讓我們來解構這個方程式意味著什麼。

左側指的是輸出序列的概率,這取決於給定輸入序列。

右側包含p(yt | v,y1,…,yt),它是所有單詞的概率向量,條件是在前一步的向量表示和輸出的情況下。其中pi等價於西格瑪(或累計求和)的乘法。則右側可降為p(Y1 | V)*p(y2 | v,y1)*p(Y3 | v,y1,y2)

在繼續之前,讓我們先做一個簡單的例子。

讓我們在第一張圖片中輸入文字:“你明天有空嗎?”

大多數人都會怎麼回答呢?一般都會用“yes”、“yeah”、“no”開始。

在我們完成了網路訓練之後,概率p(Y1 | V)將是一個類似於下面的分佈。

實戰 | 讓機器人替你聊天,還不被人看出破綻?來,手把手教你訓練一個克隆版的你

再來看我們需要計算的第二個概率,p(y2 | v,y1)表是一個函式,詞的分佈y1以及向量的表示結果v,而pi將產生最終結果並作為我們的最終反應。

Seq2Seq模型的最重要特性之一是它提供的多功能性。當你想到傳統的ML方法(線性迴歸,支援向量機)和深等深學習方法時,這些模型需要一個固定的大小輸入,併產生固定大小的輸出。但是輸入的長度必須事先知道。這是對諸如機器翻譯、語音識別和問答等任務的一個很大的限制。這些任務我們都不知道輸入短語的大小,我們也希望能夠生成可變長度響應,而不僅僅侷限於一個特定的輸出表示。而Seq2Seq模型允許這樣的靈活性!

自2014以來,Seq2Seq模型已經有了很多改進,你可以在這篇文章結尾“相關論文”部分中閱讀更多關於Seq2Seq的文章。


                                                                 資料集的選擇


在考慮將機器學習應用於任何型別的任務時,我們需要做的第一件事都是選擇資料集,並對我們需要的模型進行訓練。對於序列模型,我們需要大量的會話日誌。從高層次上講,這個編碼器-解碼器網路需要能夠正確理解每個查詢(編碼器輸入)所期望的響應型別(解碼器輸出)。

一些常見的資料集包括:康奈爾電影對話語料庫、ubuntu語料庫和微軟的社交媒體對話語料庫。

雖然大多數人都在訓練聊天機器人來回答具體資訊或提供某種服務,但我更感興趣的是更多的有趣的應用程式。有了這篇文章,我想看看我是否可以用我自己的生活中的對話日誌來訓練一個Seq2Seq的模型來學習對資訊的反應。


獲取資料


實戰 | 讓機器人替你聊天,還不被人看出破綻?來,手把手教你訓練一個克隆版的你

我們需要建立一個大量的對話資料,在我的社交媒體上,我使用了Facebook、Google Hangouts、SMS、Linkedin、Twitter、Tinder和Slack 等著與人們保持聯絡。

Facebook:這是大部分培訓資料的來源。facebook有一個很酷的功能,讓你可以下載你所有的Facebook資料。包含所有的資訊、照片、歷史資訊。

Hangouts:您可以根據這個文章的指示來提取聊天資料


https://blog.jay2k1.com/2014/11/10/how-to-export-and-backup-your-google-hangoutschat-history/


SMS:可以快速獲得所有之前的聊天記錄(sms備份+是一個不錯的應用程式),但我很少使用簡訊。

Linkedin:Linkedin確實提供了一種工具,可以在這裡獲取資料的歸檔。


https://www.linkedin.com/start/join?session_redirect=https%3A%2F%2Fwww.linkedin.com%2Fpsettings%2Fmember-data


Twitter:這其中沒有足夠的私人資訊。

Tinder:這其中的對話不是資料集。

Slack:我的Slack剛剛開始使用,只有幾個私有訊息,計劃手動複製。


建立資料集


資料集的建立是機器學習的一個重要組成部分,它涉及到資料集預處理。這些源資料存檔格式不同,並且包含我們不需要的部分(例如,fb資料的圖片部分)。

實戰 | 讓機器人替你聊天,還不被人看出破綻?來,手把手教你訓練一個克隆版的你

正如您所看到的,Hangouts資料的格式與facebook資料有一點不同,而linkedin的訊息以csv格式進行。我們的目標是使用所有這些資料集來建立一個統一的檔案,命名為(FRIENDS_MESSAGE,YOUR_RESPONSE)

為了做到這一點,我編寫了一個python指令碼,可以在這裡檢視


https://github.com/adeshpande3/Facebook-Messenger-Bot/blob/master/createDataset.py


此指令碼將建立兩個不同的檔案。其中一個是Numpy物件(conversationDictionary.npy)包含所有輸入輸出對。另一個是一個大的txt檔案(conversationData.txt)包含這些輸入輸出對的句子形式,一個對應一個。通常,我喜歡共享資料集,但是對於這個特定的資料集,我會保持私有,因為它有大量的私人對話。這是最後一個資料集的快照。

實戰 | 讓機器人替你聊天,還不被人看出破綻?來,手把手教你訓練一個克隆版的你


詞向量


LOL,WTF,這些都是在我們的會話資料檔案中經常出現的所有單詞。雖然它們在社交媒體領域很常見,但它們並不是在很多傳統的資料集中。通常情況下,我在接近NLP任務時的第一個直覺是簡單地使用預先訓練的向量,因為它們能在大型主體上進行大量迭代的訓練。

然而,由於我們有這麼多的單詞和縮寫,而不是在典型的預先訓練的單詞向量列表中,因此,生成我們自己的單詞向量對於確保單詞正確表達是至關重要的。

為了生成單詞向量,我們使用了word2vec模型的經典方法。其基本思想是,通過觀察句子中單詞出現的上下文,該模型會建立單詞向量。在向量空間中,具有相似上下文的單詞將被置於緊密的位置。關於如何建立和訓練word2vec模型的更詳細的概述,請檢視我的一個好友Varma羅漢的部落格。


https://github.com/adeshpande3/Facebook-Messenger-Bot/blob/master/Word2Vec.py


*更新:我後來瞭解到TensorFlow Seq2Seq函式從零開始對單詞embeddings進行訓練,因此我不會使用這些單詞向量,儘管它們仍然是很好的實踐*


用TensorFlow建立Seq2Seq模型


現在我們建立了資料集並生成了我們的單詞向量,我們就可以繼續編碼Seq2Seq模型了。我在python指令碼中建立和訓練了模型


https://github.com/adeshpande3/Facebook-Messenger-Bot/blob/master/Seq2Seq.py


我試著對程式碼進行評論,希望你能跟著一起。該模型的關鍵在於TensorFlow的嵌入_RNN_seq2seq()函式。你可以在這裡找到文件。


https://www.tensorflow.org/tutorials/seq2seq


跟蹤培訓進展

實戰 | 讓機器人替你聊天,還不被人看出破綻?來,手把手教你訓練一個克隆版的你

這個專案的一個有趣的地方是,能看到網路訓練時,響應是如何發生變化的。訓練迴路中,我在輸入字串上測試了網路,並輸出了所有非pad和非eos口令。

首先,您可以看到,響應主要是空白,因為網路重複輸出填充和eos口令。這是正常的,因為填充口令是整個資料集中最常見的口令。

然後,您可以看到,網路開始輸出“哈哈”的每一個輸入字串。

這在直覺上是有道理的,因為“哈哈”經常被使用,它是對任何事情都可以接受的反應。慢慢地,你開始看到更完整的思想和語法結構在反應中出現。現在,如果我們有一個經過適當訓練的Seq2Seq模型,那麼就可以建立facebook messenger 聊天機器人


                                  如何建立一個簡單的fb messenger 聊天機器人


這個過程並不是太難,因為我花了不到30分鐘的時間來完成所有步驟。基本的想法是,我們使用簡單的express應用程式建立了一個伺服器,在Heroku上安裝它,然後設定一個facebook頁面連線。但最終,你應該有一個類似這樣的 Facebook 聊天應用程式。

實戰 | 讓機器人替你聊天,還不被人看出破綻?來,手把手教你訓練一個克隆版的你

您可以向您的聊天機器人傳送訊息(這種初始行為只是響應它所傳送的所有內容)。

實戰 | 讓機器人替你聊天,還不被人看出破綻?來,手把手教你訓練一個克隆版的你


部署訓練有素的TensorFlow模型


現在是時候把一切都放在一起了。由於tensorflow和node之間還沒有找到一個很好的介面(不知道是否有一個官方支援的包裝器),所以我決定使用slack伺服器部署我的模型,並讓聊天機器人的表達與它進行互動。您可以在這裡檢視slack伺服器程式碼


https://github.com/adeshpande3/Chatbot-Flask-Server


以及聊天機器人的index.js檔案


https://github.com/adeshpande3/Facebook-Messenger-Bot/blob/master/index.js


測試它!


如果你想和這個機器人聊天,那就繼續點選這個連結


https://www.messenger.com/


或者點選facebook頁面,傳送訊息


https://www.facebook.com/Adits-FB-Chatbot-822517037906771/


第一次響應可能需要一段時間,因為伺服器需要啟動。

也許很難判斷機器人是否真的像我那樣說話(因為沒有很多人在網上和我聊天),但是它做的很好!考慮到社會媒體標準,語法是可以通過的。你可以選擇一些好的結果,但大多數都是相當荒謬的。這能幫助我在晚上睡得更好的,畢竟不能在任何時間用skynet。

實戰 | 讓機器人替你聊天,還不被人看出破綻?來,手把手教你訓練一個克隆版的你

我認為第一個是特別有趣的,因為“juju green”實際上似乎是一種 Juju Smith-Schuster,鋼人隊寬接收器,和 Draymond Green,前鋒金州勇士。有趣的組合。

雖然現在的表現還不太好。讓我們來考慮一下改善它的方法吧!


                                                                        改進方法


從與chatbot的互動中可以看到的改進方法,有很大的改進空間。經過幾條資訊後,很快就會明白,不僅僅是進行持續的對話就行了。chabtot不能夠把思想聯絡在一起,而一些反應似乎是隨機的、不連貫的。下面是一些可以提高我們聊天機器人效能的方法。

  • 合併其他資料集,以幫助網路從更大的會話語料庫中學習。這將消除聊天機器人的“個人特性”,因為它現在已經被嚴格訓練了。然而,我相信這將有助於產生更現實的對話。

  • 處理編碼器訊息與解碼器訊息無關的場景。例如,當一個對話結束時,你第二天就開始一個新的對話。談話的話題可能完全無關。這可能會影響模型的訓練。

  • 使用雙向LSTMs,注意機制和套接。

  • 優化超引數,如LSTM單元的數量、LSTM層的數量、優化器的選擇、訓練迭代次數等。


                                         你如何建立像你一樣的聊天機器人- 流程回顧


如果你一直在跟進,你應該對建立一個聊天機器人所需要的東西已經有了一個大致的概念。讓我們再看一遍最後的步驟。在GitHub repo 中有詳細的說明。


https://github.com/adeshpande3/Facebook-Messenger-Bot/blob/master/README.md


  1. 找到所有你與某人交談過的社交媒體網站,並下載你的資料副本。

  2. 從CreateDataset中提取所有(訊息、響應)對py或您自己的指令碼。

  3. (可選)通過Word2Vec.py為每一個在我們的對話中出現的單詞 生成單詞向量。

  4. 在Seq2Seq.py中建立、訓練和儲存序列模型。

  5. 建立Facebook聊天機器人。

  6. 建立一個Flask伺服器,在其中部署儲存的Seq2Seq模型。

  7. 編輯索引檔案,並與Flask伺服器通訊。


最後給大家貢獻一些可供查閱的資源:

相關論文

  • Sequence to Sequence Learning

  • https://arxiv.org/pdf/1409.3215.pdf

  • Seq2Seq with Attention

  • https://arxiv.org/pdf/1409.0473.pdf

  • Neural Conversational Model

  • https://arxiv.org/pdf/1506.05869.pdf

  • Generative Hierarchical Models

  • https://arxiv.org/pdf/1507.04808.pdf

  • Persona Based Model

  • https://arxiv.org/pdf/1603.06155.pdf

  • Deep RL for Dialogue Generation

  • https://arxiv.org/pdf/1606.01541.pdf

  • Attention with Intention

  • https://arxiv.org/pdf/1510.08565.pdf

  • Diversity Promoting Objective Functions

  • https://arxiv.org/pdf/1510.03055.pdf

  • Copying Mechanisms in Seq2Seq

  • https://arxiv.org/pdf/1603.06393.pdf


其他有用的文章

  • Seq2Seq的優秀博文

  • http://suriyadeepan.github.io/2016-06-28-easy-seq2seq/

  • 史丹佛大課程PPT

  • http://web.stanford.edu/class/cs20si/lectures/slides_13.pdf

  • Tensorflow Seq2Seq

  • https://www.tensorflow.org/tutorials/seq2seq

  • 使用Tensorflow Seq2Seq函式的視訊教程

  • https://www.youtube.com/watch?v=ElmBrKyMXxs


相關文章