使用gpt來做聊天機械人

2021-09-28 23:40:44 字數 3697 閱讀 9885

探索筆記,有些亂,吻噴。

主要思想:根據歷史對話,生成新的語句:注意,這裡不一定是回答語句。

a)基礎資料:100w qq聊天對話。見下圖

i)沒有分詞,以字為基礎進行編碼。

ii)歷史對話最少要求有兩句,也就是從第三句形如,依次做為答案之前的話語做為歷史記錄。句子的開始和結束分別加上標誌符號,名字間用[sep]分割。如下所示:

現在刷朋友圈最大的快樂就是看**們各種直播。。。。。[sep]臥槽我也是[sep][眼淚]知道**在打折 最近台灣屈臣氏周年慶

現在刷朋友圈最大的快樂就是看**們各種直播。。。。。[sep]臥槽我也是[sep][眼淚]知道**在打折 最近台灣屈臣氏周年慶[sep]11月去台灣sogo周年慶[doge]

現在刷朋友圈最大的快樂就是看**們各種直播。。。。。[sep]臥槽我也是[sep][眼淚]知道**在打折 最近台灣屈臣氏周年慶[sep]11月去台灣sogo周年慶[doge][sep]去旅遊嗎[doge]

現在刷朋友圈最大的快樂就是看**們各種直播。。。。。[sep]臥槽我也是[sep][眼淚]知道**在打折 最近台灣屈臣氏周年慶[sep]11月去台灣sogo周年慶[doge][sep]去旅遊嗎[doge][sep]四啊[doge]

iii)對ii)中的資料做padding,按最長長度來做,但最長長度要小於n_ctx引數,過長了,把前面的截斷。

c)模型引數:model = gpt-lm-model , lr = 5*10e-5 , input_ids = labels = 上面padding後的tensor。epoch=5 , batch=2

d)結果分析:結果是沒有收斂,續寫的話簡直不忍直視。

主要思想:考慮到1的實驗沒有收斂,修改句子的處理方式。並加入預熱處理。

a)基礎資料:與實驗一相同。

b)資料處理:對句子不做padding,把所有的句子拼接成一行,句子間有分隔符。取長度為n_ctx為視窗長度,視窗每次滑動的距離為stride(768)。生成若干等長樣本。

c)模型引數:model = gpt-lm-model , lr = 5*10e-5 , input_ids = labels = 上面padding後的tensor。epoch=5 , batch=2 , warmstep=2000 , gradient_accumulation_steps = 8

d)結果分析:

1)乙個epoch 36w step, 跑十幾個小時,傷不起啊。之後需要減小資料量來做實驗。

2)模型的損失在5000step從9降到2,收斂速度較快。之後下降較慢。乙個epoch跑下來,也就降到2以後,沒有突破1.

3)訓練結果分析:

i) 由於訓練語料中沒有去掉[dog]等表情符,導致續寫結果中有大量的表情符(有些還連續出現)。

ii) 句子中有很多莫名奇秒的續寫,不太好理解。為了確定是否與語料有關,用同樣的方法,使用《鬥破蒼穹》**的語料來訓練(因為有人用這個搞過,我能判斷我的模型有沒有問題),對比結果,發現模型在《鬥破蒼穹》上的表現要比在閒聊語料上的好很多。分析原因可能有兩點。1、鬥破蒼穹本身是一本**,是乙個作者寫的,主題和語言技巧通篇都很相似,模型的學習任務更簡單,更容易學習。2、語料規模差距,閒聊語料我使用了100w,171m,是鬥破的10倍,本身只訓練了乙個epoch(360000步),而鬥破我訓練了30個epoch(從第5個epoch起就沒啥提高了)。所以相對而言,聊天語料的訓練時長和迭代次數也欠少,這可能也是導致結果差的原因。

iii)實際中使用lm模型時,有乙個切分的問題,雖然lm模型把標點也給**了,但是模型並不會因為遇到句號就停止,什麼時候停止,這個還是我們用程式來控制。簡單粗暴的乙個方法是遇到句號、嘆號、問號等標點就結束。但實際的結果中,有些回答是以幾個表情符結束的(語料不乾淨啊),情況要複雜的多。所以還得是做padding啊,不能按語言模型來搞。

