GGFly/GPT2的聊天機器人-AI算法

基于GPT2的中文聊天機器人,模型構(gòu)建采用transformers,提供預訓練模型與訓練語料。

GPT2 For Chinese Chitchat

UPDATE 2020.01.09

添加50w閑聊語料與預訓練模型的GoogleDrive的下載地址

UPDATE 2019.12.17

基于微軟的論文DialoGPT:Large-Scale Generative Pre-training for Conversational Response Generation添加了MMI Model(maximum mutual information scoring function),對dialogue model生成的多個response進行篩選

項目描述

本項目使用GPT2模型對中文閑聊語料進行訓練,使用 HuggingFace的transformers實現(xiàn)GPT2模型的編寫與訓練。

在閑暇時間用?GPT2-Chinese模型訓練了幾個長文本的生成模型,并且精讀了一遍作者的源碼,獲益匪淺,加深了自己對GPT2生成模型的一些理解,于是將GPT2模型用于閑聊對話的生成,非常感謝作者的分享。

本項目中沿用了原項目中的部分結(jié)構(gòu)和一些命名方式,同時也對很多代碼細節(jié)做出了自己實現(xiàn)。

解碼器的邏輯使用了Temperature、Top-k Sampling和Nucleus Sampling等,可參考論文The Curious Case of Neural Text Degeneration

根據(jù)微軟的DialoGPT的思想,在項目中添加了互信息。訓練了兩個模型:Dialogue Model與MMI Model(maximum mutual information scoring function)。首先使用Dialogue Model生成多個候選response,然后使用MMI Model從候選response中,選取loss最小的作為最終的response

代碼中給出了許多詳細的中文注釋,方便大家更好地理解代碼(能力有限,可能有些代碼或注釋有誤,望大家不吝賜教)

運行環(huán)境

python3.6、 transformers==2.1.1、pytorch==1.3.1

項目結(jié)構(gòu)

config:存放GPT2模型的參數(shù)的配置文件

data

train.txt:默認的原始訓練集文件,存放閑聊語料

train_tokenized.txt:對原始訓練語料進行順序tokenize之后的文件,用于dialogue model的訓練

train_mmi_tokenized.txt:對原始訓練語料進行逆序tokenize之后的文件,用于mmi model的訓練

dialogue_model:存放對話生成的模型

mmi_model:存放MMI模型(maximum mutual information scoring function),用于預測P(Source|response)

sample:存放人機閑聊生成的歷史聊天記錄

vocabulary:存放GPT2模型的字典

train.py:訓練代碼

interact.py:人機交互代碼

模型參數(shù)(詳見Config/Model_config_dialogue_small.Json文件)

initializer_range: 0.02

layer_norm_epsilon: 1e-05

n_ctx: 300

n_embd: 768

n_head: 12

n_layer: 10

n_positions: 300

vocab_size: 13317

Dialogue Model

Dialogue Model是基于GPT2模型的生成模型,對每條訓練數(shù)據(jù)進行"順序"拼接,然后將其輸入到網(wǎng)絡(luò)中,進行訓練(此處的"順序"是相對于MMI Model的"逆序")

例如存在如下多輪閑聊訓練數(shù)據(jù),在訓練Dialogue Model時,將上述訓練數(shù)據(jù)進行如下拼接:"[CLS]想看你的美照[SEP]親我一口就給你看[SEP]我親兩口[SEP]討厭人家拿小拳拳捶你胸口[SEP]"。然后將上述拼接結(jié)果作為Dialogue Model的輸入,對模型進行訓練

想看你的美照

親我一口就給你看

我親兩口

討厭人家拿小拳拳捶你胸口

MMI Model

MMI Model的思想基于微軟的論文DialoGPT:Large-Scale Generative Pre-training for Conversational Response Generation

MMI Model也是一個基于GPT2的生成模型,將每條訓練數(shù)據(jù)進行"逆序"拼接,然后輸入到網(wǎng)絡(luò)中。該模型主要用于計算Dialogue Model生成的所有候選response相對于dialogue history的loss。

訓練時,將一條訓練語料進行逆序拼接,如?"[CLS]討厭人家拿小拳拳捶你胸口[SEP]我親兩口[SEP]親我一口就給你看[SEP]想看你的美照[SEP]",并作為MMI Model的輸入進行訓練

想看你的美照

親我一口就給你看

我親兩口

討厭人家拿小拳拳捶你胸口

Response生成步驟

假設(shè)當前dialogue history=["你好","你好呀","你在干嘛呢"]

首先使用Dialogue Model根據(jù)dialogue history生成n個候選response:["在看電視","我在上課啊","人家在想你啊","我不知道"]

