日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BERT论文总结

發(fā)布時間:2025/3/8 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BERT论文总结 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本次分享和總結自己所讀的論文 BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding,也就是大名鼎鼎的 BERT,網(wǎng)上對這篇論文的解讀非常多,在此就提下自己淺薄的見解。論文鏈接 BERT[1]

論文動機以及創(chuàng)新點

  • 預訓練的語言模型已經(jīng)在自然語言處理的各項任務上取得了有目共睹的效果。

  • 目前有兩種途徑應用語言模型的預訓練 feature-base: 就是將預訓練后語言模型作為特征提取器,供下游模型使用。例如 ELMo fine-tune:將預訓練后的語言模型經(jīng)過微調(diào),使之適應下游任務,保留預訓練后的參數(shù)等,直接應用到下游任務中。

  • 無論是 feature-base 還是 fine-tune,在預訓練階段都是采用單向的語言模型來學習語言表征。這種“單向”嚴重限制了模型的能力,特別是在 fine-tune 中。例如在 QA 任務中,我們需要結合上下兩個方向的文章內(nèi)容來找答案。

  • 為了解決單向的缺陷,論文中提出了兩種預訓練方法,分別是 “Masked Language model” 和 "next sentence prediction"

  • 論文中同樣用到了 transformer,不過是雙向深層的 transformer encoder。

  • 特別注意:這里面講的雙向并不是類似于 bi-lstm 上的時序上的雙向,而是指語義上的方向,代碼上是可以并行運行的。

  • BERT

    輸入表征

    在這里插入圖片描述
    • Token Embeddings: 表示詞的 embedding

    • Segment Embedding:表示詞所在句子的 index Embedding

    • Position Embedding:表示詞所在位置的 index Embedding

    這里無所謂輸入的一對句子和單句,如果一對句子,則用 sep 連接即可。

    預訓練

    Masked LM

    直觀上,雙向網(wǎng)絡肯定比單向網(wǎng)絡更有威力。對于標準的語言模型,只能是從左向右,或從右向左的單向預測,為了能雙向的預訓練,論文中提出了類似于“完形填空”的方式來雙向的預訓練語言模型。簡單來說,就是把一段句子隨機的 15%詞扣除掉(用 mask token 替換),然后在網(wǎng)絡中被扣除對應位置出做 softmax 預測扣除出去的詞。是不是于 word2vec 的 BOW 訓練方式有異曲同工之妙。但是這樣做有兩點不妥:

    • pre_train 階段和 fine_tune 階段,存在一些 mismatch,在 fine_tune 時,是沒有 mask token 的,論文中是這樣解決的:在預訓練階段,對于隨機扣除的 15%的 token,采取不同的替換策略:1、80%概率用 mask token 替換 2、10%概率隨機用文章出現(xiàn)過的詞替換 3、10%概率不變,使用原來的詞

    • 因為預測的只有 15%的詞,故相對標準的語言模型,收斂較慢。

    注意:Masked LM 模型在被扣除詞的位置處的輸入是 mask token 或者被替換的詞,而不是原本的詞。

    Next Sentence Prediction

    對于一些任務,需要學習到句子間的關系,例如 QA、NLI。這種句子間關系,語言模型是不能很好的學習到的。因此論文中提出了 Next Sentence Prediction 任務。簡單來說,就是從單語料庫中隨機選擇兩條句子 A、B。如果句子 B 是句子 A 的下一句,則 label 為 IsNext,反正為 NotNext。訓練集中,有 50%的樣本是 IsNext,50%樣本是 NotNext,并且 NotNext 的樣本是隨機選取的。論文中說該分類模型達到 97%-98%的準確率。注意:

    • Masked LM 是捕捉詞之間的關系

    • Next Sentence Prediction 是捕捉句子之間的關系

    • Masked LM 和 Next Sentence Prediction 是放在一起訓練的

    fine-tune

    不同類型的任務需要對模型做不同的修改,但是修改都是非常簡單的,最多加一層神經(jīng)網(wǎng)絡即可。如下圖所示

    ELMo、openAI GPT、BERT 比較

    在這里插入圖片描述
    • ELMo 模型 是有兩個方向相反的 LSTM 網(wǎng)絡組合而成 單向的語言模型做預訓練。Feature-base 方式

    • OpenAI GPT 1、是 transform decoder,圖中每一層所有的 Trm 是一個 transformer 層,每層間做 self attention(masked,只和之前的做 self attention),然后將輸出結果喂給下一層,這就相當于下一層的一個 trm 會和上一層該位置之前的 trm 做了連接,后面的信息被屏蔽(代碼實現(xiàn)上用一個 mask 矩陣屏蔽)。2、單向的語言模型做預訓練 3、fine-tune 方式

    • BERT 1、同 OpenAI GPT,只不過變成雙向深層 transformer encoder,同樣每層之間做 self attention,然后將輸出結果喂給下一層,這就相當于與上一層前后兩個方向的 Trm 做了連接。2、Masked LM 和 Next Sentence Prediction 做預訓練 3、fine-tune 方式。

    實驗部分

    實驗部分是一片大好咯,各種牛逼。論文中也分析了不加 Masked LM 或不加 Next Sentence Prediction 預訓練對模型結果的影響如下

    關鍵代碼分析

    Masked token、Next Sentence

    # MASK LM n_pred = min(max_pred, max(1, int(round(len(input_ids) * 0.15)))) # 15 % of tokens in one sentence cand_maked_pos = [i for i, token in enumerate(input_ids)if token != word_dict['[CLS]'] and token != word_dict['[SEP]']] shuffle(cand_maked_pos) masked_tokens, masked_pos = [], [] for pos in cand_maked_pos[:n_pred]:masked_pos.append(pos)masked_tokens.append(input_ids[pos])if random() < 0.8: # 80%input_ids[pos] = word_dict['[MASK]'] # make maskelif random() < 0.5: # 10%index = randint(0, vocab_size - 1) # random index in vocabularyinput_ids[pos] = word_dict[number_dict[index]] # replaceif tokens_a_index + 1 == tokens_b_index and positive < batch_size/2:batch.append([input_ids, segment_ids, masked_tokens, masked_pos, True]) # IsNextpositive += 1 elif tokens_a_index + 1 != tokens_b_index and negative < batch_size/2:batch.append([input_ids, segment_ids, masked_tokens, masked_pos, False]) # NotNextnegative += 1

    ScaledDotProductAttention

    def forward(self, Q, K, V, attn_mask): ## self attention 操作scores = torch.matmul(Q, K.transpose(-1, -2)) / np.sqrt(d_k) # scores : [batch_size x n_heads x len_q(=len_k) x len_k(=len_q)]scores.masked_fill_(attn_mask, -1e9) #,注意把 padding部分的注意力去掉attn = nn.Softmax(dim=-1)(scores)context = torch.matmul(attn, V)return context, attn

    MultiHeadAttention

    class MultiHeadAttention(nn.Module):def __init__(self):super(MultiHeadAttention, self).__init__()self.W_Q = nn.Linear(d_model, d_k * n_heads)self.W_K = nn.Linear(d_model, d_k * n_heads)self.W_V = nn.Linear(d_model, d_v * n_heads)def forward(self, Q, K, V, attn_mask):# q: [batch_size x len_q x d_model], k: [batch_size x len_k x d_model], v: [batch_size x len_k x d_model]residual, batch_size = Q, Q.size(0)# (B, S, D) -proj-> (B, S, D) -split-> (B, S, H, W) -trans-> (B, H, S, W)q_s = self.W_Q(Q).view(batch_size, -1, n_heads, d_k).transpose(1,2) # q_s: [batch_size x n_heads x len_q x d_k]k_s = self.W_K(K).view(batch_size, -1, n_heads, d_k).transpose(1,2) # k_s: [batch_size x n_heads x len_k x d_k]v_s = self.W_V(V).view(batch_size, -1, n_heads, d_v).transpose(1,2) # v_s: [batch_size x n_heads x len_k x d_v]attn_mask = attn_mask.unsqueeze(1).repeat(1, n_heads, 1, 1) # attn_mask : [batch_size x n_heads x len_q x len_k]# context: [batch_size x n_heads x len_q x d_v], attn: [batch_size x n_heads x len_q(=len_k) x len_k(=len_q)]context, attn = ScaledDotProductAttention()(q_s, k_s, v_s, attn_mask)context = context.transpose(1, 2).contiguous().view(batch_size, -1, n_heads * d_v) # context: [batch_size x len_q x n_heads * d_v]output = nn.Linear(n_heads * d_v, d_model)(context)return nn.LayerNorm(d_model)(output + residual), attn # output: [batch_size x len_q x d_model]

    BERT

    class PoswiseFeedForwardNet(nn.Module):def __init__(self):super(PoswiseFeedForwardNet, self).__init__()self.fc1 = nn.Linear(d_model, d_ff)self.fc2 = nn.Linear(d_ff, d_model)def forward(self, x):# (batch_size, len_seq, d_model) -> (batch_size, len_seq, d_ff) -> (batch_size, len_seq, d_model)return self.fc2(gelu(self.fc1(x)))class EncoderLayer(nn.Module):def __init__(self):super(EncoderLayer, self).__init__()self.enc_self_attn = MultiHeadAttention()self.pos_ffn = PoswiseFeedForwardNet()def forward(self, enc_inputs, enc_self_attn_mask):enc_outputs, attn = self.enc_self_attn(enc_inputs, enc_inputs, enc_inputs, enc_self_attn_mask) # enc_inputs to same Q,K,Venc_outputs = self.pos_ffn(enc_outputs) # enc_outputs: [batch_size x len_q x d_model]return enc_outputs, attnclass BERT(nn.Module):def __init__(self):super(BERT, self).__init__()self.embedding = Embedding()self.layers = nn.ModuleList([EncoderLayer() for _ in range(n_layers)])self.fc = nn.Linear(d_model, d_model)self.activ1 = nn.Tanh()self.linear = nn.Linear(d_model, d_model)self.activ2 = geluself.norm = nn.LayerNorm(d_model)self.classifier = nn.Linear(d_model, 2)# decoder is shared with embedding layerembed_weight = self.embedding.tok_embed.weightn_vocab, n_dim = embed_weight.size()self.decoder = nn.Linear(n_dim, n_vocab, bias=False)self.decoder.weight = embed_weightself.decoder_bias = nn.Parameter(torch.zeros(n_vocab))def forward(self, input_ids, segment_ids, masked_pos):output = self.embedding(input_ids, segment_ids)enc_self_attn_mask = get_attn_pad_mask(input_ids, input_ids)for layer in self.layers:output, enc_self_attn = layer(output, enc_self_attn_mask)# output : [batch_size, len, d_model], attn : [batch_size, n_heads, d_mode, d_model]# it will be decided by first token(CLS)h_pooled = self.activ1(self.fc(output[:, 0])) # [batch_size, d_model]logits_clsf = self.classifier(h_pooled) # [batch_size, 2]masked_pos = masked_pos[:, :, None].expand(-1, -1, output.size(-1)) # [batch_size, maxlen, d_model]h_masked = torch.gather(output, 1, masked_pos) # masking position [batch_size, len, d_model]h_masked = self.norm(self.activ2(self.linear(h_masked)))logits_lm = self.decoder(h_masked) + self.decoder_bias # [batch_size, maxlen, n_vocab]return logits_lm, logits_clsf

    參考資料

    [1]

    BERT: https://arxiv.org/pdf/1810.04805.pdf

    關于本站

    “機器學習初學者”公眾號由是黃海廣博士創(chuàng)建,黃博個人知乎粉絲23000+,github排名全球前110名(32000+)。本公眾號致力于人工智能方向的科普性文章,為初學者提供學習路線和基礎資料。原創(chuàng)作品有:吳恩達機器學習個人筆記、吳恩達深度學習筆記等。

    往期精彩回顧

    • 那些年做的學術公益-你不是一個人在戰(zhàn)斗

    • 適合初學者入門人工智能的路線及資料下載

    • 吳恩達機器學習課程筆記及資源(github標星12000+,提供百度云鏡像)

    • 吳恩達深度學習筆記及視頻等資源(github標星8500+,提供百度云鏡像)

    • 《統(tǒng)計學習方法》的python代碼實現(xiàn)(github標星7200+)

    • 精心整理和翻譯的機器學習的相關數(shù)學資料

    • 首發(fā):深度學習入門寶典-《python深度學習》原文代碼中文注釋版及電子書

    備注:加入本站微信群或者qq群,請回復“加群

    加入知識星球(4300+用戶,ID:92416895),請回復“知識星球

    總結

    以上是生活随笔為你收集整理的BERT论文总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。