絕對乾貨!NLP 預訓練模型:從 Transformer 到 Albert

▌背景:

語言模型是機器理解人類語言的途徑,17年的transformer是語言模型擺脫rnn,lstm建模的一次嘗試,後續的bert則是大力出奇跡的代表,用更大的模型和更多的資料將nlp任務的benchmark提高了一大截。gpt在auto-regressive的路上一路走到黑,而xlnet將gpt和bert的優點結合在了一起,然後用更更大的資料吊打了bert。沒過多久,bert的增強版roberta用更更更大的資料打敗了xlnet。然而當bert的模型達到一定程度後,受到了硬體資源的限制,於是谷歌透過矩陣分解和引數共享壓縮了bert的模型大小,因此當albert使用了和bert同樣的引數量的時候,推理能力又上了一個臺階。正好最近這幾個月也在研究語言模型,就把我對transformer等幾個具有代表性的nlp模型的理解記錄一下。

▌1. transformer

1.1 transformer的背景

17年之前,語言模型都是透過rnn,lstm來建模,這樣雖然可以學習上下文之間的關係,但是無法並行化,給模型的訓練和推理帶來了困難,因此論文提出了一種完全基於attention來對語言建模的模型,叫做transformer。transformer擺脫了nlp任務對於rnn,lstm的依賴,使用了self-attention的方式對上下文進行建模,提高了訓練和推理的速度,transformer也是後續更強大的nlp預訓練模型的基礎,因此有必要花很大的篇幅詳解一下這個模型。

1.2 transformer的流程

絕對乾貨!NLP 預訓練模型:從 Transformer 到 Albert

transformer的流程圖

<1> Inputs是經過padding的輸入資料,大小是[batch size, max seq length]。

<2> 初始化embedding matrix,透過embedding lookup將Inputs對映成token embedding,大小是[batch size, max seq length, embedding size],然後乘以embedding size的開方。

<3> 透過sin和cos函式建立positional encoding,表示一個token的絕對位置資訊,並加入到token embedding中,然後dropout。

<4> multi-head attention

<4。1> 輸入token embedding,透過Dense生成Q,K,V,大小是[batch size, max seq length, embedding size],然後按第2維split成num heads份並按第0維concat,生成新的Q,K,V,大小是[num heads*batch size, max seq length, embedding size/num heads],完成multi-head的操作。

<4。2> 將K的第1維和第2維進行轉置,然後Q和轉置後的K的進行點積,結果的大小是[num heads*batch size, max seq length, max seq length]。

<4。3> 將<4。2>的結果除以hidden size的開方(在transformer中,hidden size=embedding size),完成scale的操作。

<4。4> 將<4。3>中padding的點積結果置成一個很小的數(-2^32+1),完成mask操作,後續softmax對padding的結果就可以忽略不計了。

<4。5> 將經過mask的結果進行softmax操作。

<4。6> 將softmax的結果和V進行點積,得到attention的結果,大小是[num heads*batch size, max seq length, hidden size/num heads]。

<4。7> 將attention的結果按第0維split成num heads份並按第2維concat,生成multi-head attention的結果,大小是[batch size, max seq length, hidden size]。Figure 2上concat之後還有一個linear的操作,但是程式碼裡並沒有。

<5> 將token embedding和multi-head attention的結果相加,並進行Layer Normalization。

<6> 將<5>的結果經過2層Dense,其中第1層的activation=relu,第2層activation=None。

<7> 功能和<5>一樣。

<8> Outputs是經過padding的輸出資料,與Inputs不同的是,Outputs的需要在序列前面加上一個起始符號””,用來表示序列生成的開始,而Inputs不需要。

<9> 功能和<2>一樣。

<10> 功能和<3>一樣。

<11> 功能和<4>類似,唯一不同的一點在於mask,<11>中的mask不僅將padding的點積結果置成一個很小的數,而且將當前token與之後的token的點積結果也置成一個很小的數。

<12> 功能和<5>一樣。

<13> 功能和<4>類似,唯一不同的一點在於Q,K,V的輸入,<13>的Q的輸入來自於Outputs 的token embedding,<13>的K,V來自於<7>的結果。