使用MMI Model將每個候選response分別與dialogue history進行逆序拼接,如?"[CLS]在看電視[SEP]你在干嘛呢[SEP]你好呀[SEP]你好[SEP]"

將上述拼接結(jié)果作為MMI Model的輸入,計算每個response的loss

選擇loss最小的response作為最終的結(jié)果進行回復

閑聊語料分享

中文閑聊語料數(shù)據(jù)集地址語料描述

常見中文閑聊chinese_chatbot_corpus包含小黃雞語料、豆瓣語料、電視劇對白語料、貼吧論壇回帖語料、微博語料、PTT八卦語料、青云語料等

50w中文閑聊語料百度網(wǎng)盤【提取碼:jk8d】?或?GoogleDrive由作者GaoQ1提供的比較高質(zhì)量的閑聊數(shù)據(jù)集,整理出了50w個多輪對話的語料

50w中文閑聊語料的內(nèi)容樣例如下:

謝謝你所做的一切

你開心就好

開心

嗯因為你的心里只有學習

某某某,還有你

這個某某某用的好

你們宿舍都是這么厲害的人嗎

眼睛特別搞笑這土也不好捏但就是覺得挺可愛

特別可愛啊

今天好點了嗎?

一天比一天嚴重

吃藥不管用,去打一針。別拖著

模型分享

閑聊語料大小為67M,包含50w個多輪對話。使用該語料訓練了兩個模型dialogue_model與mmi_model

模型百度網(wǎng)盤GoogleDrive模型描述

dialogue_model百度網(wǎng)盤【提取碼:osi6】GoogleDrive使用閑聊語料訓練了40個epoch,最終loss在2.0左右,繼續(xù)訓練的話,loss應該還能繼續(xù)下降。

mmi_model百度網(wǎng)盤【提取碼:1j88】GoogleDrive以dialogue_model作為預訓練模型,使用上述閑聊語料,訓練了40個epoch,最終loss在1.8-2.2之間,繼續(xù)訓練的話,loss也能繼續(xù)下降。

模型使用方法

把下載好的模型文件夾dialogue_model與mmi_model放在項目根目錄下(否則需要通過--dialogue_model_path與--mmi_model_path參數(shù)指定對應模型的路徑),執(zhí)行如下命令:

僅使用Dialogue_model進行生成

pythoninteract.py--no_cuda(使用默認參數(shù),不使用GPU。由于閑聊對話生成的內(nèi)容長度不是很長,因此生成部分在CPU上跑速度也挺快的)或pythoninteract.py--no_cuda--dialogue_model_pathpath_to_dialogue_model--max_history_len5(自定義--max_history_len參數(shù),即對話歷史的長度)或pythoninteract.py--no_cuda--dialogue_model_pathpath_to_dialogue_model--max_history_len5--topp0.8--topk0(--topp為0到1之間的小數(shù),用于調(diào)用NucleusSampling)或pythoninteract.py--no_cuda--max_history_len5--topk8(未指定--dialogue_model_path參數(shù),默認為dialogue_model)

輸入Ctrl+Z結(jié)束對話之后,聊天記錄將保存到sample目錄下的sample.txt文件中

使用Dialogue_model生成多個候選Response,然后使用Mmi_model選取互信息Loss最小的Response

interact_mmi.py的用法與interact.py類似

pythoninteract_mmi.py--no_cuda(使用默認的model路徑)或pythoninteract_mmi.py--no_cuda--batch_size5(指定生成候選response的個數(shù))或pythoninteract_mmi.py--no_cuda--debug(debug模式,可以看到生成的所有候選response及其通過mmi_model的loss)或pythoninteract_mmi.py--no_cuda--dialogue_model_pathpath_to_dialogue_model--mmi_model_pathpath_to_mmi_model(自定義模型路徑)

輸入Ctrl+Z結(jié)束對話之后,聊天記錄將保存到sample目錄下的mmi_samples.txt文件中

更多的參數(shù)介紹,可直接看interact.py和interact_mmi.py中的setup_train_args()函數(shù)中的參數(shù)說明

Interact.Py與Interact_mmi.Py的參數(shù)

執(zhí)行interact.py時,可以嘗試通過調(diào)整topk、topp、repetition_penalty、max_history_len等參數(shù),調(diào)整生成的效果。詳細的參數(shù)描述可以查看interact.py的set_interact_args()函數(shù)

訓練模型

在項目根目錄下創(chuàng)建data文件夾,將原始訓練語料命名為train.txt,存放在該目錄下。train.txt的格式如下,每段閑聊之間間隔一行。

訓練模型:

