Transformer導論之Bert預(yù)訓練語言解析
Bert
BERT,全稱為“Bidirectional Encoder Representations from Transformers”,是一種預(yù)訓練語言表示的方法,意味著我們在一個大型文本語料庫(如維基百科)上訓練一個通用的“語言理解”模型,然后將該模型用于我們關(guān)心的下游NLP任務(wù)(如問答)。BERT的表現(xiàn)優(yōu)于之前的傳統(tǒng)NLP方法,因為它是第一個用于預(yù)訓練NLP的無監(jiān)督的、深度雙向系統(tǒng)。
Bert是利用無標簽方式建模的,當談到NLP語料庫中的無標簽和有標簽數(shù)據(jù)時,一個常見的例子是將文本分類任務(wù)。下面是一個例子:
無標簽數(shù)據(jù):來自維基百科的大量文本,這些文本沒有被人工標記或者標注。這些數(shù)據(jù)可以用來預(yù)訓練語言模型,例如 BERT、GPT 等,以學習通用的語言表示形式。
有標簽數(shù)據(jù):例如 IMDB 電影評論數(shù)據(jù)集,其中每個評論都被標記為正面或負面情感。這些數(shù)據(jù)可以用來訓練文本分類器,使其能夠自動對新的評論進行情感分類。
Bert的無監(jiān)督預(yù)訓練方法非常重要,因為它允許我們在大規(guī)模文本語料庫中進行訓練,而無需為每個具體的NLP任務(wù)收集大量的有標簽數(shù)據(jù)。由于網(wǎng)絡(luò)上有大量的無標簽文本數(shù)據(jù),這種方法使得BERT可以利用這些數(shù)據(jù)來訓練模型,提高模型在各種任務(wù)上的表現(xiàn)。與此同時,無監(jiān)督預(yù)訓練還能夠提高模型對于語言的理解和表達能力。BERT的無監(jiān)督預(yù)訓練方法使得我們可以使用一個通用的"語言理解"模型,用于各種NLP任務(wù),如問答、文本分類、實體識別等,而無需為每個任務(wù)重新訓練一個新的模型。BERT 的主要任務(wù)是通過訓練模型來預(yù)測文本序列中缺失的單詞,因此模型只需要對輸入的文本序列進行編碼,而不需要對序列進行解碼。他只用到了Transformer中的Encoder。
Pre-training BERT
Pre-training BERT(Bidirectional Encoder Representations from Transformers)是一種基于大規(guī)模無標注文本數(shù)據(jù)的預(yù)訓練方法,目的是為了訓練出一個通用的語言模型,能夠理解上下文語境中詞語的語義信息。
在BERT的預(yù)訓練過程中,使用了兩個階段的訓練方式:Masked LM和Next Sentence Prediction。
(1)Masked LM(MLM)
Masked Language Modeling (MLM) 是 BERT 模型的一種預(yù)訓練方法,通過將輸入文本中的某些單詞隨機地替換成特殊的 [MASK] 標記,使模型在預(yù)測被替換的單詞時需要依據(jù)上下文信息進行推斷,從而學習到單詞的上下文相關(guān)性。
具體來說,對于輸入文本中的每個單詞,以一定的概率(比如15%)隨機選擇將其替換為 [MASK] 標記,然后將經(jīng)過 [MASK] 標記處理后的文本輸入給模型進行預(yù)測。在預(yù)測過程中,模型需要根據(jù)上下文信息猜測被 [MASK] 標記替換的單詞。這樣的預(yù)測任務(wù)可以促使模型學習到單詞的上下文信息,從而提高下游任務(wù)的性能。
例如,對于輸入文本 "I went to the [MASK] to buy some apples",模型需要根據(jù)上下文信息猜測被 [MASK] 標記替換的單詞是 "store","market","shop" 等。通過這樣的預(yù)測任務(wù),模型可以學習到 "store","market","shop" 在不同上下文中的含義和用法,從而提高下游任務(wù)(如文本分類、情感分析、問答等)的性能。因為采用上下文無關(guān)的方式進行建模,意味著模型不考慮單詞在句子中的位置和上下文環(huán)境,而是將每個單詞獨立地編碼為固定的向量表示。所以MLM是至關(guān)重要的,因為他學習了上下文的信息。
(2)Next Sentence Prediction(NSP)
Next Sentence Prediction (NSP) 是 BERT 中的另外一種預(yù)訓練任務(wù),用于訓練模型學習句子之間的關(guān)系。它的目標是判斷兩個句子是否是相鄰的,即判斷一個句子是否是另一個句子的下一句。
NSP 的訓練過程中,對于每一對輸入的句子,有一半是相鄰的,另一半是隨機選擇的不相鄰的句子。模型需要對這兩種情況進行分類預(yù)測。這個任務(wù)主要是為了幫助模型學習更好的語義表示,尤其是對于需要理解多個句子之間關(guān)系的任務(wù),如問答和文本推理。
輸入的文本會被分成多個token,每個token會被映射為一個向量表示,這個向量表示就被稱為token embedding。
除了token embedding之外,BERT還有另外兩種embedding,分別是sentence embedding和positional embedding。
Sentence embedding是對整個句子進行編碼得到的向量表示。在BERT中,對于輸入的句子對(比如問答場景下的問題和回答),BERT會將句子對之間的特殊標記“[SEP]”添加到中間,并在整個輸入序列的開頭添加另一個特殊標記“[CLS]”。然后,整個序列的第一個token對應(yīng)的向量就是整個句子的sentence embedding。
Positional embedding則是用來表示每個token在句子中的位置信息。由于Transformer并不保留輸入中token的位置信息,因此需要在輸入的token embedding中加入位置信息,使得Transformer能夠捕捉到句子中token的位置信息。這里采用了一種相對位置編碼的方式,將每個token與其他token的相對位置信息編碼成一個向量,然后將該向量加到該token的embedding中。
在BERT中,這三種embedding會被拼接在一起,然后送入Transformer進行編碼。這些編碼代表了符號句子位置的特征。
通過使用 MLM 和 NSP 兩個任務(wù)來預(yù)訓練模型,BERT 能夠?qū)W習到更加豐富的語言表示,這些表示可以在各種 NLP 任務(wù)中進行微調(diào)。
Fine-tuning BERT
Fine-tuning BERT是指在使用預(yù)訓練的BERT模型后,將其進一步調(diào)整以適應(yīng)特定任務(wù)的過程。這個過程可以理解為在BERT的基礎(chǔ)上進行微調(diào)以使其更加適合完成特定的自然語言處理(NLP)任務(wù)。
Fine-tuning BERT的主要步驟如下:
- 準備數(shù)據(jù)集:根據(jù)特定的NLP任務(wù),準備相應(yīng)的數(shù)據(jù)集,包括訓練集、驗證集和測試集。
- 定義任務(wù):根據(jù)任務(wù)類型,選擇適當?shù)腂ERT模型和Fine-tuning策略。對于分類任務(wù),可以使用BERT的CLS向量來表示整個句子,并通過添加一個全連接層來預(yù)測標簽。對于序列標注任務(wù),可以在BERT的基礎(chǔ)上添加一個序列標注層。
- Fine-tuning:將準備好的數(shù)據(jù)集輸入BERT模型進行Fine-tuning。在Fine-tuning過程中,對BERT模型的參數(shù)進行微調(diào),以適應(yīng)特定的NLP任務(wù)。通常使用反向傳播算法進行模型優(yōu)化。
- 模型評估:使用驗證集評估Fine-tuning后的模型性能,可以根據(jù)驗證集的性能調(diào)整Fine-tuning策略或BERT模型的超參數(shù)。最終,使用測試集評估模型的性能。
需要注意的是,F(xiàn)ine-tuning BERT需要大量的計算資源和時間,因為BERT模型本身具有非常多的參數(shù)和復(fù)雜的結(jié)構(gòu)。此外,F(xiàn)ine-tuning BERT的性能還取決于任務(wù)的復(fù)雜性、數(shù)據(jù)集的質(zhì)量和模型的選擇等因素。
代碼實現(xiàn)
下面是使用PyTorch實現(xiàn)Bert模型的示例代碼,包括模型定義、數(shù)據(jù)預(yù)處理、模型訓練和推理:
import torch import torch.nn as nn import torch.optim as optim import torch.utils.data as data import transformers # 1. 定義Bert模型 class BertModel(nn.Module): def __init__(self, bert_config): super(BertModel, self).__init__() self.bert = transformers.BertModel(bert_config) self.dropout = nn.Dropout(bert_config.hidden_dropout_prob) self.fc = nn.Linear(bert_config.hidden_size, num_classes) def forward(self, input_ids, attention_mask): output = self.bert(input_ids=input_ids, attention_mask=attention_mask) output = output[1] # 取第1個tensor作為CLS向量 output = self.dropout(output) output = self.fc(output) return output # 2. 數(shù)據(jù)預(yù)處理 # 數(shù)據(jù)集包含輸入序列和對應(yīng)的標簽 inputs = ["I love Python programming.", "Python is a high-level programming language."] labels = [0, 1] # 0表示第1個句子不是關(guān)于Python編程的,1表示第2個句子是關(guān)于Python編程的 tokenizer = transformers.BertTokenizer.from_pretrained('bert-base-uncased') max_seq_length = 64 # 輸入序列最大長度 inputs_ids = [] attention_masks = [] for input_text in inputs: # 將文本轉(zhuǎn)換為ids和attention mask encoded_dict = tokenizer.encode_plus( input_text, add_special_tokens=True, max_length=max_seq_length, pad_to_max_length=True, return_attention_mask=True, return_tensors='pt' ) inputs_ids.append(encoded_dict['input_ids']) attention_masks.append(encoded_dict['attention_mask']) inputs_ids = torch.cat(inputs_ids, dim=0) attention_masks = torch.cat(attention_masks, dim=0) labels = torch.tensor(labels) # 3. 定義超參數(shù)和優(yōu)化器 num_classes = 2 learning_rate = 2e-5 num_epochs = 3 batch_size = 2 device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model = BertModel(transformers.BertConfig.from_pretrained('bert-base-uncased')).to(device) optimizer = optim.Adam(model.parameters(), lr=learning_rate) # 4. 定義數(shù)據(jù)加載器 dataset = data.TensorDataset(inputs_ids, attention_masks, labels) dataloader = data.DataLoader(dataset, batch_size=batch_size, shuffle=True) # 5. 訓練模型 model.train() for epoch in range(num_epochs): for i, (input_ids_batch, attention_masks_batch, labels_batch) in enumerate(dataloader): input_ids_batch = input_ids_batch.to(device) attention_masks_batch = attention_masks_batch.to(device) labels_batch = labels_batch.to(device) optimizer.zero_grad() outputs = model(input_ids_batch, attention_masks_batch) loss = nn.CrossEntropyLoss()(outputs, labels_batch) loss.backward() optimizer.step() if i % 10 == 0: print(f"Epoch {epoch}, batch {i}, loss: {loss.item()}") # 6. 模型推理 model.eval() test_input = "Python is a popular programming language." encoded_dict = tokenizer.encode_plus( test_input, add_special_tokens
以上就是Transformer導論之Bert預(yù)訓練語言解析的詳細內(nèi)容,更多關(guān)于Transformer導論Bert的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python讀取HDFS目錄下的所有文件的實現(xiàn)示例
HDFS是Apache Hadoop的分布式文件系統(tǒng),本文主要介紹了Python讀取HDFS目錄下的所有文件的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-07-07pytorch 如何使用batch訓練lstm網(wǎng)絡(luò)
這篇文章主要介紹了pytorch 如何使用batch訓練lstm網(wǎng)絡(luò)的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-05-05Python通過paramiko庫實現(xiàn)遠程執(zhí)行l(wèi)inux命令的方法
這篇文章主要介紹了Python通過paramiko庫實現(xiàn)遠程執(zhí)行l(wèi)inux命令,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-03-03Python Django 頁面上展示固定的頁碼數(shù)實現(xiàn)代碼
這篇文章主要介紹了Python Django 頁面上展示固定的頁碼數(shù)實現(xiàn)代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-08-08numpy求矩陣的特征值與特征向量(np.linalg.eig函數(shù)用法)
這篇文章主要介紹了numpy求矩陣的特征值與特征向量(np.linalg.eig函數(shù)用法),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02Python實現(xiàn)優(yōu)先級隊列結(jié)構(gòu)的方法詳解
優(yōu)先級隊列(priority queue)是0個或多個元素的集合,每個元素都有一個優(yōu)先權(quán),接下來就來看一下簡潔的Python實現(xiàn)優(yōu)先級隊列結(jié)構(gòu)的方法詳解:2016-06-06