<14> 功能和<5>一樣。

<15> 功能和<6>一樣。

<16> 功能和<7>一樣,結果的大小是[batch size, max seq length, hidden size]。

<17> 將<16>的結果的後2維和embedding matrix的轉置進行點積,生成的結果的大小是[batch size, max seq length, vocab size]。

<18> 將<17>的結果進行softmax操作,生成的結果就表示當前時刻預測的下一個token在vocab上的機率分佈。

<19> 計算<18>得到的下一個token在vocab上的機率分佈和真實的下一個token的one-hot形式的cross entropy,然後sum非padding的token的cross entropy當作loss,利用adam進行訓練。

1.3 transformer的技術細節

transformer中的self-attention是從普通的點積attention中演化出來的,演化過程中可以看

遍地開花的 Attention ,你真的懂嗎?

1.3.1 為什麼<2>要乘以embedding size的開方?

論文並沒有講為什麼這麼做,我看了程式碼,猜測是因為embedding matrix的初始化方式是xavier init,這種方式的方差是1/embedding size,因此乘以embedding size的開方使得embedding matrix的方差是1,在這個scale下可能更有利於embedding matrix的收斂。

1.3.2 為什麼inputs embedding要加入positional encoding?

因為self-attention是位置無關的,無論句子的順序是什麼樣的,透過self-attention計算的token的hidden embedding都是一樣的,這顯然不符合人類的思維。因此要有一個辦法能夠在模型中表達出一個token的位置資訊,transformer使用了固定的positional encoding來表示token在句子中的絕對位置資訊。positional encoding的公式如下:

positional encoding公式

至於positional encoding為什麼能表示位置資訊,可以看如何理解Transformer論文中的positional encoding,和三角函式有什麼關係?

1.3.3 為什麼<4.2>的結果要scale?

以陣列為例,2個長度是len,均值是0,方差是1的陣列點積會生成長度是len,均值是0,方差是len的陣列。而方差變大會導致softmax的輸入推向正無窮或負無窮,這時的梯度會無限趨近於0,不利於訓練的收斂。因此除以len的開方,可以是陣列的方差重新迴歸到1,有利於訓練的收斂。

1.3.4 為什麼<5>要將multi-head attention的輸入和輸出相加?

類似於resnet中的殘差學習單元,有ensemble的思想在裡面,解決網路退化問題。

1.3.5 為什麼attention需要multi-head,一個大head行不行?

multi-head相當於把一個大空間劃分成多個互斥的小空間,然後在小空間內分別計算attention,雖然單個小空間的attention計算結果沒有大空間計算得精確,但是多個小空間並行然後concat有助於網路捕捉到更豐富的資訊,類比cnn網路中的channel。

1.3.6 為什麼multi-head attention後面要加一個ffn?

類比cnn網路中,cnn block和fc交替連線,效果更好。相比於單獨的multi-head attention,在後面加一個ffn,可以提高整個block的非線性變換的能力。

1.3.7 為什麼<11>要mask當前時刻的token與後續token的點積結果?

自然語言生成(例如機器翻譯,文字摘要)是auto-regressive的,在推理的時候只能依據之前的token生成當前時刻的token,正因為生成當前時刻的token的時候並不知道後續的token長什麼樣,所以為了保持訓練和推理的一致性,訓練的時候也不能利用後續的token來生成當前時刻的token。這種方式也符合人類在自然語言生成中的思維方式。

1.4 transformer的總結

transformer剛發表的時候,我剛好在百度nlp部實習,當時覺得transformer噱頭更多一些,在小模型上self-attention並不比rnn,lstm好。直到大力出奇跡的bert出現,深深地打了我的臉,當模型變得越來越大,樣本數越來越多的時候,self-attention無論是並行化帶來的訓練提速,還是在長距離上的建模,都是要比傳統的rnn,lstm好很多。transformer現在已經各種具有代表性的nlp預訓練模型的基礎,bert系列使用了transformer的encoder,gpt系列transformer的decoder。在推薦領域,transformer的multi-head attention也應用得很廣泛。

▌2. bert

2.1 bert的背景