# 若是訓練mmi_model則需要指定--train_mmi參數(shù);若是訓練dialogue_model,則不需要指定--train_mmi參數(shù)#訓練dialogue_modelpythontrain.py --epochs 30 --batch_size 8 --device 0,1 --raw(若要對原始訓練語料進行tokenize,則要指定--raw參數(shù)。若要用GPU訓練,則通過--device指定GPU)或pythontrain.py --epochs 30 --batch_size 8 --no_cuda --raw(指定--no_cuda參數(shù),則使用CPU訓練,速度要慢得多)或pythontrain.py --epochs 30 --batch_size 8 --no_cuda(若已經(jīng)對原始語料進行tokenize,可以不用指定--raw,避免重復tokenize,節(jié)約時間)#訓練mmi_model,要指定--train_mmi參數(shù)pythontrain.py --epochs 30 --batch_size 8 --device 0,1 --raw --train_mmi(對原始訓練語料進行逆序拼接,tokenize,并且訓練mmi_model)或pythontrain.py --epochs 30 --batch_size 8 --device 0,1 --train_mmi(若已經(jīng)對原始訓練語料tokenize,則直接訓練mmi_model)或pythontrain.py --epochs 30 --batch_size 8 --device 0,1 --train_mmi --pretrained_model path_to_pretrained_model(在與訓練模型基礎(chǔ)上繼續(xù)訓練)

更多的參數(shù)介紹,可直接看train.py中的setup_train_args()函數(shù)中的參數(shù)說明

Interact.Py生成樣例

Sample 1:

user:你好啊chatbot:你好,請問您是?user:我是你的主人啊 chatbot:你是狗嗎?user:你才是狗chatbot:你不是狗我是你的小主人user:你這個大笨蛋chatbot:你大笨蛋,你是想挨打了user:你全家都是大笨蛋chatbot:我是你爸爸user:算了,不跟你吵了,你在干嘛呢chatbot:我在上班啊,你還沒下班呢啊你user:我周末要做作業(yè)啊chatbot:不是才交了嗎,早晚做完啊user:好多作業(yè)啊,還沒做完呢chatbot:我在抄,我媽讓我周五交,還有事user:你就不怕被你媽媽罵嗎chatbot:不怕user:你周末有去哪里玩嗎chatbot:沒時間啊,忙得很啊user:忙著干嘛呢chatbot:不知道啊,我周末沒有作業(yè),我想睡覺,然后還得找人

Sample 2:

user:你好啊chatbot:你好我好大家好user:你在干嘛呢chatbot:你不上課啊user:今天是周末啊,笨蛋chatbot:我在學校呢user:我也是,周末還要做作業(yè)chatbot:我還沒寫呢我們都還沒寫user:周末你有去哪里玩嗎chatbot:沒有去南京user:南京有什么好玩的啊chatbot:我們沒去南京user:你剛剛又說你去了南京,你是不是耍我啊chatbot:我剛剛才到南京user:你好笨啊chatbot:我沒有user:你是大笨蛋chatbot:你才是大笨蛋user:你全家都是大笨蛋chatbot:你個傻冒user:你個智障chatbot:哈哈哈

Sample 3:

user:在干嘛chatbot:睡覺user:這么早就睡覺啦chatbot:嗯啊你也早點睡啊user:我再玩一會兒手機chatbot:早點休息晚安user:拜拜啦chatbot:晚安晚安user:多喝熱水chatbot:哈哈哈user:多喝熱水chatbot:好的咯

Sample 4:

user:在嗎chatbot:在user:我不開心chatbot:怎么啦user:最近好累啊chatbot:是挺累的user:作業(yè)好多啊chatbot:還好還好user:我覺得我快要掛科了chatbot:我也是啊,但是我覺得我快熬出頭了user:不說了,我還有好多作業(yè)沒寫chatbot:我也是啊好多啊user:那先這樣,下次再聊,再見了chatbot:好噠

Sample 5:

user:你去過廣州嗎chatbot:去過呀,但是沒有找到工作呢user:那你去過北京嗎chatbot:沒有啊user:北京有什么好玩的chatbot:沒有你想象的那么好user:是嗎,我還沒過北京chatbot:那里我也不怎么熟,我去過北京user:北京天安門呢chatbot:沒去過,不過可以去玩玩

Sample 6:

user:你好chatbot:你好user:在干嘛呢chatbot:在想你呢user:好害羞啊chatbot:害羞什么啊user:你這樣夸我,我覺得不好意思呀chatbot:我夸你你還不好意思呢user:是啊,哈哈哈chatbot:你是不是在考驗我user:你怎么會這樣想呢chatbot:我說我在夸你,這么客氣,user:你有睡午覺嗎chatbot:有啊user:我現(xiàn)在有點困呢chatbot:我也是user:等下還要去上課,好煩啊chatbot:我們不用上課的呀

