bert的簡單回顧
google發布的**《pre-training of deep bidirectional transformers for language understanding》,提到的bert模型重新整理了自然語言處理的11項記錄。算是nlp的里程碑事件,也開始了大公司之間的資料和算力的裝備競賽。放一篇比較好的中文**翻譯。
bert在閱讀理解領域帶了很大的進展,在bert的出現之前最好的模型基本都是使用的seq2seq方法,分五步走,相當複雜。bert出現後,只需要在bert後面加上簡單的網路就可達到特別好的效果。所以理解bert用於閱讀理解是非常重要的。
下圖是squad2.0的排名,截止到19年7月1日。
bert base的引數
對於英文閱讀理解任務來說,可以選擇base版或者large版,對於中文來說只有base版。bert本身用的是transformer的encoder部分,只是堆了很多層,換了個訓練任務而已。
層參數量
佔比multiheadselfattention
2362368*12
27.55%
tokenembedding
15.77%
feedforward
4722432*12
55.08%
positionembedding
0.38%
masked language model
簡單來說是masked language model,分為詞語級別和句子級別。對於閱讀任務來說需要問題和文件之間的關係來得到最後的答案。這兩個任務對閱讀理解都很有幫助,尤其是第二個任務。下圖具體展示了預訓練時候這兩個任務的具體做法。
task specific-models
實際在用bert的時候需要根據下游任務在bert後面接上不同的網路,然後可以只訓練接的網路的引數,也可以解凍bert最後幾層一起訓練,這就是遷移學習,跟cv領域的一致。bert的四種主流應用場景:
bert應用於閱讀理解
在squad,給出了問題和包含答案的段落,任務是**答案文字的起始和結束位置(答案的跨度,span)。
bert首先在問題前面新增special classification token[cls]標記,然後問題和段落連在一起,中間使用special tokens[sep]分開。序列通過token embedding、segment embedding 和 positional embedding輸入到bert。最後,通過全連線層和softmax函式將bert的最終隱藏狀態轉換為答案跨度的概率。
bert的輸入和輸出
輸入:input_ids, input_mask, segment_ids
輸出:start_position, end_position
起始和結束位置的計算
example = squadexample( qas_id=qas_id,
question_text=question_text,
doc_tokens=doc_tokens,
orig_answer_text=orig_answer_text,
start_position=start_position,
end_position=end_position)
複製**
起始和結束位置的重新標註,這個是因為分詞的原因。即便是bert中文版是按照字的,但是某些英文單詞、年份還是會被單獨分開,如1990等,但是標註的時候為了統一,是按照字元的個數來算的,就是不分詞,所以在處理的時候要重新改寫起始和結束位置,例如下面這段文字,原本起始位置是41,但是分詞之後改為了38,注意這對生成的結果沒有影響。
由於bert的輸入是這樣拼接的:
[cls]question[sep]context[sep]
複製**
所以最後輸入模型的起始位置還要加上question的長度和([cls],[sep]),還是以上面兩個為例。
第乙個例子:"question": "範廷頌是什麼時候被任為主教的?",長度為15,加上[cls]和[sep],就是17,再加上原始的起始位置30,最後得到47.
第二個例子:"question": "2023年,範廷頌擔任什麼職務?",長度為13,加上[cls]和[sep],就是15,再加上原始的起始位置38,最後得到53.
和debug的結果一致
bert的embedding層
理解了bert的輸入,我們看一下bert的embedding層,主要包括三個部分,最後相加就ok了。
bert的token embedding
也就是word embeddings,bert的分詞用的是sub words的形式,會把詞拆分成一些字詞來減少oov。
bert的segment embedding
segment embeddings用來區分兩段話,用於句子級別的mask任務,直接加0,1區分,也是最簡單的實現。
bert的position embedding
對每個輸入的位置進行編碼,新增位置資訊,transformer是直接表示的,bert是訓練來的。
小結一下
token embeddings 形狀為(1, n, 768),就是word embedding,對於中文是字。
segment embeddings 形狀為 (1, n, 768) ,用來區分兩個句子
position embeddings 形狀為 (1, n, 768),主要是為transfomer提供位置資訊。
最後把三個加起來就是bert的embedding層了(ps.直接加起來確實有點簡單粗暴哈)。
bert閱讀理解標準模型
從文字embedding層向量後,輸入到bert預訓練模型裡面(transformer的encoder),得到bert的深層表示,再接上網路就可以得到輸出了。這裡先上**:
from pytorch_pretrained_bert.modeling import bertmodel, bertpretrainedmodel
import torch
from torch import nn
from torch.nn import crossentropyloss
class bert_qa(bertpretrainedmodel):
def __init__(self, config, num_labels):
super(bertorigin, self).__init__(config)
self.num_labels = num_labels
self.bert = bertmodel(config)
self.dropout = nn.dropout(config.hidden_dropout_prob)
self.classifier = nn.linear(config.hidden_size, num_labels)
def forward(self, input_ids, token_type_ids=none, attention_mask=none, labels=none):
sequence_output, pooled_output = self.bert(input_ids, token_type_ids, attention_mask, output_all_encoded_layers=false)
logits = self.classifier(sequence_output) # (b, t, 2)
start_logits, end_logits = logits.split(1, dim=-1)# ((b, t, 1),(b, t, 1))
start_logits = start_logits.squeeze(-1) # (b, t)
end_logits = end_logits.squeeze(-1) # (b, t)
複製**pooled_output: [batch_size, hidden_size=768], 取了最後一層transformer的輸出結果的第乙個單詞[cls]的hidden states
sequence_output:[batch_size, sequence_length, hidden_size=768],最後乙個encoder層的輸出
上面**用的是bert的squad裡面的做法得到start_logits和end_logits,就是把sequence_output接全連線轉換hidden_size維度為2,然後split輸出,最後的loss就是兩個分別計算loss然後平均。
總結bert模型太大了,即便是在**的時候也是接近400m,回到開頭,我還是比較期望有小而美的模型實現的
bert只支援單句子最長512的輸入,這是有transformer本身的attention決定的,再大google也訓練不動。解決方案是要麼截斷,要麼劃分句子後拼接bert的表示,transformer xl說可以緩解這個問題,還沒細看
bert預設的輸出的最大答案長度為30,實際用的時候最好設成300,來應對長答案
bert中的sep 語言模型 BERT
今天我們想到 nlp 就會想到 bert,在 nlp 領域中 bert 到處屠榜。bert 主要應用於自然語言處理中的預訓練。這裡想說一件有趣的事,就是當下比較火的自然語言處理模型如 elmo 和 bert 都是動畫片芝麻街中角色。那麼什麼是 bert 呢?我們先從字面上解釋一下什麼是 bert。我...
BERT原理詳解
之前的文章從attention講解到了transformer,本文將會針對目前大熱的bert進行講解,bert的內部結構其實就是多個transformer 的encoder,如果您對transformer並不了解,請參閱我之前的博文。從創新的角度來看,bert其實並沒有過多的結構方面的創新點,其和g...
BERT原理詳解
網上關於bert的模型講的好的很多 參考bert模型學習與分析 谷歌bert模型深度解析 徹底搞懂bert 這裡簡單描述一下bert和openai gpt模型區別與聯絡 bert和gpt 都是使用了transformer結構,transform的encoder和decoder是有區別的,這也是ber...