語言模型賦予了計算機理解和生成人類語言的能力。它結合了統計學原理和深度神經網絡技術,通過對大量的樣本數據進行復雜的概率分布分析來學習語言結構的內在模式和相關性。具體地,語言模型可根據上下文中已出現的詞序列,使用概率推斷來預測接下來可能出現的詞匯。接下來主要介紹一些基礎的語言模型,如Transformer、自動編碼器、自回歸模型等。
2.1 Transformer
Transformer模型是深度學習,尤其是自然語言處理(NLP)領域的一次重大突破。
從概念上看,Transformer模型可以被視為一個黑盒子,以極其翻譯任務為例,它能夠接收某種語言的輸入文本,并輸出對應語言的翻譯版本
從內部結構來看,Transformer由編碼器(encoder)和解碼器(decoder)量大部分構成,這兩部分在原始的"Attention is all you need"論文中包含6個模塊,但在實際應用中,這個數字可以根據具體任務進行調整。
以機器翻譯為例,Transformer的工作流程大致分為以下幾個步驟:
-
獲取句子中每個單詞的表示向量X,X可以通過詞嵌入(embedding)得到。X中包含單詞數據特征和位置信息。如果以簡單的框來表示向量,則每個單詞都可以被表示為一個高緯向量,最終的輸入句子被表示為一個詞向量矩陣。
-
將得到的詞向量矩陣傳入編碼器部分,每個單詞的詞向量都會經過編碼塊,在經過6個編碼塊后可以得到編碼矩陣C。單詞向量矩陣表示為Xn*d,n代表輸入語句中的單詞個數,d代表向量的維度。
-
解碼器部分也是由6個完全相同的解碼塊堆疊而成,解碼時,解碼塊會接收編碼器部分輸出的編碼矩陣C和上一個解碼塊的輸出,即解碼層會根據當前詞i和i之前的詞信息翻譯下一個單詞i+1。在實際的執行過程中,i+1位置后的單詞需要被掩蓋點以防止i+1知道后面的信息。
Transformer的核心結構由詞嵌入、編碼器、解碼器、輸出生成四個部分組成,如下圖所示
2.1.1 詞嵌入
Transformer中輸入單詞的詞嵌入包含單詞編碼和位置編碼。單詞編碼用于編碼單詞的語義,位置編碼用于編碼單詞的位置
1. 單詞編碼
單詞編碼(word embedding)是一種以數字方式表示句子中單詞的方法,該方法用來表示單詞語義特征。這里介紹三種編碼方式:神經網絡編碼、詞向量編碼和全局詞向量表示
(1)神經網絡編碼
基于神經網絡語言模型(Neural Network Language Model,NNLM)的編碼方式最早由Bengio等人提出,用于解決統計語言模型中常見的維度災難問題。該方法是訓練一個神經網絡,在訓練中,每個參與的句子告訴模型由哪些單詞在語義上相近,最終模型為每個單詞生成一種分布式表示,這種表示能夠捕捉并保留單詞的語義和語法關系
Bengio的神經網絡主要由三個部分組成:一個詞嵌入層,用于生成詞嵌入表示,且單詞之間參數共享;一個或多個隱藏層,用于生成詞嵌入的非線性關系;一個激活層,用于生成整個詞匯表中每個單詞的概率分布
該網絡使用損失函數在反向傳播過程中更新參數,并嘗試找到單詞之間相對較好的依賴關系,同時保留語義和語法屬性。下面通過簡單的代碼來理解其訓練過程
1)單詞索引
對單詞建立索引,句子中每個單詞都會被分配一個數字
word_list = " ".join(raw_sentence).split()
word_list = list(set(word_list))
word2id = {w: i for i, w in enumerate(word_list)}
id2word = {i: w for i, w in enumerate(word_list)}
n_class = len(word2id)
2)構建模型
class NNLM(nn.Module):def __init__(self):super(NNLM, self).__init__()self.embeddings = nn.Embedding(n_class, m)self.hidden1 = nn.Linear(n_step * m, n_hidden, bias=False)self.ones = nn.Parameter(torch.ones(n_hidden))self.hidden2 = nn.Linear(n_hidden, n_class, bias=False)self.hidden2 = nn.Linear(n_step * m, n_class, bias=False) #final layerself.bias = nn.Parameter(torch.ones(n_class))def forward(self, x):X = self.embedding(X)X = X.view(-1, n_step * m)tanh = torch.tanh(self.bias + self.hidden1(X))output = self.bias + self.hidden3(X) + self.hidden2(tanh)return output
在該過程中,首先初始化詞嵌入層。詞嵌入層相當于一個查找表,被索引表示的單詞通過詞嵌入層,然后再通過第一個隱藏層并與偏置量求和,求和結果傳遞給tanh函數。最后計算輸出,代碼如下:
output = self.b + self.hidden3(X) + self.hidden2(tanh)
3)損失函數
這里使用交叉熵損失函數,并將模型輸出傳遞給softmax函數獲得單詞的概率分布
criterion = nn.CrossEntropyLoss()
4)進行訓練
經過訓練最終得到單詞的編碼結果
(2)詞向量編碼
詞向量(Word2vector)模型由Mikolov等人在2013年提出,比Bengio的神經網絡語言模型的復雜性更小。詞向量模型可以在更大的數據集中訓練,但缺點是如果數據較少,就無法像神經網絡語言模型那樣精確地表征數據。詞向量模型包含兩種模式:詞袋(Bag-of-Words)模型和跳躍(Skip-gram)模型。
詞袋模型又稱為CBOW模型,它基于目標詞前后的n個單詞來預測目標單詞。假設句子為:“她在踢毽子”,以"毽子"作為目標詞,取n=2,那么[正,在,毽,子]等前后單詞及目標單詞踢將被一起輸入給模型。CBOW模型通過計算log2V來降低計算詞表中單詞分布概率的復雜性,V代表詞匯表大小。該模型速度更快,效率更高。
同樣的,通過代碼來理解CBOW模型,其訓練過程如下:
1)定義一個窗口函數,該函數提取目標單詞的左右各n個單詞
def CBOW(raw_text, window_size=2):data = []for i in range(window_size, len(raw_text) - window_size):context = [raw_text[i - window_size], raw_text[i - (window_size - 1)], raw_text[i + (window_size - 1)], raw_text[i + window_size]]target = raw_text[i]data.append((context, target))return data
上述CBOW函數包含兩個輸入參數:數據和窗口大小。窗口大小定義了應該從單詞左側和右側提取多少個單詞。for循環首先定義了句子中迭代的開始索引和結束索引,即從句子中的第3個單詞開始到倒數第3個單詞結束。在循環內部將窗口提取到窗口大小為2,此時窗口提取到的單詞為"正" “在” “毽"和"子”,目標單詞是"踢",當i=2(窗口大小)時,代碼如下:
context = [raw_text[2-2], raw_text[2 - (2-1)], raw_text[i + (2-1)], raw_text[i + 2]]
target = raw_text[2]
執行CBOW函數:
data = CBOW(raw_text)
print(data[0])
上述輸出為:
Output:
(["正","在","毽","子"], "踢")
2)構造模型
CBOW模型只包含一個詞嵌入層、一個經過ReLU層的隱藏層和一個輸出層。代碼如下:
class CBOW_Model(torch.nn.Module):def __init__(self, vocab_size, embedding_dim):super(CBOW_Model, self).__init__()self.embeddings = nn.Embbeding(vocab_size, embedding_dim)self.linear1 = nn.Linear(embedding_dim, 128)self.activation_function1 = nn.ReLU()self.linear2 = nn.Linear(128, vocab_size)def forward(self, inputs):embeds = sum(self.embeddings(inputs)).view(1, -1)out = self.linear1(embeds)out = self.activation_function1(out)out = self.linear2(out)return out
該模型非常簡單,單詞索引輸入層嵌入層,之后經過隱藏層,隱藏層輸出經過一個非線性層ReLU之后經過輸出層得到最終結果。
3)損失函數
與神經網絡語言模型一樣,采用交叉熵損失函數。優化器選擇隨機梯度下降,代碼如下:
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
4)訓練模型
訓練代碼與神經網絡語言模型袋代碼一致,具體如下:
for epoch in range(50):total_loss = 0for context, target in data:context_vector = make_context_vector(context, word_to_ix)output = model(context_vector)target = torch.tensor([word_to_ix[target]])total_loss += loss_function(output, target)optimizer.zero_grad()total_loss.backward()optimizer.step()
最終將語句單詞轉化為數字序列
對比詞向量模型,跳躍模型是基于目標單詞預測目標單詞的上下鄰近單詞。假設目標單詞n=2,同樣以句子"她正在踢毽子"為例,單詞"踢"將被輸入模型用于預測目標單詞(“正”,“在”,“毽”,“子”)。其結構如下圖:
跳躍模型與詞袋模型類似,不同點在于創建上下文和目標單詞。
相比詞袋模型,跳躍模型增加了計算的復雜度,因為它必須根據一定數量的相鄰單詞來預測鄰近單詞。在實際的語句中,距離較遠的單詞相關性往往比較差
(3)全局詞向量表示
全局詞向量表示(Global Vectors for Word Representation,GloVe)是一種基于全局信息來獲得詞向量的方法。該方法使用了語料庫的全局統計特征,也使用了局部的上下文特征,GloVe通過引入共現矩陣(Co-occurrence Probabilities Matrix)來表征。
定義詞到詞的共現矩陣為X,Xij代表單詞j出現在單詞i的上下文的次數,Xi表示出現在單詞i的上下文的詞的總數。Pij = P(j|i) = Xij/Xi表示單詞j出現在單詞i的上下文中的概率。
定義詞i、j與詞k的共現概率為P = Pik / Pjk,詞與詞之間的關系可以通過共現概率體現,即如果詞k與詞i相近,與詞j較遠,則希望Pik / Pjk越大越好,如果詞k與詞j相近,與詞i較遠,則希望Pik / Pjk越小越好,如果詞k與詞i和詞j都相近或都較遠,則Pik / Pjk趨近于1
共現概率既很好地區分了相關詞和不相關詞,又反映了相關詞的關聯程度。GloVe模型就是基于該共現概率的信息構建的,其核心目標是為了每一個詞生成一個詞向量,這樣詞向量就能映射出詞與詞之間的共現概率,以此捕捉它們的語義關系。假設定義GloVe模型為F,則上述共現概率可以使用如下公式來表示:
F(wi, wj, wk) = Pik / Pjk
其中,w 代表詞向量
綜上,單詞詞嵌入編碼方法的特點如下:
- 神經網絡語言模型的性能優于早期的統計模型
- 神經網絡語言模型解決了維度災難問題,并通過其分布式表示保留了上下文語義和句法屬性,但計算成本很高
- 詞向量模型降低了計算復雜性,比神經網絡語言模型效率更高,它可以在大量數據上進行訓練,用高維向量表示
- 詞向量模型有兩種:詞袋模型和跳躍模型。前者比后者運算更快
- GloVe納入了全局信息但無法解決一詞多義和陌生詞問題
2. 位置編碼
位置編碼(Position Embedding)用來表示句子中單詞的位置,且每個位置被賦予唯一的表示。位置編碼要滿足以下特點:
- 編碼值可以表示單詞在句子中的絕對位置,且是有界的
- 句子長度不一致時單詞間的相對位置距離也要保持一致
- 可以表示從未見過的句子長度
Transformer使用正余弦函數來進行位置編碼。其公式如下:
PE(pos, 2i) = sin(pos/10000^2i/d model)PE(pos, 2i+1) = cos(pos/10000^2i/d model)
其中,pos表示單詞在句子中的位置,d表示PE的維度(與單詞編碼一樣),2i表示偶數的維度,2i+1表示奇數維度(即2i<=d, 2i+1 <=d)。使用這種公式計算PE有以下的好處:
- 能夠適應比訓練集中所有句子更長的句子。假設訓練集中最長的句子有20個單詞,此時有一個長度為21的句子,則使用公式計算的方法可以計算出第21位的編碼
- 能夠較容易地計算出相對位置。對于固定長度的間距k,PE(pos+k)可以用PE(pos)計算得到
接下來通過代碼來理解位置編碼
import numpy as np
import matplotlib.pyplot as plt
def getPositionEncoding(seq_len, d, n=10000):P = np.zeros((seq_len, d))for k in range(seq_len):for i in np.arange(int(d/2)):denominator = np.power(n, 2*i/d)P[k, 2*i] = np.sin(k/denominator)P[k, 2*i+1] = np.cos(k/denominator)return PP = getPositionEncoding(seq_len=4, d=4, n=100)print(P)[
[0. 1. 0. 1. ]
[0.84147098 0.54030231 0.09983342 0.99500417]
[0.90929743 -0.41614684 0.19866933 0.98006658]
[0.14112001 -0.9899925. 0.29552021 0.95533649]
]
看一下n=10000和d=512的不同位置正弦曲線
def plotSinusoid(k, d=512, n=10000):x = np,arange(0, 100, 1)denominator = np.power(n, 2*x/d)y = np.sin(k/denominator)plt.plot(x, y)plt.title('k = ' + str(k))
fig = plt.figure(figsize=(15, 4))
for i in range(4):plt.subplot(141 + i)plotSinusoid(i*4)
每個位置k對應于不同位置的正弦曲線,它將位置編碼為向量。
即正弦曲線的波長形成幾何級數,并且變化范圍為2pai到2pai n,該方案的優點如下:
- 正弦和余弦函數的值在[-1, 1]范圍內,即編碼值是有界的
- 由于每個位置的正弦曲線不同,因此可以采用獨特的方式對每個位置進行編碼,即每個位置的編碼都是唯一的
- 基于正弦變化可以測量或量化不同位置之間的相似性,從而能夠對單詞的相對位置進行編碼
進一步,通過Matplotlib來可視化位置矩陣
P = getPositionEncoding(seq_len=100, d=512, n=10000)
cat = plt.matshow(P)
plt.gcf().colorbar(cax)
綜上,將整個句子所有單詞的位置編碼向量與單詞編碼向量相加得到輸出矩陣,整個流程如下圖:
2.1.2 編碼器
編碼器由多頭注意力、加法和歸一化、前饋層組成
1. 多頭注意力
在介紹多頭注意力之前,首先介紹一下自注意力
自注意力是機器學習使用的一種學習機制,屬于仿生學的一種應用,即人類會把注意力放在重點關注的信息上。在自然語言處理任務中,自注意力用于捕獲輸入序列內的依賴性和關系,讓模型通過關注自身來識別和權衡輸入序列不同部分的重要性。在編碼器中,自注意力的輸入參數有三個:查詢(query)、鍵(key)、值(value)
這三個參數在結構上很相似,都是被參數化的向量。每個單詞的詞嵌入向量都由這三個矩陣向量來表征,幫助計算機理解和處理句子中單詞之間的關系。這三個矩陣向量的作用各不相同。
1)查詢
該矩陣表示正在評估其上下文的目標單詞。系統通過使用查詢矩陣轉換該目標單詞的表示形式,生成一個查詢向量。此查詢向量用于衡量其與句子中其他單詞的關聯度
2)鍵
該矩陣用于生成句子中每個單詞對應的鍵向量。通過對每個鍵向量和目標單詞的查詢向量進行比較,計算得出目標單詞與句子中其他詞之間的相關性。查詢向量和關鍵向量之間的相似度分數越高,表示相應單詞之間的關系越緊密
3)值
該矩陣用于生成句子中所有單詞的值向量,這些向量保存每個單詞的上下文信息。使用查詢向量和鍵向量計算相似度分數后,系統計算值向量的加權和。每個值向量的權重由相似度分數確定,確保最終的上下文表示更多地受到相關單詞的影響
如下圖所示,語句中單詞"一"的查詢矩陣向量q3與所有詞的鍵矩陣向量k進行計算,得到注意力得分y31、y32、y33、y34。之后分別與自身的值矩陣向量做乘積,得到每個詞抽取信息完畢的向量,最后所有向量求和得到z3,即為單詞"一"經過注意力后的結果
Transformer中的自注意力使用的是多頭注意力,即通過組合多個類似的注意力計算給予了Transformer更大的辨別能力。多頭注意力結構如下:
在多頭注意力中,查詢、鍵和值分別通過單獨的線性層,每個層都有自己的權重,產生三個結果,分別稱為Q、K、V。然后在縮放點積注意力中基于注意力公式進行組合運算。
在上述過程中,Q、K、V攜帶了序列中每個單詞的編碼表示,之后注意力計算將每個單詞與序列中的其他單詞結合起來,以便注意力分數對序列中每個單詞的分數進行編碼。在該過程中提到了掩碼。由于輸入的序列可能具有不同的長度,因此需要使用填充標記對句子進行擴展對齊長度,以便可以將固定的向量輸入Transformer中,這里的掩碼主要是為了填充部分的注意力輸出為0,確保填充標記不會對注意力分數產生影響。
2. 加法和歸一化
加法過程是一種殘差機制,主要為了解決深層神經網絡訓練過程的不穩定性,即深度神經網絡隨著層數的增加,損失逐漸減小然后趨于穩定,繼續增加層數損失反而增大的現象。簡單來說就是用來防止梯度消失。
歸一化用來歸一化參數,加快訓練速度,提高訓練的穩定性。
3. 前饋層
前饋層作為注意力層后面的子層,由兩個線性層或致密層構成。第一層的大小為(d_model, d_ffn),第二層的大小為(d_ffn,d_model)。
通過以下代碼來理解這個過程
class PositionwiseFeedForward(nn.Module):def __init__(self, d_model: int, d_ffn: int, dropout: float = 0.1):"""Args:d_model: dimension of embeddingsd_ffn: dimension of feed-forward networkdropout: probablity of dropout occurring"""super().__init__()self.w_1 = nn.Linear(d_model, d_ffn)self.w_2 = nn.Linear(d_ffn, d_model)self.dropout = nn.Dropout(dropout)def forward(self, x):"""Args:x: output from attention (batch_size, seq_length, d_model)Returns:expanded-and-contracted representation (batch_size, seq_length, d_model)"""return self.w_2(self.dropout(self.w_1(x).relu()))
2.1.3 解碼器
解碼器也由多頭注意力、加法和歸一化、前饋層組成,每個解碼器包含兩層多頭注意力,這兩個多頭注意力與編碼器中的多頭注意力作用不同。
1. 掩碼多頭注意力
掩碼多頭注意力與編碼器不一致的地方在于掩蓋的步驟,此處的掩碼過程主要為了防止解碼器在預測下一個單詞時"偷看"目標語句的其余部分
2. 多頭注意力
解碼器中的多頭注意力與編碼器中的主要區別在于,它的K、V矩陣不是基于上一個解碼器的輸出計算而來的,而是來自編碼器的輸入,但Q矩陣還是根據解碼器的輸出計算得到的。計算過程與編碼器中的一樣,掩碼步驟也與編碼器的一致
2.1.4 解碼頭
解碼器將輸出傳遞給解碼頭,解碼頭將接收到的解碼器輸出向量映射為單詞分數。詞庫中的每個單詞在句子中的每個位置都會有一個分數。假設最終輸出的句子有4個詞,詞庫中有1000個詞,那么在這4個詞的每個位置都會生成1000個分數,這些分數代表詞庫中每個詞出現在句子中每個位置的可能性。之后這些分數將送入softmax層,softmax將這些分數轉換為概率(加起來為1.0)。在每個位置上,找到概率最高的單詞的索引,然后將該索引映射到詞匯表中相應的單詞。最后,這些單詞形成Transformer的輸出序列。
2.2 自動編碼器
自動編碼器(Autoencoder)是一類神經網絡,通過無監督學習重建其輸入數據,同時在這個過程中實現數據的有效壓縮。
自動編碼器的結構主要包括兩個部分:編碼器網絡和解碼器網絡。編碼器網絡負責將高維的輸入數據轉換成更低維的表示,而解碼器網絡則從這些低維表示中恢復出原始數據。這種結構不僅能夠捕捉數據中的關鍵特征,而且有助于在解碼過程中有效地重建數據。
自動編碼器的核心是學習輸入數據的有效表示。這一過程涉及編碼器將數據編碼為低維表示,解碼器再基于這些表示重建原始數據。網絡通過學習一個接近恒等的映射來實現這一點,其參數優化過程可以通過計算輸入與重建輸出之間的均方差來量化。
2.2.1 ELMo
前面介紹了一些常用的詞嵌入方法,如NNLM、Word2vector、GloVe等,這幾種方法本質上都是先訓練好一個語言模型,然后輸入單詞取模型的隱藏層表示來作為單詞的詞向量表示。這些方法都是靜態的表示方法,即一旦模型確定則單詞的詞向量表示也確定。雖然這些語言模型的詞表征方法在下游任務中取得了優異的表現。但大多情況下單詞的詞義是隨語境變化的,因此這些方法得到的詞向量有一定的缺陷,尤其無法表達多義詞。
與靜態詞嵌入方法不同ELMo(來自語言模型的嵌入)采用動態方法生成詞嵌入,它基于訓練好的語言模型,并能根據上下文實時調整詞嵌入,有效地緩解了詞義歧義的問題。
ELMo模型來自2018年的論文,在論文中提出了深度雙向語言模型來表征詞向量。該模型的原理是,首先訓練好一個靜態的語言模型來表征詞向量,該模型存在上述提到的缺陷,即無法理解歧義,當執行實際任務時,可實時根據上下文單詞的語義去調整之前表征好的詞向量,這些經過調整后的詞向量更能表達具體語境中的含義,從而解決多義詞問題。該方法是一種結合上下文語境的動態調整思路。ELMo模型是采用雙向LSTM構建,在一個大型文本語料庫中訓練而成的。
ELMo的訓練過程包含兩個階段,分別是預訓練和下游任務。預訓練階段與之前的語言模型訓練類似,預計訓練的目標是根據目標詞的上下文預測目標詞。
左側的雙向LSTM代表正向編碼器,負責從前往后提取信息,輸入為句子序列中從左到右(除目標詞外)的上文,右側的雙向LSTM代表逆向編碼器,負責從后往前提取信息,輸入為句子序列中從右到左的逆序下文。
ELMo的預訓練過程完成后,單詞經過ELMo模型可以得到三層編碼信息,Ei代表最底層的單詞特征信息編碼,從下往上第一層LSTM包含了句法特征的單詞位置編碼信息,第二層LSTM包含了語義特征的單詞位置編碼信息。
在預訓練好的網絡結構完成后,如何將其應用于特性的下游任務,比如問答問題?假設有一個問句X,首先,將這個句子X輸入已經預訓練好的ELMo網絡中。通過這個過程,句子X中的每個單詞在ELMo網絡中都會生成對應的三層編碼信息。接下來,分別為這三層編碼信息分配一個權重a,這些權重是可以通過學習得到的。然后,根據各自的權重進行加權求和,將這三層編碼融合成一個詞向量,這樣句子中的每個單詞都有一個對應的詞向量。在執行問答任務時,問句X中的每個詞對應的詞向量作為任務的輸入,這樣可以利用預訓練ELM。網絡中的語境信息,從而增強下游任務的性能。
2.2.2 BERT
BERT(Bidirectional Encoder Representations from Transformers,來自Transformer的雙向編碼器表征法),旨在通過聯合左側和右側的上下文,從未標記文本中預訓練出一個深度雙向表示模型。BERT的結構中只包含Transformer的編碼部分,與按順序(從左到右或從右到左)讀取文本輸入的方向模型不同,BERT的編碼器會讀取整個單詞序列,這被認為是雙向讀取,準確來說是非定向的。BERT的這種特性允許模型根據單詞的周圍環境(包括左側和右側)來學習單詞的上下文,它的訓練結果表明雙向訓練的語言模型比單向的語言模型更深入地了解語言上下文和流程。
1. 模型結構
在前面提到Transformer的編碼器結構由多頭注意力、加法和歸一化、前饋層堆疊而成。BERT中的每一個Transformer層都是由這樣的編碼器單元構成的。
2. 預訓練
BERT的預訓練方式包括兩種:MLM(Masked Language Model掩碼語言模型)和NSP(Next Sentence Prediction,下句預測)
(1)MLM
MLM任務的目標是使模型能夠根據詞的上下文推斷被掩蓋的詞。訓練時,輸入序列中約15%的詞會被選中,并作為標簽去預測,這15%中:
- 80%的詞替換為[mask],這主要是為了讓模型在沒有看到原始詞的條件下通過上下文來正確預測該詞
- 10%的詞用隨機詞來替換,這迫使模型在每個詞上學習全局語境特征準確預測該位置的原始詞,從而使BERT獲得更好的語境詞向量,有助于解決一詞多義問題
- 10%的詞保持不變,即BERT模型由1.5%比例的詞是已知的,這是為了防止模型總是預測被掩蓋的詞
基于以上的處理方式,BERT模型會嘗試根據序列中掩蓋單詞周圍的上下文來預測掩蓋單詞的原始值
(1)NSP
在進行NSP訓練時,模型接受一對句子作為輸入,其目標是判斷這兩個句子是否在原文中是連續的。為了幫助模型在訓練中區分兩個句子,輸入句子對按以下方式進行處理:
- 50%的句子對(句子A和句子B)是相鄰的,即在原始語料中,句子B是跟在句子A后面的
- 剩余50%的句子對,句子B不是句子A的后續句子,而是從語料庫中隨機選取的一個不相關的句子
- 對句子對添加特殊的標記,即句子A開頭插入[CLS]標記,句子B末尾插入[SEP]標記,句子A和句子B中間插入[SEP]標記
- [CLS]標記用來區分句子A和句子B是否連續
通過以上處理后,輸入句子對用于訓練一個理解句子關系的BERT模型
3. 微調
除了輸出層,BERT的預訓練和微調都使用了相同的架構,且使用相同的預訓練參數來初始化不同下游任務的模型。在微調過程中,所有的參數都會被微調。[CLS]是在每個輸入示例前面添加的特殊符號,[SEP]是特殊的分隔符標記,如分割問題或答案。
BERT可以通過微調被靈活應用在多種不同的語言處理任務上,且只需要在模型結構上做很小的改動:
- 對于文本分類任務(如情感分析),BERT的微調非常直接。可以在[CLS]標記的輸出向量上(該向量旨在捕捉輸入序列的整體意義)添加一個簡單的分類層。這個分類層將針對特定的分類任務進行訓練,比如區分文本是正面情感還是負面情感
- 對于問答發任務,BERT需預測文本序列中答案的位置。這可以通過預訓練模型的基礎上,在答案的開始和結束為止各加入一個預測層來實現。這些層會學習并識別出每個單詞是否為答案的開始或結束,且在訓練過程中優化這些預測
- 對于命名實體識別(NER)任務,BERT模型需要識別出文本中的命名實體,如人名、組織名、地點或時間等。為了完成這個任務,BERT對每個詞的向量表示都會輸出給一個特別設計的分類層,該層能夠預測每個詞所對應的實體類別(或無實體類別)
總之,通過在BERT的輸出層上添加定制任務的特定層,并在有監督的任務數據上進行微調,BERT能夠靈活地適應一系列不同的NLP任務且表現出色。這種方法的優勢在于,微調過程利用了BERT深層次預訓練模型中豐富語言知識,提高了特定模型的性能。
基于BERT還有很多衍生模型,如WWM、HEZHA、MacBERT和ERNIE等,分別有不同的特點
1)WWM
WWM是谷歌在2019年發布的BERT升級版本,該方法引入了全詞掩碼。簡單來說,原有基于WordPiece的分詞方式會把一個完整的詞切分為若干個子詞,在生成預訓練樣本時,這些子詞會被隨機掩蓋,在WWM中,如果一個詞的部分WordPoece子詞被掩蓋,則該詞會被完整掩蓋掉。該方法能更好地處理語義信息,尤其是對那些由多個詞符組成的詞
2)HEZHA
HEZHA是一個專門為中文優化的BERT變種,由華為諾亞方舟實驗室開發,對BERT模型的預訓練和微調過程進行了改進,即增加相對位置編碼函數、全詞掩蓋、混合精度訓練和改進優化器,使之更適合中文的語言特點,提升了中文文本的處理效果
3)MacBERT
MacBERT來自哈工大SCIR實驗室,該論文提出在預訓練階段相似的單詞來掩蓋,縮小了預訓練和微調階段的差異
4)ERNIE
ERNIE由百度開發,整合了豐富的知識圖譜信息。ERNIE在預訓練階段使用了實體級的掩蓋策略,能夠理解實體之間的關系。通過對訓練數據中的詞法結構、語法結構、語義信息進行統一建模,極大地增強了通用語義表示能力,ERNIE能更好地理解和處理復雜語言結構和知識信息。
以上這些衍生模型都是在原始BERT的基礎上進行了特定的改進,以適應不同的語言特性、提高模型的性能或解決特定的任務。這些模型展示了預訓練語言模型在自然語言處理領域的快速發展和多樣化應用
2.3 自回歸模型
自回歸模型(AutoRegressive Model, AR模型)是基于過去數據來預測當前數據的線性模型。例如,了解某產品今天的價格,可以借此預測其明天的價格。在數學上,定義自回國模型為AR§,其中p代表模型的階數,即用于預測當前值的過去觀測值的數量。如果以X表示時間序列,那么AR(1)代表一個簡單的自回歸模型
2.3.1 GPT
GPT(Generative Pre-Trained,生成式預訓練)模型是使用Transformer架構的神經網絡模型。2018年6月,OpenAI發布論文首次提出GPT模型框架,該框架通過預訓練和微調,使用與任務無關的單一模型來實現強大的自然語言理解(NLU)。接下來將從生成式預訓練、對Transformer結構的改進及GPT的演進歷史三個角度對GPT模型框架進行闡釋。
1. 生成式預訓練
在GPT開發之前,大多數SoTA NLP模型都是使用監督學習專門針對特定任務進行訓練的,例如問答、文本涵蘊、語義相似性評估、文檔分類等。然而,監督模型有兩個主要問題:
1)標記數據的稀缺
監督模型通常需要大量帶注釋的數據來學習某項任務,而這些數據通常不容易獲得,這使得經過區分訓練的模型難以充分執行
2)概括能力差
監督模型無法概括所有訓練的任務之外的任務
基于以上問題,GPT提出了在多種未標記文本的語料庫上對語言模型進行生成式預訓練,然后對每個特定下游任務進行區分性微調,取得了巨大成功
在機器學習領域,有判別式模型(Discriminative Model)和生成式模型(Generative Model)兩種
因此,生成式模型更適合大模型數據學習,判別式模型更適合小樣本標注數據。GPT中使用了生成式的預訓練和判別式的微調。以GPT-1為例,GPT-1語言模型是使用BooksGorpus數據集進行訓練的。BooksGorpus包含約7000本未出版的書籍,這些書籍有助于在未見過的數據上訓練語言模型。該語料庫還包含長段的連續文本,這有助于模型處理遠程依賴關系。具體的訓練過程如下:
- 判別式模型
- 學習類判別邊界
- 最大化條件概率:P(Y|X)給定輸入X,最大化標簽Y概率
- 生成式模型
- 學習類條件分布
- 最大化聯合概率P(X|Y)
1)無監督語言模型建模(預訓練)
在巨大的文本庫上學習高容量的語言模型,即給定無監督的token集合u = {u1, …, un},使用標準語言模型目標(Language Modeling Objective)來最大化似然函數
實驗中,使用多層Transformer解碼器作為語言模型,這與原始的Transformer有些不同,屬于Transformer的變體。該模型對輸入上下文token應用多頭注意力操作,然后通過位置前饋層在token上輸出分布
2)有監督的微調
經過無監督訓練得到訓練模型后,進一步訓練參數適應有監督的目標任務。假設一個帶標簽的數據集C,每個樣本由一系列的token x1, …, xn組成,且對應標簽y。通過預訓練模型將輸入傳遞給transformer模塊的激活層,之后輸入給線性層
同時,在微調過程中將語言模型作為輔助目標,有助于提高監督模型的泛化能力和快速收斂
本質上,監督微調是通過在Transformer模型中添加線性層和Softmax層來獲取下游任務的任務標簽來實現的
3)特定任務的輸入轉換
對于一些文本分類任務,可以直接按以上所述對預訓練模型進行微調。但對于一些其他任務,如文本蘊涵或問答,它們的特點是結構化的輸入,如有序句子對或文檔、問題和答案的三元組等。由于預訓練模型是在連續的文本序列上訓練的,因此對于此類任務需要對輸入做一些修改以適應預訓練模型。整體的邏輯是需要將結構化輸入轉換為一個有序的序列,以使預訓練模型可以進行處理。對于不同的任務,處理方法也不同
4)文本蘊涵(內涵邏輯推理)
對于文本繼承,將前提P和假設H的token序列用分隔符$連接
5)相似性任務
對于相似性任務,兩個被比較的句子沒有固定的順序。為了表達這一點,將輸入序列進行修改以包含兩個句子順序的所有可能性,句子之間通過分隔符連接,分別處理每個序列以生成兩個序列的表示,并在送入線性輸出層之前按元素寬度相加。
6)問答和常識推理
對于有一個上下文文檔z,一個問題q和一組可能的答案{ak} 的樣本,首先將文檔和問題連接組成上下文,之后通過分隔符($)與每個可能的答案連接組成序列。每個序列都通過模型獨立處理,結果輸入線性層之后通過Softmax層輸出所有答案的可能性分布。
2. 對Transformer結構的改進
GPT的模型設計遵循了原始Transformer的工作原理,不同之處在于GPT只保留了解碼層,從而使得模型更為簡單。整體上,GPT模型由12個解碼器堆疊成,每個解碼器包含掩碼多頭注意力層、正則層、前饋層等。
3. GPT演進歷史
最早的語言模型是基于規則的系統,需要大量的人類輸入才能發揮作用。然而,隨著機器學習和深度學習技術的出現,這些模型的復雜性和準確性急劇增加。整體上,GPT模型的演進歷史可以概括如下:
1)GPT-1
2018年6月,OpenAI推出了第一個GPT模型,即GPT-1。包含1.17億個參數,通過BooksCorpus數據集(約7000本書)進行訓練,并主張通過大規模、無監督預訓練+有監督微調進行模型構建。GPT-1能夠幾乎與人類寫作無異的連貫句子和段落,具有開創性意義。
2)GPT-2
2019年2月,OpenAI發布GPT-2模型,它是GPT-1的升級版,具有15億個參數,在更大規模的數據集上訓練(約40GB數據集),同時訓練過程去掉微調,強調零樣本和多任務學習。該模型能夠生成更長、更連貫的文本。然而,由于其強大的能力,開發者未完全公開其版本,因擔心它可能被用于生成假新聞和誤導性內容。
3)GPT-3
2020年5月,OpenAI發布GPT-3模型。它的創建者使用大量文本數據(約570GB數據集,包括書籍、文章和網頁)對其進行訓練,它擁有1750億個參數,訓練過程同時采用少樣本學習模式。GPT-3能夠生成與人類編寫的內容幾乎無法區分的文本。GPT-3的性能非常出色,已被用于各種應用,例如自然語言處理、文本分類和聊天機器人
4)Instruct GPT
2022年2月,OpenAI發布Instruction GPT模型。該模型主要是在GPT3的基礎上增加了監督微調(Supervised Fine-tuning)環節,并且基于此,進一步加入了獎勵模型,通過RM訓練模型來對學習模型進行增強學習優化。
5)ChatGPT
2022年11月30日,OpenAI發布ChatGPT模型,可以理解為一個多輪迭代訓練后的InstructionGPT,并在此基礎上增加了對話聊天功能。ChatGPT的發布是自然語言處理領域的重大發展。ChatGPT的發布是自然語言處理領域的重大發展。ChatGPT已經過大型對話數據語料庫的訓練,這使其能夠理解并響應自然語言查詢。
6)GPT-4
2023年3月14日,OpenAI發布GPT-4,GPT-4是一個先進的多模態大語言模型,不僅能夠處理文本輸入,還能夠理解和分析圖像內容。GPT-4的訓練資料包含了廣泛的公共數據集以及第三方提供商授權使用的數據集。該模型經過了強化學習過程,即依賴于人類審查員和AI系統生成反饋的優化。強化學習過程提升了模型的性能和適應性,確保GPT-4的輸出既符合人類的期望,又嚴格遵循既定的政策和指導原則。
從GPT-1模型到GPT-4模型,隨著深度學習技術的發展,GPT語言模型取得了巨大的進步,隨著GPT語言模型的不斷發展,在塑造人工智能技術的未來及釋放對語言理解和生成的新見解方面具有巨大的潛力。
2.3.2 LLaMA
LLaMA(Large Language Model Meta AI, Meta AI大型語言模型)是Meta AI的FAIR團隊于2002年12月至2023年2月開發的,它的誕生是自然語言處理研究領域的一個重要里程碑。
1. LLaMA模型簡介
LLaMA有7B、13B、33B和65B四種不同參數規模的模型,不同的模型大小可以適應不同的研究需求和算力資源。從這些模型的評測表現來看,LLaMA-13B僅比1/10規模的參數在多數的Benchmarks上性能優于GPT-3(175B),而LLaMA-65B可比肩業內最好的模型CHinchilla-70B和PaLM-540B
2. 預訓練數據
LLaMA的預訓練數據來自多種不同的數據源,涵蓋了多個領域
3. 模型結構
LLaMA的整體架構仍然是Transformer的解碼器架構,但在Transformer的基礎上進一步做了3方面改進:
1)預歸一化(Pre-normalization)
為了提高訓練的穩定性,對每一個解碼器的子層輸入進行歸一化而不是輸出進行歸一化,歸一化方式采用均方根標準化(Root Mean Square layer Normalization,RMSNorm)
2)SwiGLM激活函數
為了提升性能,在前饋層用SwiGLU激活函數替換ReLU函數
3)旋轉嵌入(Rotary Embeddings)
去掉了絕對位置嵌入,并在每個網絡層中添加旋轉位置嵌入(Rotary Positional Embeddings,RoPE)
2.4 本章小節
本章介紹了語言模型的基礎原理,包含了Transformer、自動編碼器、自回歸模型等的原理。在Transformer的原理介紹中,以語言翻譯為例介紹了Transformer的工作流程,以及詞嵌入、編碼器、解碼器等核心部分。而在詞嵌入中,詳細介紹了單詞編碼(神經網絡編碼和詞向量編碼)和位置編碼,并說明底層構造原因。在編碼器和解碼器中,重點講解了注意力機器和前饋層。在自動編碼器的原理一節中,介紹了ELMo和BERT的原理和內部機制。最后,在自回歸模型中,介紹了GPT和LLaMA,當下最熱門的語言模型,介紹了數學原理和對原始transformer結構的改進。