在bert之前,將預訓練的embedding應用到下游任務的方式大致可以分為2種,一種是feature-based,例如ELMo這種將經過預訓練的embedding作為特徵引入到下游任務的網路中;一種是fine-tuning,例如GPT這種將下游任務接到預訓練模型上,然後一起訓練。然而這2種方式都會面臨同一個問題,就是無法直接學習到上下文資訊,像ELMo只是分別學習上文和下文資訊,然後concat起來表示上下文資訊,抑或是GPT只能學習上文資訊。因此,作者提出一種基於transformer encoder的預訓練模型,可以直接學習到上下文資訊,叫做bert。bert使用了12個transformer encoder block,在13G的資料上進行了預訓練,可謂是nlp領域大力出奇跡的代表。

2.2 bert的流程

bert是在transformer encoder的基礎之上進行改進的,因此在整個流程上與transformer encoder沒有大的差別,只是在embedding,multi-head attention,loss上有所差別。

2.2.1 bert和transformer在embedding上的差異

絕對乾貨!NLP 預訓練模型:從 Transformer 到 Albert

bert pre-train and fine-tune

bert和transformer在embedding上的差異主要有3點:

<1> transformer的embedding由2部分構成,一個是token embedding,透過embedding matrix lookup到token_ids上生成表示token的向量;一個是position embedding,是透過sin和cos函式建立的定值向量。而bert的embedding由3部分構成,第一個同樣是token embedding,透過embedding matrix lookup到token_ids上生成表示token的向量;第二個是segment embedding,用來表達當前token是來自於第一個segment,還是第二個segment,因此segment vocab size是2;第三個是position embedding,與transformer不同的是,bert建立了一個position embedding matrix,透過position embedding matrix lookup到token_ids的位置上生成表示token位置的位置向量。

<2> transformer在embedding之後跟了一個dropout,但是bert在embedding之後先跟了一個layer normalization,再跟了一個dropout。

<3> bert在token序列之前加了一個特定的token“[cls]”,這個token對應的向量後續會用在分類任務上;如果是句子對的任務,那麼兩個句子間使用特定的token“[seq]”來分割。

2。2。2 bert和transformer在multi-head attention上的差異

bert和transformer在multi-head attention上的差異主要有2點:

<1> transformer在<4。7>會concat<4。6>的attention的結果。而bert不僅會concat<4。6>的attention的結果,還會把前N-1個encoder block中attention的結果都concat進來。

<2> transformer在<4。7>之後沒有linear的操作(也可能是因為我看的transformer程式碼不是官方transformer的緣故),而bert在transformer的<4。7>之後有一個linear的操作。

2。2。3 bert和transformer在loss上的差異

bert和transformer在loss上的差異主要有2點:

<1> transformer的loss是在decoder階段計算的,loss的計算方式是transformer的<19>。bert預訓練的loss由2部分構成,一部分是NSP的loss,就是token“[cls]”經過1層Dense,然後接一個二分類的loss,其中0表示segment B是segment A的下一句,1表示segment A和segment B來自2篇不同的文字;另一部分是MLM的loss,segment中每個token都有15%的機率被mask,而被mask的token有80%的機率用“”表示,有10%的機率隨機替換成某一個token,有10%的機率保留原來的token,被mask的token經過encoder後乘以embedding matrix的轉置會生成在vocab上的分佈,然後計算分佈和真實的token的one-hot形式的cross entropy,最後sum起來當作loss。這兩部分loss相加起來當作total loss,利用adam進行訓練。bert fine-tune的loss會根據任務性質來設計,例如分類任務中就是token“[cls]”經過1層Dense,然後接了一個二分類的loss;例如問題回答任務中會在paragraph上的token中預測一個起始位置,一個終止位置,然後以起始位置和終止位置的預測分佈和真實分佈為基礎設計loss;例如序列標註,預測每一個token的詞性,然後以每一個token在詞性的預測分佈和真實分佈為基礎設計loss。

<2> bert在encoder之後,在計算NSP和MLM的loss之前,分別對NSP和MLM的輸入加了一個Dense操作,這部分引數只對預訓練有用,對fine-tune沒用。而transformer在decoder之後就直接計算loss了,中間沒有Dense操作。