a)基礎資料:資料與上面的相同。為了加快實驗程序,只取了60萬的資料來做實驗。

b)資料處理:

1)訓練語料的格式以組為單位,每組中包含乙個正例(history + reply) 和若干負例( history + distractors )

2)history 最少需要兩句,最多不超過5句。

因為我們是要使用gpt double head model , 所以這次的輸入有些多,我按每個head來說我們要準備的資料。

lm_head:

i)引數:input_ids , token_type_ids , position , lm_labels

ii) 說明:

input_ids : 這個就是把歷史對話和對應的回答用分隔符拼接起來,再轉成id。 具體格式 = [[bos]] + history[0] + history[1] + history[2] ] + [reply + [eos]]

token_type_ids : 這個比就是哪個詞是誰說的給標記出來,對話只只有兩個角色,我們使用speaker1、speaker2標記,開始和結束的分隔符不用管, 最後也轉會成id。長度與input_ids相同

position:這個是位置資訊,就是指每個詞是這句的第幾個,這個我們不用管,使用gpt的模型時,我們如果不傳這個引數,模型內部會自己計算。長度與input_ids相同。

lm_labels:這個是要**的標籤,我們需要注意一下,我們只對的reply部分進行編碼,其餘部分全為-1(掩碼,表示不計算損失),負債中的lm_labels標籤全為-1,不計算損失。長度與input_ids相同。

mc_head:

i)引數:mc_token_ids , mc_labels

mc_token_ids: 告訴mc_head我們要用哪個token的階層來進行計算。通常我們選擇最後乙個token。

mc_labels:告訴模型我們的正例是哪個。(一組資料中,正例的下標)

3)pading:

lm_head的輸入都需要做padding , 即 [「input_ids」, 「lm_labels」, 「token_type_ids」] 三個欄位要做padding, padding的長度取inputs_ids中的最大長度就可以(這三個向量其實是相同長度的)

4)整體格式:

i) 對於每次迭代的乙個輸入size: [批大小][每組的樣本數][樣本長度]

ii)輸入比較多,容易亂。建議寫個資料結構(instance),包含history , reply , distractors。然後寫乙個轉換的方法,根據這三個字段生成輸入的5個字段。這樣,我們最終的資料就是乙個instance列表,訓練時取出若干個instance拼成乙個batch。然後進行訓練。

c)模型引數:

引數1:model = gpt-dh-model , lr = 510e-5 , epoch=5 , batch=1 , warmstep=2000 , gradient_accumulation_steps = 16

引數2:model = gpt-dh-model , lr = 110e-5 , epoch=5 , batch=2 , warmstep=5000 , gradient_accumulation_steps = 8

d)結果分析:續寫能力與2比沒看出來提高,明顯的優點是加入padding後,**的話能自己停止。

注:實驗結果都沒有上圖,分析的也比較粗,實在是因為結果不好,不好上圖。畢竟gpt中文沒有開源預訓練中文模型,我這相當於自己訓練,單卡跑個十幾個小時,也就是玩玩,知道怎麼搞。坐等gpt開源中文預訓練模型。

聊天機械人

我你好!小愛同學 小愛你好,很高興認識你!charset utf 8 css document 休息一會 sleep 1 獲取 使用者傳送的 訊息 可選 後端 對於 使用者發過來的 時候 是否 使用 可選 根據 傳送 過來的 訊息 返回 不同的內容 messagelist array 床前明月光,有...

機械人聊天軟體c C 聊天機械人

例項簡介 c 聊天機械人 例項截圖 核心 3181078聊天機械人 原始碼必讀.pdf 聊天機械人 1.ico 聊天機械人 1.ico form1.designer.cs form1.cs form1.resx program.cs properties assemblyinfo.cs resour...

聊天機械人ELIZA

1 在 自然語言理解 這本書的緒論中曾分析了聊天機械人eliza的設計機理,表明這是一種語言變換的技巧,而不是真正的 自然語言理解 午間休息時檢索了一下,找到了乙個它的連線 它並不如書中所舉的例子那樣的 聰明 也許因為這是第乙個聊天機械人,以及它並沒有真正採取 自然語言理解 的技術有關。下面是筆者與...