Prompt Learning详解
現階段NLP最火的兩個idea 一個是對比學習(contrastive learning) 另一個就是 prompt
prompt 說簡單也很簡單 看了幾篇論文之后發現其實就是構建一個語言模板 但是仔細想想又覺得復雜? 總感覺里面還有很多細節 因此我想從頭到尾梳理一下prompt 很多地方會把它翻譯成[范式] 但是這個詞本身不好理解 我個人更傾向于看作是模板
首先我們要知道預訓練模型(Bert為首)到底做了什么?
我覺得是預訓練模型提供了一個非常好的初始化參數 這組參數在預訓練任務上的表現非常好(預訓練損失非常低) 但是由于下游任務千奇百怪 我們需要在這組參數的基礎上進行 Fine-tune 以適應我們的下游任務(使得下游任務的損失值非常低)目前做 NLP 任務的大致流程 即 "Pre-train, Fine-tune",而對我們來說實際上大部分時候都是直接拿別人預訓練好的模型做 Fine-tune 并沒有 Pre-train 這一步 融入了 Prompt 的模式大致可以歸納成 "Pre-train, Prompt, and Predict",在該模式中 下游任務被重新調整成類似預訓練任務的形式 ok 下面我們舉例說明
假設我現在輸入一句話:中午我吃了大盤[MASK]?
然后得到一個hidden state 最后的答案必須在vocabulary 里面選擇? 候選詞是整個詞庫 我們這里希望他輸出‘雞’? 實際上可能并不是 我們需要用上loss function 當他預測不對時就會產生損失 有損失我們就可以反向傳播 然后逐漸糾正[MASK] 從而符合我們的預期
我們這里調用hugging face 里面的api 來測試一下
可以看到這里輸出概率最高的為飯 這說明在預訓練的過程中 實際上并沒有看到很多大盤和雞連在一起的情況 看的比較多的情況是?【中午我吃了大盤飯】? 但是你拿下游任務做微調的時候 是可以慢慢的讓模型輸出‘雞’ 有更高的概率 那么prompt具體是怎么做呢?這里以情感分析為例
假設這是一個二分類問題 積極或者消極原始我輸入的是 【今天天氣真好】
我們一般的做法是微調 我們會把這個句子送入bert 然后會得到一個句向量 這個句向量有很多處理方式 crf 或者softmax平均 然后會把它送入一個FC層 他的輸出維度一定是二維的 因為是二分類 然后我們做argmax或者softmax 然后得到概率最大的那個下標
prompt這樣做:我們會在【今天天氣真好】前面問一個問題(或者后面中間也可以)我會問后面的句子情感是積極的還是消極的?然后給他一個MASK 我們希望mask輸出是積極 那我們就會映射到真是標簽1 但是無論是積極或者是消極 這個token 一定要是vocabulary里面存在的?
同時 這個prompt并不是固定的 同樣的我們在api中測試一下
?在這里我們可以把強映射為1 把弱映射為0? 這樣就能完成我們的情感分析任務
除了情感分析任務 其他 NLP 任務的 Prompt 如何設計?實際上劉鵬飛大神在他的論文中給我們提供了一些參考
大概了解的prompt任務之后 我們從論文的角度再來深挖一下細節
我們可以將prompt的設計涵蓋為兩部分:
在基于 Prompt 的微調方法中 不同的模板和標簽詞對最終結果影響很大 下圖是陳丹琦團隊論文中的實驗結果
從上圖我們可以看出兩點:
然后就是離散prompt 和 連續prompt
離散 Prompts
這篇文章發表在 TACL 2020 講的是如何拿預訓練語言模型當作「知識庫」使用 并且引入了依存樹和 Paraphrase(轉述)等方法來挖掘更好的「模板」 下圖是實驗結果
可以看到 被挖掘出來的若干「連接謂詞」相比于人工設計的「模板」結果提升還是很明顯的
有很多種方法可以實現 Prompt Paraphrsing 例如「回譯」
??????然后就是??????(基于梯度的搜索)是由論文 AUTOPROMPT 提出的 這篇文章發表在 EMNLP 2020 它的主要思想用下面這張圖就可以表示
上圖中 a real joy 是原始的輸入句子Xinp 紅色的Trigger tokens 是由Xinp[激發]的相關詞匯集合Xtrig 根據Template λ 的配置 將Xtrip和Xinp組合起來構造最終的輸入Xprompt 送入Masked LM 來預測情感標簽 下面是論文中舉的例子
Prompt Generation?是陳丹琦團隊的一項工作 主要是把 Seq2Seq 預訓練模型 T5 應用到模板搜索的過程 T5基于多種無監督目標進行預訓練 其中最有效的一個無監督目標就是:利用 <X> 或 < Y > 替換一個或多個連續 span 然后生成對應輸出 例如:
?Thank you <X> me to your party <Y> week
T5 會在 <X> 生成?for inviting?在 <Y> 生成?last。很顯然,T5 這種方式很適合生成模板,而且不需要指定模板的 token 數。具體來說,有三種可能的生成方式
首先在標簽詞前后添加填充位 <X> 和 < Y>(上面提到的三種生成方式) 然后將其送入 T5 模型中 T5 會自動在填充位生成序列 最后將標簽詞(great 或 terribel)轉換為 [MASK] 標簽 形成多個模板 具體過程中采用 Beam Search 的方法生成多個候選模板 然后對每一個候選模板利用 dev 集進行微調 選擇其中一個最佳模板
我還想說一下這篇論文中另外一個有意思的點 最后送入模型進行預測的句子還拼接上了每種類別的「示例」(Demonstration) 如下圖所示
這種 Prompt 的設計有點像是在做語義相似度任務 X?為原始 Input 句子 已知?Y?為正例 Z?為負例 構造了如下形式的輸入:?
?X是[MASK]例?Y為正例 Z為負例
實際上是依據下面兩條規則:
連續 Prompts
構造 Prompt 的初衷是能夠找到一個合適的方法 讓 Pre-trained Language Model(PLM)更好地輸出我們想要的結果 但其實并不一定要將 Prompt 的形式設計成人類可以理解的自然語言 只要機器理解就行了 因此 還有一些方法探索連續型 Prompts—— 直接作用到模型的 Embedding 空間 連續型 Prompts 去掉了兩個約束條件 這也是最關鍵的兩點!
Prefix Tuning?最開始由 Li 等人提出 這是一種在輸入句子前添加一組連續型向量的方法 該方法保持 PLM 的參數不動 僅訓練前綴(Prefix)向量?Prefix Tuning 的提出主要是為了做生成任務,因此它根據不同的模型結構定義了不同的 Prompt 拼接方式,在 GPT 類的 Auto-Regressive(自回歸)模型上采用的是?[Prefix;x;y]?的方式,在 T5 類的 Encoder-Decoder 模型上采用的是?[Prefix;x;Prefix′;y]?的方式
輸入部分?Prefix,x,y?的 Position id 分別記作?Pidx,Xidx,Yidx。Prefix Tuning 初始化一個可訓練的矩陣,記作?Pθ∈R|Pidx|×dim?(hi),其中
?上述公式的含義是,索引?i?如果屬于前綴的部分,則從?Pθ?中抽取向量;i?如果不是前綴部分,則由參數固定的預訓練模型生成對應的向量。訓練目標為:
同樣是在連續空間上搜索 Prompt,OptiPrompt?構建的「模板」并不局限于前綴,也可以在句子的中間?
首先根據 AutoPrompt 定義一個 Prompt 模板:
[x]?[v]1?[v]2?...?[v]m?[MASK]
其中?[v]i?為一個連續型向量(與 BERT 的輸入維度一致)。OptiPrompt 還考慮以人工構建的離散 Prompt 作為起點,在連續空間上進行搜索以構建較優的 Prompt。例如?[x]?is?[MASK]?citizen?可以轉換為[x]?[v]1?[MASK]?[v]2 將?is?和?citizen?對應的 input Embedding 作為?[v]1?和?[v]2?的初始化
Hard-Soft Prompt Hybrid Tuning 方法可以說是人工設計和自動學習的結合,它通常不單純使用可學習的 Prompt 模板,而是在人工設計的模板中插入一些可學習的 Embedding。實際上有了上面的基礎我們都知道,連續的 Prompt 要比離散的 Prompt 好一點,但是在此基礎上還有什么改進的余地嗎?Liu 等人提出的?P-Tuning?解決了 Prompt token 之間的關聯性問題
之前連續的 Prompt 生成方式無非都是訓練一個矩陣,然后通過索引出矩陣的某幾行向量拼起來。坦白地說,我們希望這些 prompt token Embedding 之間有一個比較好的關聯性,而不是獨立地學習,為了解決這個問題,P-Tuning 引入了一個 Prompt Encoder(如下圖 b 所示)
?## 下面的數學公式我們就不多討論了?
上圖 a 是傳統的離散型 Prompt,我們把生成離散 Prompt token 的東西叫做 Prompt Generator;上圖 b 首先傳入一些 Virtual(Pseudo)token,例如 BERT 詞表中的 [unused1],[unused2],... 當然,這里的 token 數目是一個超參數,插入的位置也可以調整。將這些 Pseudo token 通過一個 Prompt Encoder 得到連續的向量?h0,...,hm,其中
hi=MLP([hi→;hi←])=MLP([LSTM(h0:i):LSTM(hi:m)])
即,Prompt Encoder 是由 BiLSTM+MLP 組成的一個簡單網絡。作者還發現加入一些 anchor token(領域或者任務相關的 token)可以有助于 Template 的優化。例如文本蘊含任務,輸入是前提和假設,判斷是否蘊含。一個連續的模版是
[PRE][continuous tokens][HYP][continuous tokens][MASK]
在其中加入一個 anchor token:[?]?效果會更好,此時模板變成
[PRE][continuous tokens][HYP]?[continuous tokens][MASK]
大家可能想問,如何優化 P-tuning?實際上根據標注數據量的多少,分兩種情況討論
就在 P-Tuning 方法提出不久后,Liu 等人又提出了?P-Tuning v2,主要解決 P-Tuning 的兩個問題:
Liu 等人認為先前的 P-Tuning 只用了一層 BiLSTM 來編碼 Pseudo token,這是其推理能力不足的原因之一,因此 v2 版本提出 Deep Prompt Tuning,用 Prefix Tuning 中的深層模型替換 BiLSTM,如下圖所示
?P-Tuning v2 相比于 P-Tuning,區別在于:
取消 Reparameterization:以前的方法利用重參數化功能來提高訓練速度和魯棒性(例如,用于 Prefix-Tuning 的 MLP 和用于 P-Tuning 的 LSTM)。在 P-Tuning v2 中,作者發現重參數化的改進很小,尤其是對于較小的模型,同時還會影響模型的表現
Multi-task Learning:Deep Prompt Tuning 的優化難題可以通過增加額外的任務數據或者無標注數據來緩解,同時可微調的 Prefix Continuous Prompt 也可以用來做跨任務的知識共享。例如在 NER 中,可以同時訓練多個數據集,不同數據集使用不同的頂層 Classifier,但是 Prefix Continuous Prompt 是共享的
取消 verbalizer:v2 取消了標簽映射,完全變為生成模型,可以在 [CLS] 部分輸出句子級別的標簽(Sentence-level label),也可以在每個 token 位置輸出 token 級別的標簽(Token-level label),直接輸出真實標簽
這里說一下我的理解:
首先是 v1 版本的 LSTM 實際上引入 LSTM 目的是為了幫助「模板」生成的 token(某種程度上)更貼近自然語言 或者說 token 之間的語義更流暢 但更自然的方法應該是在訓練下游任務的時候 不僅預測下游任務的目標 token(例如 great terrible),還應該同時做其他 token 的預測
比如 如果是 MLM 模型 那么也隨機 MASK 掉其它的一些 token 來預測 如果是 LM 模型 則預測完整的序列 而不單單是目標詞 這樣做的理由是:因為我們的 MLM/LM 都是經過自然語言預訓練的 所以我們認為它能夠很好的完成序列的重構 即便一開始不能 隨著迭代輪數的增加 模型也能很好完成這項任務 所以這本質上是讓模型進行「負重訓練」
最后一個點
為什么要引入 Prompt?
在標準的 Fine-tune 過程中(如上圖 b 所示) 新引入的參數量可能會很大(獨立于原始預訓練模型外的參數) 例如基于 RoBERTa-large 的二分類任務會新引入 2048 個參數(1024, 2)如果你僅有例如 64 個標注數據這樣的小樣本數據集 微調就會非常困難
為解決這一問題 Prompt 應運而生(如上圖 a 所示) 直接將下游任務轉換為輸出空間有限的 MLM 任務 但是上述方法在預訓練參數的基礎上進行微調 并且沒有引入任何新參數 同時還減少了微調和預訓練任務之間的差距 總的來說 這可以更有效地用于小樣本場景
tips:上述提到的論文我基本上都提供了超鏈接 如果還想了解更多細節可以閱讀原作者論文//
總結
以上是生活随笔為你收集整理的Prompt Learning详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 什么是 prompt learning?
- 下一篇: prompt范式