2.3 bert的技術細節

2.3.1 為什麼bert需要額外的segment embedding?

因為bert預訓練的其中一個任務是判斷segment A和segment B之間的關係,這就需要embedding中能包含當前token屬於哪個segment的資訊,然而無論是token embedding,還是position embedding都無法表示出這種資訊,因此額外建立一個segment embedding matrix用來表示當前token屬於哪個segment的資訊,segment vocab size就是2,其中index=0表示token屬於segment A,index=1表示token屬於segment B。

2.3.2 為什麼transformer的embedding後面接了一個dropout,而bert是先接了一個layer normalization,再接dropout?

LN是為了解決梯度消失的問題,dropout是為了解決過擬合的問題。在embedding後面加LN有利於embedding matrix的收斂。

2.3.3 為什麼在multi-head attention中,bert不僅會concat<4.6>的attention的結果,還會把前N-1個encoder block中attention的結果都concat進來?

有ensemble的思路在裡面,比起單純只用第N個encoder block中的attention結果,將前N個encoder block中的attention結果concat起來顯然能夠get到更多的資訊,而下一步的linear操作又將結果的大小重新變回[batch size, max seq length, hidden size]。該問題和transformer的問題3。4的本質是一樣的,透過ensemble可以得到更多的資訊。

2.3.4 為什麼token被mask的機率是15%?為什麼被mask後,還要分3種情況?

15%的機率是透過實驗得到的最好的機率,xlnet也是在這個機率附近,說明在這個機率下,既能有充分的mask樣本可以學習,又不至於讓segment的資訊損失太多,以至於影響mask樣本上下文資訊的表達。然而因為在下游任務中不會出現token“”,所以預訓練和fine-tune出現了不一致,為了減弱不一致性給模型帶來的影響,被mask的token有80%的機率用“”表示,有10%的機率隨機替換成某一個token,有10%的機率保留原來的token,這3個百分比也是多次實驗得到的最佳組合,在這3個百分比的情況下,下游任務的fine-tune可以達到最佳的實驗結果。

2.4 bert的總結

相比於那些說自己很好,但是在實際場景中然並軟的論文,bert是真正地影響了學術界和工業界。無論是GLUE,還是SQUAD,現在榜單上的高分方法都是在bert的基礎之上進行了改進。在我的工作中,用bert落地的業務效果也比我預想的要好一些。bert在nlp領域的地位可以類比cv領域的inception或者resnet,cv領域的演算法效果在幾年前就已經超過了人類的標註準確率,而nlp領域直到bert的出現才做到這一點。不過bert也並不是萬能的,bert的框架決定了這個模型適合解決自然語言理解的問題,因為沒有解碼的過程,所以bert不適合解決自然語言生成的問題。因此如何將bert改造成適用於解決機器翻譯,文字摘要問題的框架,是今後值得研究的一個點。

▌3. xlnet

3.1 xlnet的背景

目前語言預訓練模型的模式主要有2種,第一種是像gpt這種的auto-regressive模型,每個時刻都依據之前所有時刻的token來預測下一個token,auto-regressive的loss的定義如下:

自迴歸的loss

第二種是像bert這種的auto-encoder模型,隨機mask掉句子中若干個token,然後依據上下文預測被mask掉的token,auto-encoder的loss的定義如下:

自編碼的loss

auto-regressive模型在訓練的過程中只能用到上文的資訊,但是不會出現訓練和推理的gap;auto-encoder模型在訓練的過程中能利用到上下文資訊,但是會出現訓練和推理的gap,訓練過程中的在推理的時候並不會出現。因此,作者就提出一種基於transformer-xl的融合了auto-regressive模型和auto-encoder模型優勢的auto-regressive模型。

3.2 xlnet的流程

3.2.1 因子分解序

