【深度学习】预训练语言模型-BERT
1.BERT簡介
????????BERT是一種預訓練語言模型(pre-trained language model, PLM),其全稱是Bidirectional Encoder Representations from Transformers。下面從語言模型和預訓練開始展開對預訓練語言模型BERT的介紹。
1-1 語言模型
????????語言模型 :對于任意的詞序列,它能夠計算出這個序列是一句話的概率。比如詞序列A:“知乎|的|文章|真|水|啊”,這個明顯是一句話,一個好的語言模型也會給出很高的概率,再看詞序列B:“知乎|的|睡覺|蘋果|好快”,這明顯不是一句話,如果語言模型訓練的好,那么序列B的概率就很小很小。
????????下面給出較為正式的定義。假設我們要為中文創建一個語言模型,V?表示詞典, V = ?{ 貓,狗,機器,學習,語言,模型,…},?。語言模型就是這樣一個模型:給定詞典 V,能夠計算出任意單詞序列(比如:單詞序列[、、...]、[???????、、])是一句話的概率。probability?=??
????????從文本生成角度來看,我們也可以給出如下的語言模型定義:給定一個短語(一個詞組或一句話),語言模型可以生成(預測)接下來的一個詞。
1-2?預訓練模型
????????從字面上看,預訓練模型(pre-training model)是先通過一批語料進行模型訓練,然后在這個初步訓練好的模型基礎上,再繼續訓練或者另作他用。預訓練模型的訓練和使用分別對應兩個階段:預訓練階段(pre-training)和?微調(fune-tuning)階段。
????????預訓練階段一般會在超大規模的語料上,采用無監督(unsupervised)或者弱監督(weak-supervised)的方式訓練模型,期望模型能夠獲得語言相關的知識,比如句法,語法知識等等。經過超大規模語料的”洗禮”,預訓練模型往往會是一個Super模型,一方面體現在它具備足夠多的語言知識,一方面是因為它的參數規模很大。
????????微調階段是利用預訓練好的模型,去定制化地訓練某些任務,使得預訓練模型”更懂”這個任務。例如,利用預訓練好的模型繼續訓練文本分類任務,將會獲得比較好的一個分類結果,直觀地想,預訓練模型已經懂得了語言的知識,在這些知識基礎上去學習文本分類任務將會事半功倍。利用預訓練模型去微調的一些任務(例如前述文本分類)被稱為下游任務(down-stream)。
1-3 BERT的原理
????????從BERT的全稱,Bidirectional Encoder Representation from Transformer(來自Transformer的雙向編碼器表征),可以看出BERT是基于Transformer模型的,只是其中的編碼器。輸入一個句子,Transformer的編碼器會輸出句子中每個單詞的向量表示。而雙向則是由于Transformer編碼器是雙向的。它的輸入是完整的句子,在指定某個Token時,BERT已經讀入了它兩個方向上的所有單詞。舉個例來理解BERT是如何從Transformer中得到雙向編碼表示的。
????????假設我們有一個句子A:He got bit by Python,現在我們把這個句子輸入Transformer并得到了每個單詞的上下文表示(嵌入表示)作為輸出。Transformer的編碼器通過多頭注意力機制理解每個單詞的上下文,然后輸出每個單詞的嵌入向量。如下圖所示,我們輸入一個句子到Transformer的編碼器,它輸出句子中每個單詞的上下文表示。下圖中代表單詞He的向量表示,每個單詞向量表示的大小應當于每個編碼器隱藏層的大小。假設編碼器層大小為768,那么單詞的向量表示大小也就是768。
1-4?BERT的參數
????????BERT初期有兩個版本,分為base版和large版本。base版一共有110M參數,large版有340M的參數,兩個版本的BERT的參數量都是上億的。
????????L:Transformer blocks 層數;H:hidden size?;A:the number of self-attention heads
?2.BERT預訓練任務
?????????Bert是Transformer的encoder部分,使用大量的未標記文本數據進行預訓練,從而學習并掌握某種語言的表達形式。結構上使用了基于多頭注意力機制的transformer,訓練中采取兩種不同的訓練方式:(Masked Language Model)隱蔽語言模型、(Next Sentence Prediction)下一結構預測。其中雙向主要體現在bert的訓練任務一中:隱蔽語言模型。
2-1?Masked Language Model
????????Masked LM 可以形象地稱為完形填空問題,隨機掩蓋掉每一個句子中15%的詞,用其上下文來去判斷被蓋住的詞原本應該是什么。隨機Mask語料中15%的Token,然后將masked token位置的最終隱層向量送入softmax,來預測masked token。?舉例來說,有這樣一個未標注句子 my dog is hairy ,我們可能隨機選擇了hairy進行遮掩,就變成 my dog is [mask] ,訓練模型去預測 [mask] 位置的詞,使預測出 hairy的可能性最大,在這個過程中就將上下文的語義信息學習并體現到模型參數中。
????????而在下游的NLP任務fine-tuning階段中不存被Mask的詞,為了和后續任務保持一致,作者按一定比例在需要預測的詞的位置上輸入了原詞或輸入了某個隨機的詞。[MASK]通過attention均結合了左右上下文的信息,這體現了雙向。以下是MASK策略:
????????在任何一個詞都有可能是被替換掉的條件下,強迫模型在編碼當前時刻不能太依賴于當前的詞,而是要考慮它的上下文,甚至根據上下文進行糾錯。所以訓練預料中有必須正確的信息(10%)、未知的信息(80% MASK,使模型具有預測能力)、錯誤的信息(加入噪聲10%,使模型具有糾錯能力),模型才能獲取全局全量的信息。
2-2?Next sentence prediction
???????很多下游任務(QA和natural language inference)都是基于兩個句子之間關系的理解,基于此項任務,為了增強模型對句子之間關系的理解能力。?所以預測句子關系,判斷兩個句子之間是否是有關聯,在訓練過程中,BERT會抽全50%有關聯的句子(這里的句子是指有聯系的Token序列),百分之50的概率隨機抽選兩無關的句子,然后讓BERT模型判斷這兩個句子是否相關。其輸入形式是,開頭是一個特殊符號[CLS],然后兩個句子之間用[SEP]隔斷:
Input = [CLS] the man went to [MASK] store [SEP]he bought a gallon [MASK] milk [SEP]
Label = IsNext
Input = [CLS] the man [MASK] to the store [SEP]penguin [MASK] are flight ##less birds[SEP]
Label = NotNext
3.BERT的輸入和輸出
3-1 BERT的輸入
????????在把數據喂給BERT之前,通過下面三個嵌入層將輸入轉換為嵌入向量:詞嵌入(Token embedding);段嵌入(Segment embedding);位置嵌入(Position embedding)。
? ? ? ? 以下面句子為例,展現三種嵌入向量的表示。
Sentence A: Paris is a beautiful city. Sentence B: I love Paris.1.Token Embedding(詞嵌入)
????????表示的是詞向量,既可以是原始詞向量(源碼中是token在詞匯表中對應的索引),也可以是經過word2vector或者是glove等模型處理后的靜態向量。在實際代碼實現中,輸入文本在送入token embeddings 層之前要先進行tokenization處理。此外,兩個特殊的token會被插入到tokenization的結果的開頭 ([CLS])和結尾 ([SEP])
? ? ? ? 第一步:使用使用WordPiece分詞器分詞。
#第一步:使用WordPiece分詞器分詞 tokens = [Paris, is, a, beautiful, city, I, love, Paris]? ? ? ? 第二步:在一個句子前面,添加[CLS]標記。
tokens = [ [CLS], Paris, is, a, beautiful, city, I, love, Paris]? ? ? ? 第三步:在每個句子的結尾,添加[SEP]標記。
tokens = [ [CLS], Paris, is, a, beautiful, city, [SEP], I, love, Paris, [SEP]]? ? ? ? 特別說明:
????????????????[CLS]標記只加在第一個句子前面,而[SEP]標記加到每個句子末尾。
??????[CLS]標記用于分類任務,而[SEP]標記用于表示每個句子的結尾。
????????在把所有的標記喂給BERT之前,我們使用一個叫作標記嵌入的嵌入層轉換這些標記為嵌入向量。這些嵌入向量的值會在訓練過程中學習。經過學習,得到了每個token的詞嵌入向量。
2.Segment Embedding (段嵌入)
? ? ? ? 段嵌入用來區別兩種句子。因為Bert中存在著兩個任務,一個是隱藏語言模型,另一個是預測句子關系,所以在輸入時需要區分兩個句子。?如果輸入數據由兩個句子拼接而成,如果詞語是屬于第一個句子A,那么該標記會映射到嵌入;反之屬于句子 B,則映射到嵌入。
??????如果輸入僅僅只有一個句子,那么它的segment embedding只會映射到?。?
3.Position Embedding(位置編碼)?
????????學習出來的embedding向量。與Transformer不同,Transformer中是預先設定好的值。
4.最終表示
? ? ? ? 如下圖所示,首先我們將給定的輸入序列分詞為標記列表,然后喂給標記嵌入層,片段嵌入層和位置嵌入層,得到對應的嵌入表示。然后,累加所有的嵌入表示作為BERT的輸入表示。
3-2?BERT的輸出
???????bert模型的輸出可以包括四個:
? ? ? ?1.?last_hidden_state
????????torch.FloatTensor類型的,最后一個隱藏層的序列的輸出。大小是(batch_size, sequence_length, hidden_size) sequence_length是我們截取的句子的長度,hidden_size是768。
????????2.pooler_output
????????torch.FloatTensor類型的,[CLS]的這個token的輸出,輸出的大小是(batch_size, hidden_size)。
? ? ? ? 3.hidden_states
????????tuple(torch.FloatTensor)這是輸出的一個可選項,如果輸出,需要指定config.output_hidden_states=True,它也是一個元組,它的第一個元素是embedding,其余元素是各層的輸出,每個元素的形狀是(batch_size, sequence_length, hidden_size)。
????????4.attentions
????????這也是輸出的一個可選項,如果輸出,需要指定config.output_attentions=True,它也是一個元組,它的元素是每一層的注意力權重,用于計算self-attention heads的加權平均值。
4.BERT代碼?
????????Transformers(以前稱為pytorch-transformers和pytorch-pretrained-bert)提供用于自然語言理解(NLU)和自然語言生成(NLG)的最先進的模型(BERT,GPT-2,RoBERTa,XLM,DistilBert,XLNet,CTRL ...) ,擁有超過32種預訓練模型,支持100多種語言,并且在TensorFlow 2.0和PyTorch之間具有深厚的互操作性。我們借助Transformers來實現bert的調用。
import transformers #實例化bert模型 bert_model = transformers.BertModel.from_pretrained(pretrained_model_name_or_path = '/ssd/Spider/Baidu_NER/Pre_Model/chinese_roberta_wwm_large_ext/',output_hidden_states=True,output_attentions=True) #bert需要的三種輸入形式 def encoder(vocab_path,sentence):#將text_list embedding成bert模型可用的輸入形式tokenizer = transformers.BertTokenizer.from_pretrained(vocab_path)tokenizer = tokenizer(sentence,return_tensors='pt' # 返回的類型為pytorch tensor)input_ids = tokenizer['input_ids']token_type_ids = tokenizer['token_type_ids']attention_mask = tokenizer['attention_mask']return input_ids,token_type_ids,attention_mask sentence = "中華人民共和國萬歲" #生成三種bert需要的輸入形式 input_ids,token_type_ids,attention_mask = encoder(vocab_path="/ssd/Spider/Baidu_NER/Pre_Model/chinese_roberta_wwm_large_ext/vocab.txt",sentence = sentence) #調用bert模型 sentence_outputs = bert_model(input_ids,token_type_ids,attention_mask)? ? ? ? ? 如下圖所示:
? ? ? ? input_ids表示的是分詞后在token中添加了[CLS]和[SEP]標記之后的id表示。token_types_ids則表示的是Segment Embeddings ,如果輸入數據由兩個句子拼接而成,如果詞語是屬于第一個句子,則Segment Embeddings 對應的位置是0,如果屬于第二個句子,則segment Embeddings對應的位置為1。?
總結
以上是生活随笔為你收集整理的【深度学习】预训练语言模型-BERT的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 统计学_第一章_统计和数据
- 下一篇: 软考高级-系统架构师-软件工程