如何用 GPT2 和 BERT 建立一個可信的 reddit 自動回覆機器人?

上個月,我嘗試構建一個 reddit 評論機器人,通過結合兩個預先訓練的深度學習模型 GPT-2 和 BERT 生成自然語言回覆。在這裡我想一步一步地介紹一下我的工作,這樣其他人就可以用我所建立的東西來工作了。如果願意,可以直接跳轉到項目代碼:https://github.com/lots-of-things/gpt2-bert-reddit-bot。這項工作還參考了以下內容:https://colab.research.google.com/drive/1VLG8e7YSEwypxU-noRNhsv5dW4NfTGce;https://colab.research.google.com/github/google-research/bert/blob/master/predicting_movie_reviews_with_bert_on_tf_hub.ipynb

模型概述

在討論細節之前,我想對整個過程做一個概述。這個流程圖顯示了我需要訓練的 3 個模型,以及將模型連接在一起以生成輸出的過程。

如何用 GPT2 和 BERT 建立一个可信的 reddit 自动回复机器人?

這裡有很多步驟,但我希望它們不要太混亂。以下是我將在這篇文章中解釋的步驟。

  • 步驟 0:從你最喜歡的 reddit 文章中獲取一些 reddit 評論數據,並將其格式化為類似「comment[SEP]reply」的字符串

  • 步驟 1:微調 GPT-2 以生成格式為「comment[SEP]reply」的 reddit 文本

  • 步驟 2:微調兩個 BERT 分類器:

a: 區分真實回覆和 GPT-2 生成的回覆

b: 預測評論將獲得多少次支持

  • 步驟 3:使用 praw 下載當前評論

  • 步驟 4:使用微調的 GPT2 為每個評論生成多個回覆

  • 步驟 5:將生成的回覆傳遞給兩個 BERT 模型,以生成對真實性和投票數的預測

  • 步驟 6:使用一些標準來選擇要提交的回覆

  • 步驟 7:使用 praw 提交所選評論

  • 步驟 8:享受成果!

獲取大量 reddit 評論數據

與任何機器學習項目一樣,只有獲得用於訓練模型的數據,才能啟動項目。

我用來微調模型的數據來自之前檢索到的 reddit 評論大型數據庫:https://bigquery.cloud.google.com/dataset/fh-bigquery:reddit_comments?pli=1。有一個正在進行的項目(https://www.reddit.com/r/bigquery/wiki/datasets),它在 web 上搜索許多站點,並將它們存儲在一堆 Google BigQuery 表中。對我來說,我很驚訝竟然找不到一個關於如此大的項目的中心頁面,但我用了幾個 reddit 和 medium 帖子來拼湊我需要的查詢格式。

首先,我下載了一堆評論和回覆信息,分別是「寫作」、「科幻」、「科幻小說」、「機器學習」、「哲學」、「COGSICI」、「神經學」和「未來學」。此查詢用於從 bigquery 中提取特定年份和月份({ym})的註釋。

SELECT s.subreddit as subreddit,

s.selftext as submission, a.body AS comment, b.body as reply,

s.score as submission_score, a.score as comment_score, b.score as reply_score,

s.author as submission_author, a.author as comment_author, b.author as reply_author

FROM `fh-bigquery.reddit_comments.{ym}` a

LEFT JOIN `fh-bigquery.reddit_comments.{ym}` b

ON CONCAT('t1_',a.id) = b.parent_id

LEFT JOIN `fh-bigquery.reddit_posts.{ym}` s

ON CONCAT('t3_',s.id) = a.parent_id

where b.body is not null

and s.selftext is not null and s.selftext != ''

and b.author != s.author

and b.author != a.author

and s.subreddit IN ('writing',

'scifi',

'sciencefiction',

'MachineLearning',

'philosophy',

'cogsci',

'neuro',

'Futurology')

我使用 bigquery python API 自動生成查詢,以便下載 2017 年和 2018 年的幾個月的數據。這個腳本在我需要的時間段內迭代,並將它們下載到 raw_data/ 文件夾中的本地磁盤。

最後,我希望能夠給 GPT-2 網絡加上一條評論並生成一個回覆。為此,我需要重新格式化數據,使其包含由特殊 [SEP] 字符串分隔的兩部分,以便讓算法分清每個部分。每行訓練數據看起來是如下的樣子。

"a bunch of primary comment text [SEP] all of the reply text”

在我用這種格式訓練模型之後,我可以給訓練模型一個字符串,比如「一些新的主要評論文本」,它將開始根據訓練數據生成它認為最適合的剩餘的「一些新回覆」。下面我將更詳細地解釋如何將此類數據輸入 GPT-2 微調腳本。現在,你可以使用此腳本將數據轉換為 GPT-2 微調所需的格式,並將其保存為 gpt2_finetune.csv。