一個句子的因子分解序就是這個句子的token的一種隨機排列。為了能融合auto-regressive模型和auto-encoder模型的優勢,xlnet使用因子分解序將上下文資訊引入auto-regressive的loss中。例如句子1->2->3->4->5,在auto-regressive的loss中,預測token 2可以利用token 1的資訊,但是不能利用token 2/3/4/5的資訊;在引入了因子分解序之後,假設使用了1->4->2->3->5的因子分解序,那麼預測token 2可以利用token 1/4的資訊,但是不能利用token 3/5的資訊。在使用因子分解序之後,並不會影響句子的輸入順序,只是在transformer-xl的multi-head attention中計算每一個token的attention結果時會有所改變,原先的方式是mask掉當前token以及句子中的後續token,而現在是mask掉當前token以及因子分解序中的後續token。這種方式可以在計算當前token的attention結果時利用到當前token的上下文資訊,例如上面這個因子分解序,計算token 2的attention結果時就是用到了token 1/4的資訊,在原始句子中,token 1在token 2之前,token 4在token 2之後。

因子分解序的實現方式是在計算multi-head attention的時候進行了proper mask。例如1->4->2->3->5的因子分解序,在輸入token 2時,由於在因子分解序中token 2排在token 1/3的後面,所以在計算token 2的attention結果時將token 2/4/5進行了mask,只計算token 2和token 1/3的點積結果,然後softmax以及加權求和當作attention的結果。

3.2.2 雙流自注意力機制

xlnet使用了transformer-xl的框架,並在transformer的基礎之上使用了雙流自注意力機制。

雙流自注意力機制

相比於普通的transformer,xlnet多加了一個multi-head attention+ffn的計算。雙流自注意力機制分為查詢流g和內容流h 2個流。h就是和transformer一樣的multi-head attention,計算第t個時刻的attention的結果時用到了因子分解序中前t個位置的位置資訊和token資訊,而g在transformer的multi-head attention的基礎之上做了修改,計算第t個時刻的attention的結果時只用到了因子分解序中前t個位置的位置資訊和前t-1個位置的token資訊。在預訓練的過程當中,為了降低最佳化的難度,xlnet只會計算因子分解序最後的1/6或者1/7的token的g,然後把g融合到auto-regressive的loss當中進行訓練,順帶著訓練h。在預訓練結束之後,放棄g,使用h做下游任務的fine-tune,fine-tune的過程就和普通的transfomer的fine-tune一模一樣了。

3.3 xlnet的技術細節

3.3.1 因子分解序的優勢

因子分解序創新地將上下文資訊融入到auto-regressive的loss中,理論上,只要模型的預訓練將一個句子的所有因子分解序都訓練一遍,那麼模型就能準確地get到句子中每一個token和上下文之間的聯絡。然而實際情況下,一個句子的因子分解序的數量是隨著句子長度指數增長的,因此在實際訓練中只是用到了句子的某個因子分解序或者某幾個因子分解序而已。即便如此,相比於只能get到上文資訊的auto-regressive,加了因子分解序之後可以同時get到上下文資訊,能夠提高模型的推理能力。

3.3.2 為什麼自注意力要用雙流?

因為普通的transformer無法融合因子分解序和auto-regressive的loss,例如2個不同的因子分解序1->3->2->4->5和1->3->2->5->4,第1個句子的4和第2個句子的5在auto-regressive的loss下的attention結果是一樣的,因此第1個句子的4和第2個句子的5在vocab上的預測機率分佈也是一樣的,這就不符合常理了。造成這種現象的原因在於,auto-regressive的loss是利用前t-1個token的token資訊和位置資訊預測第t個token,然而因子分解序的第t個token在原始句子中的位置是不確定的,因此需要額外的資訊表示因子分解序中需要預測的token在原始句子中的位置。為了達到目的,xlnet使用雙流的multi-head attention+ffn,查詢流g利用因子分解序中前t個位置的位置資訊和前t-1個位置的token資訊計算第t個位置的輸出資訊,而內容流h利用因子分解序中前t個位置的位置資訊和token資訊計算第t個位置的輸出資訊。在預訓練的過程中,使用g計算auto-regressive的loss,然後最小化的loss的值,順帶著訓練h。預訓練完成之後,放棄g,使用h無縫切換到普通transformer的fine-tune。

3.4 xlnet的總結

