Bert最近很火,應該是最近最火爆的AI進展,網上的評價很高,那么Bert值得這么高的評價嗎?我個人判斷是值得。那為什么會有這么高的評價呢?是因為它有重大的理論或者模型創新嗎?其實并沒有,從模型創新角度看一般,創新不算大。但是架不住效果太好了,基本刷新了很多NLP的任務的最好性能,有些任務還被刷爆了,這個才是關鍵。另外一點是Bert具備廣泛的通用性,就是說絕大部分NLP任務都可以采用類似的兩階段模式直接去提升效果,這個第二關鍵。客觀的說,把Bert當做最近兩年NLP重大進展的集大成者更符合事實。
本文的主題是自然語言處理中的預訓練過程,會大致說下NLP中的預訓練技術是一步一步如何發展到Bert模型的,從中可以很自然地看到Bert的思路是如何逐漸形成的,Bert的歷史沿革是什么,繼承了什么,創新了什么,為什么效果那么好,主要原因是什么,以及為何說模型創新不算太大,為何說Bert是近年來NLP重大進展的集大成者。我們一步一步來講,而串起來這個故事的脈絡就是自然語言的預訓練過程,但是落腳點還是在Bert身上。要講自然語言的預訓練,得先從圖像領域的預訓練說起。
圖像領域的預訓練
自從深度學習火起來后,預訓練過程就是做圖像或者視頻領域的一種比較常規的做法,有比較長的歷史了,而且這種做法很有效,能明顯促進應用的效果。
那么圖像領域怎么做預訓練呢,上圖展示了這個過程,我們設計好網絡結構以后,對于圖像來說一般是CNN的多層疊加網絡結構,可以先用某個訓練集合比如訓練集合A或者訓練集合B對這個網絡進行預先訓練,在A任務上或者B任務上學會網絡參數,然后存起來以備后用。假設我們面臨第三個任務C,網絡結構采取相同的網絡結構,在比較淺的幾層CNN結構,網絡參數初始化的時候可以加載A任務或者B任務學習好的參數,其它CNN高層參數仍然隨機初始化。之后我們用C任務的訓練數據來訓練網絡,此時有兩種做法,一種是淺層加載的參數在訓練C任務過程中不動,這種方法被稱為“Frozen”;另外一種是底層網絡參數盡管被初始化了,在C任務訓練過程中仍然隨著訓練的進程不斷改變,這種一般叫“Fine-Tuning”,顧名思義,就是更好地把參數進行調整使得更適應當前的C任務。一般圖像或者視頻領域要做預訓練一般都這么做。
這么做有幾個好處,首先,如果手頭任務C的訓練集合數據量較少的話,現階段的好用的CNN比如Resnet/Densenet/Inception等網絡結構層數很深,幾百萬上千萬參數量算起步價,上億參數的也很常見,訓練數據少很難很好地訓練這么復雜的網絡,但是如果其中大量參數通過大的訓練集合比如ImageNet預先訓練好直接拿來初始化大部分網絡結構參數,然后再用C任務手頭比較可憐的數據量上Fine-tuning過程去調整參數讓它們更適合解決C任務,那事情就好辦多了。這樣原先訓練不了的任務就能解決了,即使手頭任務訓練數據也不少,加個預訓練過程也能極大加快任務訓練的收斂速度,所以這種預訓練方式是老少皆宜的解決方案,另外療效又好,所以在做圖像處理領域很快就流行開來。
那么新的問題來了,為什么這種預訓練的思路是可行的?
目前我們已經知道,對于層級的CNN結構來說,不同層級的神經元學習到了不同類型的圖像特征,由底向上特征形成層級結構,如上圖所示,如果我們手頭是個人臉識別任務,訓練好網絡后,把每層神經元學習到的特征可視化肉眼看一看每層學到了啥特征,你會看到最底層的神經元學到的是線段等特征,圖示的第二個隱層學到的是人臉五官的輪廓,第三層學到的是人臉的輪廓,通過三步形成了特征的層級結構,越是底層的特征越是所有不論什么領域的圖像都會具備的比如邊角線弧線等底層基礎特征,越往上抽取出的特征越與手頭任務相關。正因為此,所以預訓練好的網絡參數,尤其是底層的網絡參數抽取出特征跟具體任務越無關,越具備任務的通用性,所以這是為何一般用底層預訓練好的參數初始化新任務網絡參數的原因。而高層特征跟任務關聯較大,實際可以不用使用,或者采用Fine-tuning用新數據集合清洗掉高層無關的特征抽取器。
一般我們喜歡用ImageNet來做網絡的預訓練,主要有兩點,一方面ImageNet是圖像領域里有超多事先標注好訓練數據的數據集合,分量足是個很大的優勢,量越大訓練出的參數越靠譜;另外一方面因為ImageNet有1000類,類別多,算是通用的圖像數據,跟領域沒太大關系,所以通用性好,預訓練完后哪哪都能用,是個萬金油。分量足的萬金油當然老少通吃,人人喜愛。
聽完上述話,如果你是具備研究素質的人,也就是說具備好奇心,你一定會問下面這個問題:”既然圖像領域預訓練這么好用,那干嘛自然語言處理不做這個事情呢?是不是搞NLP的人比搞CV的傻?。烤退隳闵?,你看見人家這么做,有樣學樣不就行了嗎?這不就是創新嗎,也許能成,萬一成了,你看,你的成功來得就是這么突然!”
嗯,好問題,其實搞NLP的人一點都不比你傻,早就有人嘗試過了,不過總體而言不太成功而已。聽說過word embedding嗎?2003年出品,陳年技術,馥郁芳香。word embedding其實就是NLP里的早期預訓練技術。當然也不能說word embedding不成功,一般加到下游任務里,都能有1到2個點的性能提升,只是沒有那么耀眼的成功而已。
沒聽過?那下面就把這段陳年老賬講給你聽聽。
Word Embedding考古史
這塊大致講講Word Embedding的故事,很粗略,因為網上關于這個技術講的文章太多了,汗牛沖動,我不屬牛,此刻更沒有流汗,所以其實絲毫沒有想講Word Embedding的沖動和激情,但是要說預訓練又得從這開始,那就粗略地講講,主要是引出后面更精彩的部分。在說Word Embedding之前,先更粗略地說下語言模型,因為一般NLP里面做預訓練一般的選擇是用語言模型任務來做。
什么是語言模型?其實看上面這張PPT上扣下來的圖就明白了,為了能夠量化地衡量哪個句子更像一句人話,可以設計如上圖所示函數,核心函數P的思想是根據句子里面前面的一系列前導單詞預測后面跟哪個單詞的概率大?。ɡ碚撋铣松衔闹?,也可以引入單詞的下文聯合起來預測單詞出現概率)。句子里面每個單詞都有個根據上文預測自己的過程,把所有這些單詞的產生概率乘起來,數值越大代表這越像一句人話。語言模型壓下暫且不表,我隱約預感到我這么講你可能還是不太會明白,但是大概這個意思,不懂的可以去網上找,資料多得一樣地汗牛沖動。
假設現在讓你設計一個神經網絡結構,去做這個語言模型的任務,就是說給你很多語料做這個事情,訓練好一個神經網絡,訓練好之后,以后輸入一句話的前面幾個單詞,要求這個網絡輸出后面緊跟的單詞應該是哪個,你會怎么做?
你可以像上圖這么設計這個網絡結構,這其實就是大名鼎鼎的中文人稱“神經網絡語言模型”,英文小名NNLM的網絡結構,用來做語言模型。這個工作有年頭了,是個陳年老工作,是Bengio 在2003年發表在JMLR上的論文。它生于2003,火于2013,以后是否會不朽暫且不知,但是不幸的是出生后應該沒有引起太大反響,沉寂十年終于時來運轉沉冤得雪,在2013年又被NLP考古工作者從海底濕淋淋地撈出來了祭入神殿。為什么會發生這種技術奇遇記?你要想想2013年是什么年頭,是深度學習開始滲透NLP領域的光輝時刻,萬里長征第一步,而NNLM可以算是南昌起義第一槍。在深度學習火起來之前,極少有人用神經網絡做NLP問題,如果你10年前堅持用神經網絡做NLP,估計別人會認為你這人神經有問題。所謂紅塵滾滾,誰也擋不住歷史發展趨勢的車輪,這就是個很好的例子。
上面是閑話,閑言碎語不要講,我們回來講一講NNLM的思路。先說訓練過程,現在看其實很簡單,見過RNN、LSTM、CNN后的你們回頭再看這個網絡甚至顯得有些簡陋。學習任務是輸入某個句中單詞 Wt = "Bert" 前面句子的t-1個單詞,要求網絡正確預測單詞Bert,即最大化:
前面任意單詞 Wi 用Onehot編碼(比如:0001000)作為原始單詞輸入,之后乘以矩陣Q后獲得向量 C(Wi),每個單詞的C(Wi)拼接,上接隱層,然后接softmax去預測后面應該后續接哪個單詞。這個 C(Wi)是什么?這其實就是單詞對應的Word Embedding值,那個矩陣Q包含V行,V代表詞典大小,每一行內容代表對應單詞的Word embedding值。只不過Q的內容也是網絡參數,需要學習獲得,訓練剛開始用隨機值初始化矩陣Q,當這個網絡訓練好之后,矩陣Q的內容被正確賦值,每一行代表一個單詞對應的Word embedding值。所以你看,通過這個網絡學習語言模型任務,這個網絡不僅自己能夠根據上文預測后接單詞是什么,同時獲得一個副產品,就是那個矩陣Q,這就是單詞的Word Embedding是被如何學會的。
2013年最火的用語言模型做Word Embedding的工具是Word2Vec,后來又出了Glove,Word2Vec是怎么工作的呢?看下圖。
Word2Vec的網絡結構其實和NNLM是基本類似的,只是這個圖長得清晰度差了點,看上去不像,其實它們是親兄弟。不過這里需要指出:盡管網絡結構相近,而且也是做語言模型任務,但是其訓練方法不太一樣。Word2Vec有兩種訓練方法,一種叫CBOW,核心思想是從一個句子里面把一個詞摳掉,用這個詞的上文和下文去預測被摳掉的這個詞;第二種叫做Skip-gram,和CBOW正好反過來,輸入某個單詞,要求網絡預測它的上下文單詞。而你回頭看看,NNLM是怎么訓練的?是輸入一個單詞的上文,去預測這個單詞。這是有顯著差異的。為什么Word2Vec這么處理?原因很簡單,因為Word2Vec和NNLM不一樣,NNLM的主要任務是要學習一個解決語言模型任務的網絡結構,語言模型就是要看到上文預測下文,而word embedding只是無心插柳的一個副產品。但是Word2Vec目標不一樣,它單純就是要word embedding的,這是主產品,所以它完全可以隨性地這么去訓練網絡。
為什么要講Word2Vec呢?這里主要是要引出CBOW的訓練方法,BERT其實跟它有關系,后面會講它們之間是如何的關系,當然它們的關系BERT作者沒說,是我猜的,至于我猜的對不對,后面你看后自己判斷。
使用Word2Vec或者Glove,通過做語言模型任務,就可以獲得每個單詞的Word Embedding,那么這種方法的效果如何呢?上圖給了網上找的幾個例子,可以看出有些例子效果還是很不錯的,一個單詞表達成Word Embedding后,很容易找出語義相近的其它詞匯。
我們的主題是預訓練,那么問題是Word Embedding這種做法能算是預訓練嗎?這其實就是標準的預訓練過程。要理解這一點要看看學會Word Embedding后下游任務是怎么用它的。
假設如上圖所示,我們有個NLP的下游任務,比如QA,就是問答問題,所謂問答問題,指的是給定一個問題X,給定另外一個句子Y,要判斷句子Y是否是問題X的正確答案。問答問題假設設計的網絡結構如上圖所示,這里不展開講了,懂得自然懂,不懂的也沒關系,因為這點對于本文主旨來說不關鍵,關鍵是網絡如何使用訓練好的Word Embedding的。它的使用方法其實和前面講的NNLM是一樣的,句子中每個單詞以Onehot形式作為輸入,然后乘以學好的Word Embedding矩陣Q,就直接取出單詞對應的Word Embedding了。這乍看上去好像是個查表操作,不像是預訓練的做法是吧?其實不然,那個Word Embedding矩陣Q其實就是網絡Onehot層到embedding層映射的網絡參數矩陣。所以你看到了,使用Word Embedding等價于什么?等價于把Onehot層到embedding層的網絡用預訓練好的參數矩陣Q初始化了。這跟前面講的圖像領域的低層預訓練過程其實是一樣的,區別無非Word Embedding只能初始化第一層網絡參數,再高層的參數就無能為力了。下游NLP任務在使用Word Embedding的時候也類似圖像有兩種做法,一種是Frozen,就是Word Embedding那層網絡參數固定不動;另外一種是Fine-Tuning,就是Word Embedding這層參數使用新的訓練集合訓練也需要跟著訓練過程更新掉。
上面這種做法就是18年之前NLP領域里面采用預訓練的典型做法,之前說過,Word Embedding其實對于很多下游NLP任務是有幫助的,只是幫助沒有大到閃瞎忘記戴墨鏡的圍觀群眾的雙眼而已。那么新問題來了,為什么這樣訓練及使用Word Embedding的效果沒有期待中那么好呢?答案很簡單,因為Word Embedding有問題唄。這貌似是個比較弱智的答案,關鍵是Word Embedding存在什么問題?這其實是個好問題。
這片在Word Embedding頭上籠罩了好幾年的烏云是什么?是多義詞問題。我們知道,多義詞是自然語言中經常出現的現象,也是語言靈活性和高效性的一種體現。多義詞對Word Embedding來說有什么負面影響?如上圖所示,比如多義詞Bank,有兩個常用含義,但是Word Embedding在對bank這個單詞進行編碼的時候,是區分不開這兩個含義的,因為它們盡管上下文環境中出現的單詞不同,但是在用語言模型訓練的時候,不論什么上下文的句子經過word2vec,都是預測相同的單詞bank,而同一個單詞占的是同一行的參數空間,這導致兩種不同的上下文信息都會編碼到相同的word embedding空間里去。所以word embedding無法區分多義詞的不同語義,這就是它的一個比較嚴重的問題。
你可能覺得自己很聰明,說這可以解決啊,確實也有很多研究人員提出很多方法試圖解決這個問題,但是從今天往回看,這些方法看上去都成本太高或者太繁瑣了,有沒有簡單優美的解決方案呢?
ELMO提供了一種簡潔優雅的解決方案。
從Word Embedding到ELMO
ELMO是“Embedding from Language Models”的簡稱,其實這個名字并沒有反應它的本質思想,提出ELMO的論文題目:“Deep contextualized word representation”更能體現其精髓,而精髓在哪里?在deep contextualized這個短語,一個是deep,一個是context,其中context更關鍵。在此之前的Word Embedding本質上是個靜態的方式,所謂靜態指的是訓練好之后每個單詞的表達就固定住了,以后使用的時候,不論新句子上下文單詞是什么,這個單詞的Word Embedding不會跟著上下文場景的變化而改變,所以對于比如Bank這個詞,它事先學好的Word Embedding中混合了幾種語義 ,在應用中來了個新句子,即使從上下文中(比如句子包含money等詞)明顯可以看出它代表的是“銀行”的含義,但是對應的Word Embedding內容也不會變,它還是混合了多種語義。這是為何說它是靜態的,這也是問題所在。ELMO的本質思想是:我事先用語言模型學好一個單詞的Word Embedding,此時多義詞無法區分,不過這沒關系。在我實際使用Word Embedding的時候,單詞已經具備了特定的上下文了,這個時候我可以根據上下文單詞的語義去調整單詞的Word Embedding表示,這樣經過調整后的Word Embedding更能表達在這個上下文中的具體含義,自然也就解決了多義詞的問題了。所以ELMO本身是個根據當前上下文對Word Embedding動態調整的思路。
ELMO采用了典型的兩階段過程,第一個階段是利用語言模型進行預訓練;第二個階段是在做下游任務時,從預訓練網絡中提取對應單詞的網絡各層的Word Embedding作為新特征補充到下游任務中。上圖展示的是其預訓練過程,它的網絡結構采用了雙層雙向LSTM,目前語言模型訓練的任務目標是根據單詞 Wi 的上下文去正確預測單詞 Wi ,Wi 之前的單詞序列Context-before稱為上文,之后的單詞序列Context-after稱為下文。圖中左端的前向雙層LSTM代表正方向編碼器,輸入的是從左到右順序的除了預測單詞外 Wi 的上文Context-before和下文Context-after;右端的逆向雙層LSTM代表反方向編碼器,輸入的是從右到左的逆序的句子上文和下文;每個編碼器的深度都是兩層LSTM疊加,而每一層的正向和逆向單詞編碼會拼接到一起。這個網絡結構其實在NLP中是很常用的。使用這個網絡結構利用大量語料做語言模型任務就能預先訓練好這個網絡,如果訓練好這個網絡后,輸入一個新句子 Snew ,句子中每個單詞都能得到對應的三個Embedding:最底層是單詞的Word Embedding,往上走是第一層雙向LSTM中對應單詞位置的Embedding,這層編碼單詞的句法信息更多一些;再往上走是第二層LSTM中對應單詞位置的Embedding,這層編碼單詞的語義信息更多一些。也就是說,ELMO的預訓練過程不僅僅學會單詞的Word Embedding,還學會了一個雙層雙向的LSTM網絡結構,而這兩者后面都有用。
上面介紹的是ELMO的第一階段:預訓練階段。那么預訓練好網絡結構后,如何給下游任務使用呢?上圖展示了下游任務的使用過程,比如我們的下游任務仍然是QA問題,此時對于問句X,我們可以先將句子X作為預訓練好的ELMO網絡的輸入,這樣句子X中每個單詞在ELMO網絡中都能獲得對應的三個Embedding,之后給予這三個Embedding中的每一個Embedding一個權重a,這個權重可以學習得來,根據各自權重累加求和,將三個Embedding整合成一個。然后將整合后的這個Embedding作為X句在自己任務的那個網絡結構中對應單詞的輸入,以此作為補充的新特征給下游任務使用。對于上圖所示下游任務QA中的回答句子Y來說也是如此處理。因為ELMO給下游提供的是每個單詞的特征形式,所以這一類預訓練的方法被稱為“Feature-based Pre-Training”。至于為何這么做能夠達到區分多義詞的效果,你可以想一想,其實比較容易想明白原因。
上面這個圖是TagLM采用類似ELMO的思路做命名實體識別任務的過程,其步驟基本如上述ELMO的思路,所以此處不展開說了。TagLM的論文發表在2017年的ACL會議上,作者就是AllenAI里做ELMO的那些人,所以可以將TagLM看做ELMO的一個前導工作。前幾天這個PPT發出去后有人質疑說FastAI的在18年4月提出的ULMFiT才是拋棄傳統Word Embedding引入新模式的開山之作,我深不以為然。首先TagLM出現的更早而且模式基本就是ELMO的思路;另外ULMFiT使用的是三階段模式,在通用語言模型訓練之后,加入了一個領域語言模型預訓練過程,而且論文重點工作在這塊,方法還相對比較繁雜,這并不是一個特別好的主意,因為領域語言模型的限制是它的規模往往不可能特別大,精力放在這里不太合適,放在通用語言模型上感覺更合理;再者,盡管ULFMiT實驗做了6個任務,但是都集中在分類問題相對比較窄,不如ELMO驗證的問題領域廣,我覺得這就是因為第二步那個領域語言模型帶來的限制。所以綜合看,盡管ULFMiT也是個不錯的工作,但是重要性跟ELMO比還是差一檔,當然這是我個人看法。
前面我們提到靜態Word Embedding無法解決多義詞的問題,那么ELMO引入上下文動態調整單詞的embedding后多義詞問題解決了嗎?解決了,而且比我們期待的解決得還要好。上圖給了個例子,對于Glove訓練出的Word Embedding來說,多義詞比如play,根據它的embedding找出的最接近的其它單詞大多數集中在體育領域,這很明顯是因為訓練數據中包含play的句子中體育領域的數量明顯占優導致;而使用ELMO,根據上下文動態調整后的embedding不僅能夠找出對應的“演出”的相同語義的句子,而且還可以保證找出的句子中的play對應的詞性也是相同的,這是超出期待之處。之所以會這樣,是因為我們上面提到過,第一層LSTM編碼了很多句法信息,這在這里起到了重要作用。
ELMO經過這般操作,效果如何呢?實驗效果見上圖,6個NLP任務中性能都有幅度不同的提升,最高的提升達到25%左右,而且這6個任務的覆蓋范圍比較廣,包含句子語義關系判斷,分類任務,閱讀理解等多個領域,這說明其適用范圍是非常廣的,普適性強,這是一個非常好的優點。
那么站在現在這個時間節點看,ELMO有什么值得改進的缺點呢?首先,一個非常明顯的缺點在特征抽取器選擇方面,ELMO使用了LSTM而不是新貴Transformer,Transformer是谷歌在17年做機器翻譯任務的“Attention is all you need”的論文中提出的,引起了相當大的反響,很多研究已經證明了Transformer提取特征的能力是要遠強于LSTM的。如果ELMO采取Transformer作為特征提取器,那么估計Bert的反響遠不如現在的這種火爆場面。另外一點,ELMO采取雙向拼接這種融合特征的能力可能比Bert一體化的融合特征方式弱,但是,這只是一種從道理推斷產生的懷疑,目前并沒有具體實驗說明這一點。
我們如果把ELMO這種預訓練方法和圖像領域的預訓練方法對比,發現兩者模式看上去還是有很大差異的。除了以ELMO為代表的這種基于特征融合的預訓練方法外,NLP里還有一種典型做法,這種做法和圖像領域的方式就是看上去一致的了,一般將這種方法稱為“基于Fine-tuning的模式”,而GPT就是這一模式的典型開創者。
從Word Embedding到GPT
GPT是“Generative Pre-Training”的簡稱,從名字看其含義是指的通用的預訓練,核心在通用上。GPT也采用兩階段過程,第一個階段是利用語言模型進行預訓練,第二階段通過Fine-tuning的模式解決下游任務。上圖展示了GPT的預訓練過程,其實和ELMO是類似的,主要不同在于兩點:首先,特征抽取器不是用的RNN,而是用的Transformer,上面提到過它的特征抽取能力要強于RNN,這個選擇很明顯是很明智的;其次,GPT的預訓練雖然仍然是以語言模型作為目標任務,但是采用的是單向的語言模型,所謂“單向”的含義是指:語言模型訓練的任務目標是根據 Wi 單詞的上下文去正確預測單詞 Wi ,Wi 之前的單詞序列Context-before稱為上文,之后的單詞序列Context-after稱為下文。ELMO在做語言模型預訓練的時候,預測單詞 Wi 同時使用了上文和下文,而GPT則只采用Context-before這個單詞的上文來進行預測,而拋開了下文。這個選擇現在看不是個太好的選擇,原因很簡單,它沒有把單詞的下文融合進來,這限制了其在更多應用場景的效果,比如閱讀理解這種任務,在做任務的時候是可以允許同時看到上文和下文一起做決策的。如果預訓練時候不把單詞的下文嵌入到Word Embedding中,是很吃虧的,白白丟掉了很多信息。
這里強行插入一段簡單提下Transformer,盡管上面提到了,但是說的還不完整,補充兩句。首先,Transformer是個疊加的“自注意力機制(Self Attention)”構成的深度網絡,是目前NLP里最強的特征提取器,注意力這個機制在此被發揚光大,從任務的配角不斷搶戲,直到Transformer一躍成為踢開RNN和CNN傳統特征提取器,榮升頭牌,大紅大紫。你問了:什么是注意力機制?這里再插個廣告,對注意力不了解的可以參考鄙人16年出品17年修正的下文:“深度學習中的注意力模型”,補充下相關基礎知識,如果不了解注意力機制你肯定會落后時代的發展。而介紹Transformer比較好的文章可以參考“The Annotated Transformer. ”這里不展開介紹。
其次,我的判斷是Transformer在未來會逐漸替代掉RNN成為主流的NLP工具,RNN一直受困于其并行計算能力,這是因為它本身結構的序列性依賴導致的,盡管很多人在試圖通過修正RNN結構來修正這一點,但是我不看好這種模式,因為給馬車換輪胎不如把它升級到汽車,這個道理很好懂,更何況目前汽車的雛形已經出現了,干嘛還要執著在換輪胎這個事情呢?是吧?再說CNN,CNN在NLP里一直沒有形成主流,CNN的最大優點是易于做并行計算,所以速度快,但是在捕獲NLP的序列關系尤其是長距離特征方面天然有缺陷,不是做不到而是做不好,目前也有很多改進模型,但是特別成功的不多。綜合各方面情況,很明顯Transformer同時具備并行性好,又適合捕獲長距離特征,沒有理由不在賽跑比賽中跑不過RNN和CNN。
好了,題外話結束,我們再回到主題,接著說GPT。上面講的是GPT如何進行第一階段的預訓練,那么假設預訓練好了網絡模型,后面下游任務怎么用?它有自己的個性,和ELMO的方式大有不同。
上圖展示了GPT在第二階段如何使用。首先,對于不同的下游任務來說,本來你可以任意設計自己的網絡結構,現在不行了,你要向GPT的網絡結構看齊,把任務的網絡結構改造成和GPT的網絡結構是一樣的。然后,在做下游任務的時候,利用第一步預訓練好的參數初始化GPT的網絡結構,這樣通過預訓練學到的語言學知識就被引入到你手頭的任務里來了,這是個非常好的事情。再次,你可以用手頭的任務去訓練這個網絡,對網絡參數進行Fine-tuning,使得這個網絡更適合解決手頭的問題。就是這樣??吹搅嗣??這有沒有讓你想起最開始提到的圖像領域如何做預訓練的過程(請參考上圖那句非常容易暴露年齡的歌詞)?對,這跟那個模式是一模一樣的。
這里引入了一個新問題:對于NLP各種花樣的不同任務,怎么改造才能靠近GPT的網絡結構呢?
GPT論文給了一個改造施工圖如上,其實也很簡單:對于分類問題,不用怎么動,加上一個起始和終結符號即可;對于句子關系判斷問題,比如Entailment,兩個句子中間再加個分隔符即可;對文本相似性判斷問題,把兩個句子順序顛倒下做出兩個輸入即可,這是為了告訴模型句子順序不重要;對于多項選擇問題,則多路輸入,每一路把文章和答案選項拼接作為輸入即可。從上圖可看出,這種改造還是很方便的,不同任務只需要在輸入部分施工即可。
GPT的效果是非常令人驚艷的,在12個任務里,9個達到了最好的效果,有些任務性能提升非常明顯。
那么站在現在的時間節點看,GPT有什么值得改進的地方呢?其實最主要的就是那個單向語言模型,如果改造成雙向的語言模型任務估計也沒有Bert太多事了。當然,即使如此GPT也是非常非常好的一個工作,跟Bert比,其作者炒作能力亟待提升。
Bert的誕生
我們經過跋山涉水,終于到了目的地Bert模型了。
Bert采用和GPT完全相同的兩階段模型,首先是語言模型預訓練;其次是使用Fine-Tuning模式解決下游任務。和GPT的最主要不同在于在預訓練階段采用了類似ELMO的雙向語言模型,當然另外一點是語言模型的數據規模要比GPT大。所以這里Bert的預訓練過程不必多講了。
第二階段,Fine-Tuning階段,這個階段的做法和GPT是一樣的。當然,它也面臨著下游任務網絡結構改造的問題,在改造任務方面Bert和GPT有些不同,下面簡單介紹一下。
在介紹Bert如何改造下游任務之前,先大致說下NLP的幾類問題,說這個是為了強調Bert的普適性有多強。通常而言,絕大部分NLP問題可以歸入上圖所示的四類任務中:一類是序列標注,這是最典型的NLP任務,比如中文分詞,詞性標注,命名實體識別,語義角色標注等都可以歸入這一類問題,它的特點是句子中每個單詞要求模型根據上下文都要給出一個分類類別。第二類是分類任務,比如我們常見的文本分類,情感計算等都可以歸入這一類。它的特點是不管文章有多長,總體給出一個分類類別即可。第三類任務是句子關系判斷,比如Entailment,QA,語義改寫,自然語言推理等任務都是這個模式,它的特點是給定兩個句子,模型判斷出兩個句子是否具備某種語義關系;第四類是生成式任務,比如機器翻譯,文本摘要,寫詩造句,看圖說話等都屬于這一類。它的特點是輸入文本內容后,需要自主生成另外一段文字。
對于種類如此繁多而且各具特點的下游NLP任務,Bert如何改造輸入輸出部分使得大部分NLP任務都可以使用Bert預訓練好的模型參數呢?上圖給出示例,對于句子關系類任務,很簡單,和GPT類似,加上一個起始和終結符號,句子之間加個分隔符即可。對于輸出來說,把第一個起始符號對應的Transformer最后一層位置上面串接一個softmax分類層即可。對于分類問題,與GPT一樣,只需要增加起始和終結符號,輸出部分和句子關系判斷任務類似改造;對于序列標注問題,輸入部分和單句分類是一樣的,只需要輸出部分Transformer最后一層每個單詞對應位置都進行分類即可。從這里可以看出,上面列出的NLP四大任務里面,除了生成類任務外,Bert其它都覆蓋到了,而且改造起來很簡單直觀。盡管Bert論文沒有提,但是稍微動動腦子就可以想到,其實對于機器翻譯或者文本摘要,聊天機器人這種生成式任務,同樣可以稍作改造即可引入Bert的預訓練成果。只需要附著在S2S結構上,encoder部分是個深度Transformer結構,decoder部分也是個深度Transformer結構。根據任務選擇不同的預訓練數據初始化encoder和decoder即可。這是相當直觀的一種改造方法。當然,也可以更簡單一點,比如直接在單個Transformer結構上加裝隱層產生輸出也是可以的。不論如何,從這里可以看出,NLP四大類任務都可以比較方便地改造成Bert能夠接受的方式。這其實是Bert的非常大的優點,這意味著它幾乎可以做任何NLP的下游任務,具備普適性,這是很強的。
Bert采用這種兩階段方式解決各種NLP任務效果如何?在11個各種類型的NLP任務中達到目前最好的效果,某些任務性能有極大的提升。一個新模型好不好,效果才是王道。
到這里我們可以再梳理下幾個模型之間的演進關系。從上圖可見,Bert其實和ELMO及GPT存在千絲萬縷的關系,比如如果我們把GPT預訓練階段換成雙向語言模型,那么就得到了Bert;而如果我們把ELMO的特征抽取器換成Transformer,那么我們也會得到Bert。所以你可以看出:Bert最關鍵兩點,一點是特征抽取器采用Transformer;第二點是預訓練的時候采用雙向語言模型。
那么新問題來了:對于Transformer來說,怎么才能在這個結構上做雙向語言模型任務呢?乍一看上去好像不太好搞。我覺得吧,其實有一種很直觀的思路,怎么辦?看看ELMO的網絡結構圖,只需要把兩個LSTM替換成兩個Transformer,一個負責正向,一個負責反向特征提取,其實應該就可以。當然這是我自己的改造,Bert沒這么做。那么Bert是怎么做的呢?我們前面不是提過Word2Vec嗎?我前面肯定不是漫無目的地提到它,提它是為了在這里引出那個CBOW訓練方法,所謂寫作時候埋伏筆的“草蛇灰線,伏脈千里”,大概就是這個意思吧?前面提到了CBOW方法,它的核心思想是:在做語言模型任務的時候,我把要預測的單詞摳掉,然后根據它的上文Context-Before和下文Context-after去預測單詞。其實Bert怎么做的?Bert就是這么做的。從這里可以看到方法間的繼承關系。當然Bert作者沒提Word2Vec及CBOW方法,這是我的判斷,Bert作者說是受到完形填空任務的啟發,這也很可能,但是我覺得他們要是沒想到過CBOW估計是不太可能的。
從這里可以看出,在文章開始我說過Bert在模型方面其實沒有太大創新,更像一個最近幾年NLP重要技術的集大成者,原因在于此,當然我不確定你怎么看,是否認同這種看法,而且我也不關心你怎么看。其實Bert本身的效果好和普適性強才是最大的亮點。
那么Bert本身在模型和方法角度有什么創新呢?就是論文中指出的Masked 語言模型和Next Sentence Prediction。而Masked語言模型上面講了,本質思想其實是CBOW,但是細節方面有改進。
Masked雙向語言模型向上圖展示這么做:隨機選擇語料中15%的單詞,把它摳掉,也就是用[Mask]掩碼代替原始單詞,然后要求模型去正確預測被摳掉的單詞。但是這里有個問題:訓練過程大量看到[mask]標記,但是真正后面用的時候是不會有這個標記的,這會引導模型認為輸出是針對[mask]這個標記的,但是實際使用又見不到這個標記,這自然會有問題。為了避免這個問題,Bert改造了一下,15%的被上天選中要執行[mask]替身這項光榮任務的單詞中,只有80%真正被替換成[mask]標記,10%被貍貓換太子隨機替換成另外一個單詞,10%情況這個單詞還待在原地不做改動。這就是Masked雙向語音模型的具體做法。
至于說“Next Sentence Prediction”,指的是做語言模型預訓練的時候,分兩種情況選擇兩個句子,一種是選擇語料中真正順序相連的兩個句子;另外一種是第二個句子從語料庫中拋色子,隨機選擇一個拼到第一個句子后面。我們要求模型除了做上述的Masked語言模型任務外,附帶再做個句子關系預測,判斷第二個句子是不是真的是第一個句子的后續句子。之所以這么做,是考慮到很多NLP任務是句子關系判斷任務,單詞預測粒度的訓練到不了句子關系這個層級,增加這個任務有助于下游句子關系判斷任務。所以可以看到,它的預訓練是個多任務過程。這也是Bert的一個創新。
上面這個圖給出了一個中文訓練實例,從中可以體會下上面講的masked語言模型和下句預測任務。訓練數據就長這種樣子。
順帶講解下Bert的輸入部分,也算是有些特色。它的輸入部分是個線性序列,兩個句子通過分隔符分割,最前面和最后增加兩個標識符號。每個單詞有三個embedding:位置信息embedding,這是因為NLP中單詞順序是很重要的特征,需要在這里對位置信息進行編碼;單詞embedding,這個就是我們之前一直提到的單詞embedding;第三個是句子embedding,因為前面提到訓練數據都是由兩個句子構成的,那么每個句子有個句子整體的embedding項對應給每個單詞。把單詞對應的三個embedding疊加,就形成了Bert的輸入。
至于Bert在預訓練的輸出部分如何組織,可以參考上圖的注釋。
我們說過Bert效果特別好,那么到底是什么因素起作用呢?如上圖所示,對比試驗可以證明,跟GPT相比,雙向語言模型起到了最主要的作用,對于那些需要看到下文的任務來說尤其如此。而預測下個句子來說對整體性能來說影響不算太大,跟具體任務關聯度比較高。
最后,我講講我對Bert的評價和看法,我覺得Bert是NLP里里程碑式的工作,對于后面NLP的研究和工業應用會產生長久的影響,這點毫無疑問。但是從上文介紹也可以看出,從模型或者方法角度看,Bert借鑒了ELMO,GPT及CBOW,主要提出了Masked 語言模型及Next Sentence Prediction,但是這里Next Sentence Prediction基本不影響大局,而Masked LM明顯借鑒了CBOW的思想。所以說Bert的模型沒什么大的創新,更像最近幾年NLP重要進展的集大成者,這點如果你看懂了上文估計也沒有太大異議,如果你有大的異議,杠精這個大帽子我隨時準備戴給你。如果歸納一下這些進展就是:首先是兩階段模型,第一階段雙向語言模型預訓練,這里注意要用雙向而不是單向,第二階段采用具體任務Fine-tuning或者做特征集成;第二是特征抽取要用Transformer作為特征提取器而不是RNN或者CNN;第三,雙向語言模型可以采取CBOW的方法去做(當然我覺得這個是個細節問題,不算太關鍵,前兩個因素比較關鍵)。Bert最大的亮點在于效果好及普適性強,幾乎所有NLP任務都可以套用Bert這種兩階段解決思路,而且效果應該會有明顯提升。可以預見的是,未來一段時間在NLP應用領域,Transformer將占據主導地位,而且這種兩階段預訓練方法也會主導各種應用。
另外,我們應該弄清楚預訓練這個過程本質上是在做什么事情,本質上預訓練是通過設計好一個網絡結構來做語言模型任務,然后把大量甚至是無窮盡的無標注的自然語言文本利用起來,預訓練任務把大量語言學知識抽取出來編碼到網絡結構中,當手頭任務帶有標注信息的數據有限時,這些先驗的語言學特征當然會對手頭任務有極大的特征補充作用,因為當數據有限的時候,很多語言學現象是覆蓋不到的,泛化能力就弱,集成盡量通用的語言學知識自然會加強模型的泛化能力。如何引入先驗的語言學知識其實一直是NLP尤其是深度學習場景下的NLP的主要目標之一,不過一直沒有太好的解決辦法,而ELMO/GPT/Bert的這種兩階段模式看起來無疑是解決這個問題自然又簡潔的方法,這也是這些方法的主要價值所在。
對于當前NLP的發展方向,我個人覺得有兩點非常重要,一個是需要更強的特征抽取器,目前看Transformer會逐漸擔當大任,但是肯定還是不夠強的,需要發展更強的特征抽取器;第二個就是如何優雅地引入大量無監督數據中包含的語言學知識,目前看預訓練這種兩階段方法還是很有效的,當然后面肯定還會有更好的模型出現。
完了,這就是自然語言模型預訓練的發展史。
責任編輯:lq
-
深度學習
+關注
關注
73文章
5503瀏覽量
121162 -
自然語言處理
+關注
關注
1文章
618瀏覽量
13561
原文標題:從Word Embedding到Bert模型—自然語言處理中的預訓練技術發展史
文章出處:【微信號:zenRRan,微信公眾號:深度學習自然語言處理】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論