Interact_mmi.Py生成樣例(Debug模式下)

添加了MMI Model之后,效果確實提高了許多,可以看到,使用loss越小的response進行回復,對話越流暢

每個Sample為完整的一段對話,為了方便閱讀,每輪對話之間加上了換行符。candidate response為dialogue model生成的候選response

需要指定--debug參數(shù)才會輸出候選response及其loss

Sample 1:

user:你好candidateresponse:你好loss:1.8774782419204712你好!loss:2.1092255115509033你好loss:1.8774782419204712你好,朋友loss:1.9210820198059082你好!loss:2.1092255115509033chatbot:你好user:在干嘛呢candidateresponse:上課玩手機loss:1.8411542177200317上班呢loss:1.8623629808425903上班啊loss:1.8383764028549194剛吃完飯,你呢,我今天吃飽了沒事,后天出去吃宵夜,loss:2.471815586090088剛剛搬家loss:2.341609239578247chatbot:上班啊user:周末要一起出去玩嗎candidateresponse:可以呀loss:2.0150623321533203可以呀loss:2.0150623321533203可以,你還是做老師嗎loss:2.2639517784118652可以啊loss:1.9695569276809692周末要loss:2.1701855659484863chatbot:可以啊user:我好想你啊candidateresponse:我也好想你啊loss:1.8660272359848022那我們就可以一起出來玩呀loss:2.046417236328125我也好想你啊loss:1.8660272359848022我也很久沒出去玩啦loss:2.17940354347229來找我吧loss:2.14339542388916chatbot:我也好想你啊user:愛你么么噠candidateresponse:么么噠loss:1.6875463724136353好想你可是也不著急了loss:2.2054319381713867么么噠loss:1.6875463724136353你會愛上新花園的人嗎loss:2.521526575088501我也愛你loss:1.6839145421981812chatbot:我也愛你user:你喜歡我嗎candidateresponse:那必須是啊loss:1.545378565788269喜歡你啊loss:1.4527238607406616喜歡喜歡loss:1.4971727132797241還行吧loss:1.5946317911148071你是我的小公舉么么噠你還不睡覺啊loss:1.6506415605545044chatbot:喜歡你啊

Sample 2

user:親愛的在干嘛呢

candidateresponse:剛看了一個小片段子,好難過loss:2.541116714477539你猜呀loss:2.1126084327697754親愛的休息啊loss:2.073425054550171在家里玩兒loss:1.9639413356781006我在等你啊loss:1.9869526624679565chatbot:在家里玩兒user:作業(yè)寫完了嗎candidateresponse:沒啊,你呢loss:2.01458477973938沒有今天剛寫完loss:2.0036869049072266沒,今天剛寫完loss:2.0473012924194336沒有l(wèi)oss:1.9207587242126465沒呢,明天上午沒課loss:1.943585753440857chatbot:沒有user:還不快滾去寫作業(yè)candidateresponse:我們還沒寫呢loss:2.271885871887207我還沒寫呢loss:2.1460421085357666哈哈哈我還沒loss:2.2205970287323去死loss:2.469320058822632我們還要寫作業(yè)loss:2.247976779937744chatbot:我還沒寫呢user:你個大笨蛋candidateresponse:我就說loss:2.052217483520508你個大傻紙loss:1.9332027435302734可以loss:2.0493569374084473你才是loss:1.8672529458999634我們五月五號才放寒假loss:2.1910266876220703chatbot:你才是user:你是傻子吧candidateresponse:是你是你loss:2.3064982891082764你是大傻loss:2.4247941970825195好好上課loss:2.4157748222351074你是傻子你說誰是傻子loss:2.1408958435058594是你才是loss:2.4862639904022217chatbot:你是傻子你說誰是傻子user:說的就是你,怎樣candidateresponse:傻子,你才傻loss:2.2158799171447754我不傻loss:2.188838005065918傻的跟你一樣loss:2.3169684410095215那你是聰明的小孩,你想怎樣?loss:2.2750229835510254你才傻loss:2.262368679046631chatbot:我不傻user:不和你玩了candidateresponse:你怎么那么傻loss:2.126516819000244我是傻子loss:2.044743061065674我不和你說話了loss:2.107841730117798不要loss:2.124176502227783我不和你玩你說我傻loss:2.1581454277038574chatbot:我是傻子

不足之處

沒有對chatbot生成的response的內(nèi)容進行檢測,有時會生成一些敏感、略帶玩笑性質(zhì)的辱罵內(nèi)容

Future Work

對生成內(nèi)容進行控制

Reference

The Curious Case of Neural Text Degeneration

transformers

GPT2-Chinese

DialoGPT:Large-Scale Generative Pre-training for Conversational Response Generation

閱讀原文<<

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容