微調 GPT-2 併為 reddit 生成文本

使用 GPT-2 的主要優勢在於,它已經在互聯網上數百萬頁文本的海量數據集上進行了預訓練。然而,如果你直接使用 GPT-2,你最終生成的文本會看起來像你在互聯網上找到的任何東西。有時它會生成一篇新聞文章,有時它會生成一個烹飪博客菜譜,有時它會生成一個充滿憤怒情緒的 facebook 帖子。你沒有太多的控制權,因此,你將無法真正使用它來有效地生成 reddit 評論。

為了克服這個問題,我需要「微調」預先訓練的模型。微調意味著採用一個已經在大數據集上訓練過的模型,然後只使用你想要在其上使用的特定類型的數據繼續對它進行訓練。這個過程(有點神奇地)允許你從大的預訓練模型中獲取大量關於語言的一般信息,並用所有關於你正試圖生成的確切輸出格式的特定信息對其進行調整。

微調是一個標準的過程,但並不是很容易做到。我不是一個深度學習專家,但幸運的是,對我來說,一個非常優秀的專家已經建立了一些非常簡單的打包好的實用程序,它就是 gpt-2-simple,可以用於微調 gpt-2,是不是很簡單?!

最棒的是,gpt-2-simple 的作者甚至建立了一個經過微調的 Google Colab notebook。Google Colab 是一個令人驚歎的免費資源,可以讓你在 Google GPU 服務器上運行 python jupyter notebook。這項資源完全公開,因此我正式成為了谷歌的終身粉絲。