由於我也是隻看過論文,並沒有在實際工作中用過xlnet,因此我也只能講講xlnet的理論。在bert之後,有很多論文都對bert進行了改進,但是創新點都很有限,xlnet是在我看過的論文中唯一一篇在transformer的框架之下將上下文資訊和auto-regressive的loss融合在一起的論文。但是xlnet是否真的比bert優秀,這還是一個疑問,xlnet使用了126G的資料進行預訓練,相比於bert的13G資料大了一個數量級,在xlnet釋出之後不久,bert的改進版roberta使用了160G的資料進行預訓練,又打敗了xlnet。

▌4. albert

4.1 albert的背景

增大預訓練模型的大小通常能夠提高預訓練模型的推理能力,但是當預訓練模型增大到一定程度之後,會碰到GPU/TPU memory的限制。因此,作者在bert中加入了2項減少引數的技術,能夠縮小bert的大小,並且修改了bert NSP的loss,在和bert有相同引數量的前提之下,有更強的推理能力。

4.2 albert的流程

4.2.1 詞向量矩陣的分解

在bert以及諸多bert的改進版中,embedding size都是等於hidden size的,這不一定是最優的。因為bert的token embedding是上下文無關的,而經過multi-head attention+ffn後的hidden embedding是上下文相關的,bert預訓練的目的是提供更準確的hidden embedding,而不是token embedding,因此token embedding沒有必要和hidden embedding一樣大。albert將token embedding進行了分解,首先降低embedding size的大小,然後用一個Dense操作將低維的token embedding映射回hidden size的大小。bert的embedding size=hidden size,因此詞向量的引數量是vocab size * hidden size,進行分解後的引數量是vocab size * embedding size + embedding size * hidden size,只要embedding size << hidden size,就能起到減少引數的效果。

4.2.2 引數共享

bert的12層transformer encoder block是序列在一起的,每個block雖然長得一模一樣,但是引數是不共享的。albert將transformer encoder block進行了引數共享,這樣可以極大地減少整個模型的引數量。

4.2.3 sentence order prediction(SOP)

在auto-encoder的loss之外,bert使用了NSP的loss,用來提高bert在句對關係推理任務上的推理能力。而albert放棄了NSP的loss,使用了SOP的loss。NSP的loss是判斷segment A和segment B之間的關係,其中0表示segment B是segment A的下一句,1表示segment A和segment B來自2篇不同的文字。SOP的loss是判斷segment A和segment B的的順序關係,0表示segment B是segment A的下一句,1表示segment A是segment B的下一句。

4.3 albert的技術細節

4.3.1 引數減少技術

albert使用了2項引數減少的技術,但是2項技術對於引數減少的貢獻是不一樣的,第1項是詞向量矩陣的分解,當embedding size從768降到64時,可以節省21M的引數量,但是模型的推理能力也會隨之下降。第2項是multi-head attention+ffn的引數共享,在embedding size=128時,可以節省77M的引數量,模型的推理能力同樣會隨之下降。雖然引數減少會導致了模型推理能力的下降,但是可以透過增大模型使得引數量變回和bert一個量級,這時模型的推理能力就超過了bert。

現在學術界發論文有2種常見的套路,第1種是往死里加引數加資料量,然後提高模型的推理能力;第2種是減引數,然後使模型的推理能力不怎麼降。albert使用的引數減少技術看似是第2種,實則是第1種。當bert從large變到xlarge時,雖然模型變大到了1270M,但是模型出現了退化現象,推理能力下跌了一大截,說明在bert的框架下,large已經是模型推理能力的極限了。albert使用了引數減少技術,相比於bert的large是334M,albert的large只有18M,雖然推理能力比bert差,但是引數減少後的albert還有成長空間,將albert從large變到xlarge,甚至是xxlarge時,模型的推理能力又得到了提高,並且超過了bert最好的模型。

4.3.2 loss

在albert之前,很多bert的改進版都對NSP的loss提出了質疑。structbert在NSP的loss上進行了修改,有1/3的機率是segment B是segment A的下一句,有1/3的機率是segment A是segment B的下一句,有1/3的機率是segment A和segment B來自2篇不同的文字。roberta則是直接放棄了NSP的loss,修改了樣本的構造方式,將輸入2個segment修改為從一個文字中連續sample句子直到塞滿512的長度。當到達文字的末尾且未塞滿512的長度時,先增加一個“[sep]”,再從另一個文字接著sample,直到塞滿512的長度。

albert在structbert的基礎之上又拋棄了segment A和segment B來自2篇不同的文字的做法,只剩下1/2的機率是segment B是segment A的下一句,1/2的機率是segment A是segment B的下一句。論文中給出了這麼做的解釋,NSP的loss包含了2部分功能:topic prediction和coherence prediction,其中topic prediction要比coherence prediction更容易學習,而MLM的loss也包含了topic prediction的功能,因此bert難以學到coherence prediction的能力。albert的SOP loss拋棄了segment A和segment B來自2篇不同的文字的做法,讓loss更關注於coherence prediction,這樣就能提高模型在句對關係推理上的能力。

4.4 albert的總結

albert雖然減少引數量,但是並不會減少推理時間,推理的過程只不過是從序列計算12個transformer encoder block變成了迴圈計算transformer encoder block 12次。albert最大的貢獻在於使模型具備了比原始的bert更強的成長性,在模型變向更大的時候,推理能力還能夠得到提高。

▌5. 其他論文

5.1 gpt

gpt在bert之前就發表了,使用了transformer decoder作為預訓練的框架。在看到了decoder只能get上文資訊,不能get下文資訊的缺點之後,bert改用了transformer encoder作為預訓練的框架,能夠同時get上下文資訊,獲得了巨大的成功。

5.2 structbert

structbert的創新點主要在loss上,除了MLM的loss外,還有一個重構token順序的loss和一個判斷2個segment關係的loss。重構token順序的loss是以一定的機率挑選segment中的token三元組,然後隨機打亂順序,最後經過encoder之後能夠糾正被打亂順序的token三元組的順序。判斷2個segment關係的loss是1/3的機率是segment B是segment A的下一句,有1/3的機率是segment A是segment B的下一句,有1/3的機率是segment A和segment B來自2篇不同的文字,透過“[cls]”預測樣本屬於這3種的某一種。

5.3 roberta

在xlnet使用126G的資料登頂GLUE之後不久,roberta使用160G的資料又打敗了xlnet。roberta的創新點主要有4點:第1點是動態mask,之前bert使用的是靜態mask,就是資料預處理的時候完成mask操作,之後訓練的時候同一個樣本都是相同的mask結果,動態mask就是在訓練的時候每輸入一個樣本都要重新mask,動態mask相比靜態mask有更多不同mask結果的資料用於訓練,效果很好。第2點是樣本的構造方式,roberta放棄了NSP的loss,修改了樣本的構造方式,將輸入2個segment修改為從一個文字中連續sample句子直到塞滿512的長度。當到達文字的末尾且未塞滿512的長度時,先增加一個“[sep]”,再從另一個文字接著sample,直到塞滿512的長度。第3點是增大了batch size,在訓練相同資料量的前提之下,增大batch size能夠提高模型的推理能力。第4點是使用了subword的分詞方法,類比於中文的字,相比於full word的分詞方法,subword的分詞方法使得詞表的大小從30k變成了50k,雖然實驗效果上subword的分詞方法比full word差,但是作者堅信subword具備了理論優越性,今後肯定會比full word好(手動黑臉)。

▌6. 總結

nlp和cv的不同點在於nlp是認識學習,而cv是感知學習,nlp在cv的基礎之上多了一個符號對映的過程,正因如此,nlp領域發展得比cv慢很多,cv領域有很多比較成功的創業公司,有很多能夠達到商用程度的子領域,而nlp領域就比較少。不過nlp領域在17年的transformer釋出之後開始進入快速迭代的時期,bert的發表使得nlp領域的benchmark提高了一大截,產生了不少可以達到商用程度的子領域。到了19年,nlp領域的發展可以說是越來越快了,我在國慶的時候開始執筆寫這個技術分享,當時albert剛發表1個星期,等我寫完這個技術分享已經到11月了,前幾天谷歌又發表了一篇T5,又把albert打敗了。T5的論文據說有50頁,是nlp預訓練模型的一個綜述,值得花時間一看。

最後,水平有限,如有錯誤,請指正。