你可以跟隨教程(https://colab.research.google.com/drive/1VLG8e7YSEwypxU-noRNhsv5dW4NfTGce)學習如何使用 GPT-2-simple 微調 GPT-2 模型。對於我的用例,我把所有的代碼壓縮並重新格式化了一點,以生成自己的 gpt-2 notebook(https://colab.research.google.com/drive/1VyOU81rsPsP_8WSKq-VZfB8TcMkPszG-),它運行在我在上一步生成的 gpt2_finetune.csv 文件上。和在原始教程中一樣,你需要授予筆記本從 Google 驅動器讀寫的權限,然後將模型保存到 Google 驅動器中,以便從以後的腳本重新加載。

用於偽檢測和上投票預測的訓練BERT模型

即使經過微調,這個模型的輸出也可能會相當怪異。為了提高回覆的質量,我修改了 GAN 的概念,創建了另一個元模型,這個模型能夠找出所有奇怪的回覆。因此,我使用 GPT-2 為每條評論生成 10+ 個候選回覆,然後使用另一個模型篩選出我能發佈的最佳回覆。

為了確定最佳方案,我實際上想做兩件事:

  • 過濾掉不切實際的回覆

  • 對於具有現實性的回答,選擇一個我認為最有說服力的

因此,為了做到這一點,我必須訓練兩個分類器,一個是預測真實回覆的概率,另一個是預測高分回覆的概率。有很多方法可以執行這個預測任務,但是最近為這類問題構建的最成功的語言模型之一是另一種深度學習架構,稱為 Transformers 或 BERT 的雙向編碼器表示。使用這個模型的一個很大的好處是,與 GPT-2 類似,研究人員已經在我永遠無法獲得的超大型數據集上預先訓練了網絡。

同樣,我不是使用深度學習基礎設施最厲害的專家,但幸運的是,其他優秀的 tensorflowhub 專家編寫了一個 GoogleColab 教程(https://colab.research.google.com/github/google-research/bert/blob/master/predicting_movie_reviews_with_bert_on_tf_hub.ipynb),使用預先訓練的 BERT 網絡對文本分類器模型進行微調。所以我所要做的就是把兩者結合起來。

在下一節中,我將介紹微調和一些模型評估,但是如果你想快速啟動而不想自己費心微調,可以從這裡(https://drive.google.com/open?id=1GmGNqihV0nCQ6evLBmopOhjups_RESv-)、這裡(https://drive.google.com/open?id=1-Bov5PtPrP2DvFw4yD-lxp2wTjGw0bwB)和這裡(https://drive.google.com/file/d/1DTfYUxXEz80S0baCb4xPSrzx85F0FVTP/view?usp=sharing)下載三個微調的模型。

BERT 鑑別器性能

評估現實性的模型的訓練就和在傳統的 GAN 中一樣。我讓另一個 Colab notebook 生成了成千上萬的虛假評論,然後創建了一個數據集,將我的虛假評論與成千上萬的真實評論混在一起。然後,我把這個數據集輸入一個 BERT 現實性微調的 notebook 進行訓練和評估。該模型實際上具有驚人的區分真假評論的能力。

BERT 現實性模型度量

'auc': 0.9933777,

'eval_accuracy': 0.9986961,

'f1_score': 0.99929225,

'false_negatives': 3.0,

'false_positives': 11.0,

'precision': 0.9988883,

'recall': 0.99969655,

'true_negatives': 839.0,

'true_positives': 9884.0

接下來,生成器創建的每個回覆都可以通過這個 BERT 鑑別器運行,根據其真實性會得到從 0 到 1 的分數。然後我只過濾返回最具有真實性的評論。

為了預測一個回覆將獲得多少次支持,我以類似的方式(https://drive.google.com/open?id=1vXJjQbBZZ0Jo-LvcwRaNzCSAgAVem1cC)構建了另一個模型。這一次,這個模型只是在一個數據集上訓練,這個數據集包含了一堆真實的 reddit 評論,用來預測他們實際獲得了多少投票。

該模型還具有令人驚訝的高預測精度。下面這個 ROC 曲線表明,我們可以得到很多正確的真陽性,而不會有太多的假陽性。關於真陽性和假陽性的含義,請參閱本文:https://developers.google.com/machine-learning/crash-course/classification/true-false-positive-negative。

如何用 GPT2 和 BERT 建立一个可信的 reddit 自动回复机器人?

基於BERT 的支持票預測的 ROC 曲線

在模型交叉驗證性能的支持下,我很高興將它連接到一個實時評論系統,並開始發佈我的機器人的想法!

用PRAW拉實時評論

儘管我可以使用 bigquery 上的數據生成訓練集,但大多數數據實際上都是幾個月前的。在社交媒體網站上回復幾個月前的評論是一件非常不正常的事情,因此能夠以某種方式從 reddit 上獲取最新的數據非常重要。

幸運的是,我可以使用 praw 庫和下面的代碼片段,從幾個我認為會產生一些有趣響應的 reddit 中的前 5 個「上升」帖子中獲取所有評論。

for subreddit_name in ['sciencefiction',

'artificial',

'scifi',

'BurningMan',

'writing',

'MachineLearning',

'randonauts']:

subreddit = reddit.subreddit(subreddit_name)

for h in subreddit.rising(limit=5):

我可以在生成器和鑑別器中運行每條評論以生成一個回覆。

運行生成器和鑑別器

最後,我只需要構建一些東西來重新加載所有經過微調的模型,並通過它們傳遞新的 reddit 評論來獲得回覆。在理想的情況下,我會在一個腳本中運行 GPT-2 和 BERT 模型。不幸的是,設計人員在實現 gpt2-simple 包的過程中有一個怪癖,使得在同一個環境中無法實例化兩個計算圖。

所以,我自己運行了一個 GPT-2 生成器 notebook(https://drive.google.com/open?id=1Z-sXQUsC7kHfLVQSpluTR-SqnBavh9qC),下載最新的評論,生成一批候選回覆,並將它們存儲在我的 Google 驅動器上的 csv 文件中。然後,我在一個單獨的 BERT 鑑別器 notebook(https://drive.google.com/open?id=1mWRwK1pY34joZul5gBeMortfTu8M9OPC)中重新加載了候選的回覆,選擇最好的回覆並將其提交回 reddit。

你可以在項目的 github repo(https://github.com/lots-of-things/gpt2-bert-reddit-bot)或 Google Drive文件夾(https://drive.google.com/open?id=1by97qt6TBpi_o644uKnYmQE5AJB1ybMK)中查看整個工作流。如果你認為事情可以解釋得更清楚,或者你發現了錯誤,請將問題提交給項目。

最後一步:享受成果

我在 tupperware party 的 reddit 帳戶下提交了所有回覆(希望不會因為商標問題而被關閉)。你可以在這裡(https://www.bonkerfield.org/2020/02/combining-gpt-2-and-bert/#replies)查看模型輸出的一些亮點,或者查看註釋的完整列表,以檢查系統輸出的所有內容。我也在 Google Drive 上共享了一個文件夾(https://drive.google.com/drive/folders/1a2MhIqL6jvyJ-3bGCXAweLbYtNXSUei7?usp=sharing),其中包含了所有的候選答案以及 BERT 模型中的分數。

最後,我知道在創作這樣的作品時,肯定有一些倫理上的考慮。所以,請儘量負責任地使用這個工具。

via:https://www.bonkerfield.org/2020/02/reddit-bot-gpt2-bert/

雷鋒網雷鋒網雷鋒網


分享到:


相關文章: