天天看點

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

一文讀懂BERT(原理篇)

2018年的10月11日,Google釋出的論文《Pre-training of Deep Bidirectional Transformers for Language Understanding》,成功在 11 項 NLP 任務中取得 state of the art 的結果,赢得自然語言處理學界的一片贊譽之聲。

本文是對近期關于BERT論文、相關文章、代碼進行學習後的知識梳理,僅為自己學習交流之用。因筆者精力有限,如果文中因引用了某些文章觀點未标出處還望作者海涵,也希望各位一起學習的讀者對文中不恰當的地方進行批評指正。

1)資源梳理

  • BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding
  • 論文原文:

    BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding

  • 官方代碼和預訓練模型

    Github: https://github.com/google-research/bert

  • Google AI Blog:

    Open Sourcing BERT: State-of-the-Art Pre-training for Natural Language Processing

  • 第三方代碼
    1. pytorch-pretrained-BERT

      Google官方推薦的PyTorch BERB版本實作,可加載Google預訓練的模型:PyTorch version of Google AI’s BERT model with script to load Google’s pre-trained models

    2. BERT-pytorch

      另一個Pytorch版本實作:Google AI 2018 BERT pytorch implementation

    3. BERT-tensorflow

      Tensorflow版本:BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding

    4. bert-chainer

      Chanier版本: Chainer implementation of “BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding”

    5. bert-as-service

      将不同長度的句子用BERT預訓練模型編碼,映射到一個固定長度的向量上:Mapping a variable-length sentence to a fixed-length vector using pretrained BERT model

      進一步是否可以做一個句子相似度計算服務?有沒有同學一試?

    6. bert_language_understanding

      BERT實戰:Pre-training of Deep Bidirectional Transformers for Language Understanding: pre-train TextCNN

    7. sentiment_analysis_fine_grain

      BERT實戰,多标簽文本分類,在 AI Challenger 2018 細粒度情感分析任務上的嘗試:Multi-label Classification with BERT; Fine Grained Sentiment Analysis from AI challenger

    8. BERT-NER

      BERT實戰,命名實體識别: Use google BERT to do CoNLL-2003 NER !

    9. BERT-keras

      Keras版: Keras implementation of BERT with pre-trained weights

    10. tbert

      PyTorch port of BERT ML model

2)NLP發展史

關于NLP發展史,特别推薦weizier大佬的NLP的巨人肩膀。學術性和文學性都很棒,縱覽NLP近幾年的重要發展,對各算法如數家珍,深入淺出,思路清晰,文不加點,一氣呵成。

現對NLP發展脈絡簡要梳理如下:

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)
  • 2001 - Neural language models(神經語言模型)
  • 2008 - Multi-task learning(多任務學習)
  • 2013 - Word embeddings(詞嵌入)
  • 2013 - Neural networks for NLP(NLP神經網絡)
  • 2014 - Sequence-to-sequence models
  • 2015 - Attention(注意力機制)
  • 2015 - Memory-based networks(基于記憶的網絡)
  • 2018 - Pretrained language models(預訓練語言模型)

2001 - 神經語言模型

第一個神經語言模型是Bengio等人在2001年提出的前饋神經網絡,如圖所示:

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

這個模型将從表C中查找到的n個單詞作為輸入向量表征。這種向量被現在的學者們稱做“詞嵌入”。這些詞嵌入級聯後被輸入到一個隐藏層中,該隐藏層的輸出又被輸入到softmax層。更多關于模型的資訊。

語言模組化通常是應用RNN時的第一步,是一種非監督學習形式。盡管它很簡單,但卻是本文後面讨論的許多技術發展的核心:

  • 詞嵌入:word2vec 的目标是簡化語言模組化。
  • sequence-to-sequence 模型:這種模型通過一次預測一個單詞生成一個輸出序列。
  • 預訓練語言模型:這些方法使用來自語言模型的表述進行遷移學習。

反過來講,這意味着近年來 NLP 的許多重要進展都可以歸結為某些形式的語言模組化。為了“真正”了解自然語言,僅僅從文本的原始形式中學習是不夠的。我們需要新的方法和模型。

2008- 多任務學習

多任務學習是在多個任務上訓練的模型之間共享參數的一種通用方法。在神經網絡中,可以通過給不同層施以不同的權重,來很容易地實作多任務學習。多任務學習的概念最初由Rich Caruana 在1993年提出,并被應用于道路跟蹤和肺炎預測(Caruana,1998)。直覺地說,多任務學習鼓勵模型學習對許多任務有用的表述。這對于學習一般的、低級的表述形式、集中模型的注意力或在訓練資料有限的環境中特别有用。詳情請看這篇文章

在2008年,Collobert 和 Weston 将多任務學習首次應用于 NLP 的神經網絡。在他們的模型中,查詢表(或單詞嵌入矩陣)在兩個接受不同任務訓練的模型之間共享,如下面的圖所示。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

2013- 詞嵌入

用稀疏向量表示文本,即所謂的詞袋模型在 NLP 有着悠久的曆史。正如上文中介紹的,早在 2001年就開始使用密集向量表示詞或詞嵌入。Mikolov等人在2013年提出的創新技術是通過去除隐藏層,逼近目标,進而使這些單詞嵌入的訓練更加高效。雖然這些技術變更本質上很簡單,但它們與高效的word2vec配合使用,便能使大規模的詞嵌入訓練成為可能。

Word2vec有兩種風格,如下面的圖所示:連續字袋 CBOW 和 skip-gram。不過他們的目标不同:一個是根據周圍的單詞預測中心單詞,而另一個則相反。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

雖然這些嵌入在概念上與使用前饋神經網絡學習的嵌入在概念上沒有差別,但是在一個非常大的語料庫上訓練之後,它們就能夠捕獲諸如性别、動詞時态和國家-首都關系等單詞之間的特定關系,如下圖所示。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

2013 - NLP 神經網絡

2013 年和 2014 年是 NLP 問題開始引入神經網絡模型的時期。使用最廣泛的三種主要的神經網絡是:循環神經網絡、卷積神經網絡和遞歸神經網絡。

循環神經網絡(RNNs) 循環神經網絡是處理 NLP 中普遍存在的動态輸入序列的一個最佳的技術方案。Vanilla RNNs (Elman,1990)很快被經典的長-短期記憶網絡(Hochreiter & Schmidhuber,1997)所取代,它被證明對消失和爆炸梯度問題更有彈性。在 2013 年之前,RNN 仍被認為很難訓練;Ilya Sutskever 的博士論文為改變這種現狀提供了一個關鍵性的例子。下面的圖對 LSTM 單元進行了可視化顯示。雙向 LSTM(Graves等,2013)通常用于處理左右兩邊的上下文。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

卷積神經網絡(CNNs) 卷積神經網絡本來是廣泛應用于計算機視覺領域的技術,現在也開始應用于語言(Kalchbrenner等,2014;Kim等,2014)。文本的卷積神經網絡隻在兩個次元上工作,其中濾波器(卷積核)隻需要沿着時間次元移動。下面的圖顯示了NLP中使用的典型 CNN。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

卷積神經網絡的一個優點是它們比 RNN 更可并行化,因為其在每個時間步長的狀态隻依賴于本地上下文(通過卷積運算),而不是像 RNN 那樣依賴過去所有的狀态。使用膨脹卷積,可以擴大 CNN 的感受野,使網絡有能力捕獲更長的上下文(Kalchbrenner等,2016)。CNN 和 LSTM 可以組合和疊加(Wang等,2016),卷積也可以用來加速 LSTM(Bradbury等, 2017)。

遞歸神經網絡 RNN 和 CNN 都将語言視為一個序列。然而,從語言學的角度來看,語言本質上是階層化的:單詞被組合成高階短語和從句,這些短語和從句本身可以根據一組生産規則遞歸地組合。将句子視為樹而不是序列的語言學啟發思想産生了遞歸神經網絡(Socher 等人, 2013),如下圖所示

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

遞歸神經網絡從下到上建構序列的表示,這一點不同于從左到右或從右到左處理句子的 RNN。在樹的每個節點上,通過組合子節點的結果來計算新的結果。由于樹也可以被視為在 RNN 上強加不同的處理順序,是以 LSTM 自然地也被擴充到樹上(Tai等,2015)。

RNN 和 LSTM 可以擴充到使用層次結構。單詞嵌入不僅可以在本地學習,還可以在文法語境中學習(Levy & Goldberg等,2014);語言模型可以基于句法堆棧生成單詞(Dyer等,2016);圖卷積神經網絡可以基于樹結構運作(Bastings等,2017)。

2014-sequence-to-sequence 模型

2014 年,Sutskever 等人提出了 sequence-to-sequence 模型。這是一個使用神經網絡将一個序列映射到另一個序列的通用架構。在該架構中,編碼器神經網絡逐符号處理一個句子,并将其壓縮為一個向量表示;然後,一個解碼器神經網絡根據編碼器狀态逐符号輸出預測值,并将之前預測的符号作為每一步的輸入,如下圖所示。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

機器翻譯是對這個架構比較成功的應用。2016 年,谷歌宣布将開始用神經 MT 模型取代基于單片短語的 MT 模型(Wu等,2016)。根據 Jeff Dean 的說法,這意味着用 500 行神經網絡模型替換 50 萬行基于短語的MT代碼。

由于其靈活性,這個架構現在是自然語言生成任務的首選架構,其中不同的模型承擔了編碼器和解碼器的角色。重要的是,解碼器模型不僅可以解碼一個序列,而且可以解碼任意表征。例如,可以基于圖像生成标題(Vinyals等,2015)(如下圖所示)、基于表生成文本(Lebret等,2016)和基于應用程式中源代碼更改描述(Loyola等,2017)。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

sequence-to-sequence 學習甚至可以應用于 NLP 中輸出具有特定結構的結構化預測任務。為了簡單起見,輸出被線性化,如下面的圖所示,用于進行選區解析。神經網絡已經證明了在有足夠數量的訓練資料進行選區分析(Vinyals等,2015)和命名實體識别(Gillick等, 2016)的情況下,直接學習可以産生這種線性化輸出的能力。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

2015- 注意力機制

注意力機制(Bahdanau 等,2015)是神經網絡機器翻譯(NMT)的核心創新之一,也是使 NMT模型勝過經典的基于短語的MT系統的關鍵思想。sequence-to-sequence模型的主要瓶頸是需要将源序列的全部内容壓縮為一個固定大小的向量。注意力機制通過允許解碼器回頭檢視源序列隐藏狀态來緩解這一問題,然後将其權重平均作為額外輸入提供給解碼器,如下面的圖所示

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

注意力機制有很多不同的形式(Luong等,2015)。這裡有一個簡短的概述。注意力機制廣泛适用于任何需要根據輸入的特定部分做出決策的任務,并且效果不錯。它已被應用于一緻性解析(Vinyals等,2015)、閱讀了解(Hermann等,2015)和一次性學習(Vinyals等,2016)等諸多領域。輸入甚至不需要是一個序列,即可以包含其他表示,如圖像字幕(Xu等,2015),如下圖所示。注意力機制的一個額外的功能是,它提供了一種少見的功能,我們可以通過檢查輸入的哪些部分與基于注意力權重的特定輸出相關來了解模型的内部工作方式。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

2015 - 基于記憶的網絡

注意力機制可以看作是模糊記憶的一種形式。記憶由模型的隐藏狀态組成,模型選擇從記憶中檢索内容。研究者們提出了許多具有更明确記憶的模型。這些模型有不同的變體,如神經圖靈機(Graves等,2014)、記憶網絡(Weston等,2015)和端到端記憶網絡(Sukhbaatar等,2015)、動态記憶網絡(Kumar等,2015)、神經微分計算機(Graves等,2016)和循環實體網絡(Henaff等,2017)。

記憶的通路通常基于與目前狀态的相似度,類似于注意力,通常可以寫入和讀取。模型在如何實作和利用記憶體方面有所不同。例如,端到端記憶網絡多次處理輸入,并更新記憶以實作多個推理步驟。神經圖靈機也有一個基于位置的尋址,這允許他們學習簡單的計算機程式,如排序。基于記憶的模型通常應用于一些特定任務中,如語言模組化和閱讀了解。在這些任務中,長時間儲存資訊應該很有用。記憶的概念是非常通用的:知識庫或表可以充當記憶,而記憶也可以根據整個輸入或它的特定部分填充。

2018 - 預訓練語言模型

預訓練的詞嵌入與上下文無關,僅用于初始化模型中的第一層。一系列監督型任務被用于神經網絡的預訓練。相反,語言模型隻需要無标簽的文本;是以,訓練可以擴充到數十億個tokens, new domains, new languages。預訓練語言模型于 2015 年被首次提出(Dai & Le,2015);直到最近,它們才被證明在各種任務中效果還是不錯的。語言模型嵌入可以作為目标模型中的特征(Peters等,2018),或者使用語言模型對目标任務資料進行微調(Ramachandranden等,2017; Howard & Ruder,2018)。添加語言模型嵌入可以在許多不同的任務中提供比最先進的技術更大的改進,如下面的圖所示。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

預訓練的語言模型已經被證明可以用更少的資料進行學習。由于語言模型隻需要無标記的資料,是以對于标記資料稀缺的低資源語言尤其有用。

其他裡程碑事件

其他一些技術發展沒有上面提到的那樣流行,但仍然有廣泛的影響。

  • 基于字元的表示

    在字元上使用 CNN 或 LSTM 以獲得基于字元的詞表示的做法現在相當普遍,特别是對于形态資訊重要或有許多未知單詞的豐富的語言和任務,效果更加明顯。據我所知,序列标簽使用基于字元的表示(Lample 等人,2016;普蘭克等人,2016),可以減輕在計算成本增加的情況下必須處理固定詞彙表的需要,并支援完全基于字元的 NMT (Ling 等人, 2016;Lee 等人,2017)。

  • 對抗學習

    對抗學習方法已經在 ML 領域掀起了風暴,在 NLP 中也有不同形式的應用。對抗性的例子越來越被廣泛使用,它不僅是作為一種工具來探究模型和了解它們的失敗案例,而且也使自身更加魯棒(Jia & Liang, 2017)。(虛拟)對抗性訓練,即最壞情況擾動(Miyato 等人,2017)和領域對抗性損失(Ganin 等人, 2016;Kim 等人,2017),同樣可以使模型更加魯棒。生成對抗網絡(GANs)對于自然語言生成還不是很有效(Semeniuta 等人, 2018),但在比對分布時很有用(Conneau 等人, 2018)。

  • 強化學習

    強化學習已被證明對具有時間依賴性的任務有效,例如在訓練期間選擇資料(Fang 等人, 2017;Wu 等人, 2018)和模組化對話(Liu 等人, 2018)。RL 對于直接優化不可微的末端度量(如 ROUGE 或 BLEU)也有效,反而在彙總中優化替代損失(如交叉熵)(Paulus 等人, 2018;Celikyilmaz 等人,2018)和機器翻譯場景效果就不明顯了(Ranzato 等人,2016)。類似地,逆向強化學習在過于複雜而無法指定資料的情況下也很有用,比看圖說話任務(Wang 等人, 2018)。

3)BERT:一切過往, 皆為序章

Attention機制講解

attention是一種能讓模型對重要資訊重點關注并充分學習吸收的技術,它不算是一個完整的模型,應當是一種技術,能夠作用于任何序列模型中。本文較多引用了本篇文章思路,如感興趣可以跳轉學習。

Seq2Seq

在開始講解Attention之前,我們先簡單回顧一下Seq2Seq模型,傳統的機器翻譯基本都是基于Seq2Seq模型來做的,該模型分為encoder層與decoder層,并均為RNN或RNN的變體構成,如下圖所示:

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

在encode階段,第一個節點輸入一個詞,之後的節點輸入的是下一個詞與前一個節點的hidden state,最終encoder會輸出一個context,這個context又作為decoder的輸入,每經過一個decoder的節點就輸出一個翻譯後的詞,并把decoder的hidden state作為下一層的輸入。該模型對于短文本的翻譯來說效果很好,但是其也存在一定的缺點,如果文本稍長一些,就很容易丢失文本的一些資訊,為了解決這個問題,Attention應運而生。

Attention

Attention,正如其名,注意力,該模型在decode階段,會選擇最适合目前節點的context作為輸入。Attention與傳統的Seq2Seq模型主要有以下兩點不同。

1)encoder提供了更多的資料給到decoder,encoder會把所有的節點的hidden state提供給decoder,而不僅僅隻是encoder最後一個節點的hidden state。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

2)decoder并不是直接把所有encoder提供的hidden state作為輸入,而是采取一種選擇機制,把最符合目前位置的hidden state選出來,具體的步驟如下

  • 确定哪一個hidden state與目前節點關系最為密切
  • 計算每一個hidden state的分數值(具體怎麼計算我們下文講解)
  • 對每個分數值做一個softmax的計算,這能讓相關性高的hidden state的分數值更大,相關性低的hidden state的分數值更低

這裡我們以一個具體的例子來看下其中的詳細計算步驟:

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

把每一個encoder節點的hidden states的值與decoder目前節點的上一個節點的hidden state相乘,如上圖,h1、h2、h3分别與目前節點的上一節點的hidden state進行相乘(如果是第一個decoder節點,需要随機初始化一個hidden state),最後會獲得三個值,這三個值就是上文提到的hidden state的分數,注意,這個數值對于每一個encoder的節點來說是不一樣的,把該分數值進行softmax計算,計算之後的值就是每一個encoder節點的hidden states對于目前節點的權重,把權重與原hidden states相乘并相加,得到的結果即是目前節點的hidden state。可以發現,其實Atttention的關鍵就是計算這個分值。

明白每一個節點是怎麼擷取hidden state之後,接下來就是decoder層的工作原理了,其具體過程如下:

第一個decoder的節點初始化一個向量,并計算目前節點的hidden state,把該hidden state作為第一個節點的輸入,經過RNN節點後得到一個新的hidden state與輸出值。注意,這裡和Seq2Seq有一個很大的差別,Seq2Seq是直接把輸出值作為目前節點的輸出,但是Attention會把該值與hidden state做一個連接配接,并把連接配接好的值作為context,并送入一個前饋神經網絡,最終目前節點的輸出内容由該網絡決定,重複以上步驟,直到所有decoder的節點都輸出相應内容。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

Attention模型并不隻是盲目地将輸出的第一個單詞與輸入的第一個詞對齊。實際上,它在訓練階段學習了如何在該語言對中對齊單詞(示例中是法語和英語)。Attention函數的本質可以被描述為一個查詢(query)到一系列(鍵key-值value)對的映射。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

在計算attention時主要分為三步,第一步是将query和每個key進行相似度計算得到權重,常用的相似度函數有點積,拼接,感覺機等;然後第二步一般是使用一個softmax函數對這些權重進行歸一化;最後将權重和相應的鍵值value進行權重求和得到最後的attention。目前在NLP研究中,key和value常常都是同一個,即key=value。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

Transrofmer模型講解

接下來我将介紹《Attention is all you need》這篇論文。這篇論文是google機器翻譯團隊在2017年6月放在arXiv上,最後發表在2017年nips上,到目前為止google學術顯示引用量為2203,可見也是受到了大家廣泛關注和應用。這篇論文主要亮點在于

1)不同于以往主流機器翻譯使用基于RNN的seq2seq模型架構,該論文用attention機制代替了RNN搭建了整個模型架構。

2)提出了多頭注意力(Multi-headed attention)機制方法,在編碼器和解碼器中大量的使用了多頭自注意力機制(Multi-headed self-attention)。

3)在WMT2014語料中的英德和英法任務上取得了先進結果,并且訓練速度比主流模型更快。

《Attention Is All You Need》是一篇Google提出的将Attention思想發揮到極緻的論文。這篇論文中提出一個全新的模型,叫 Transformer,抛棄了以往深度學習任務裡面使用到的 CNN 和 RNN ,Bert就是基于Transformer建構的,這個模型廣泛應用于NLP領域,例如機器翻譯,問答系統,文本摘要和語音識别等等方向。關于Transrofmer模型的了解特别推薦一位國外部落客文章《The Illustrated Transformer》。

Transformer總體結構

和Attention模型一樣,Transformer模型中也采用了 encoer-decoder 架構。但其結構相比于Attention更加複雜,論文中encoder層由6個encoder堆疊在一起,decoder層也一樣。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

每一個encoder和decoder的内部簡版結構如下圖

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

對于encoder,包含兩層,一個self-attention層和一個前饋神經網絡,self-attention能幫助目前節點不僅僅隻關注目前的詞,進而能擷取到上下文的語義。decoder也包含encoder提到的兩層網絡,但是在這兩層中間還有一層attention層,幫助目前節點擷取到目前需要關注的重點内容。

現在我們知道了模型的主要元件,接下來我們看下模型的内部細節。首先,模型需要對輸入的資料進行一個embedding操作,(也可以了解為類似w2c的操作),enmbedding結束之後,輸入到encoder層,self-attention處理完資料後把資料送給前饋神經網絡,前饋神經網絡的計算可以并行,得到的輸出會輸入到下一個encoder。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

Self-Attention

接下來我們詳細看一下self-attention,其思想和attention類似,但是self-attention是Transformer用來将其他相關單詞的“了解”轉換成我們正常了解的單詞的一種思路,我們看個例子:

The animal didn't cross the street because it was too tired

這裡的it到底代表的是animal還是street呢,對于我們來說能很簡單的判斷出來,但是對于機器來說,是很難判斷的,self-attention就能夠讓機器把it和animal聯系起來

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

接下來我們看下詳細的處理過程。

1、首先,self-attention會計算出三個新的向量,在論文中,向量的次元是512維,我們把這三個向量分别稱為Query、Key、Value,這三個向量是用embedding向量與一個矩陣相乘得到的結果,這個矩陣是随機初始化的,次元為(64,512)注意第二個次元需要和embedding的次元一樣,其值在BP的過程中會一直進行更新,得到的這三個向量的次元是64低于embedding次元的。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

那麼Query、Key、Value這三個向量又是什麼呢?這三個向量對于attention來說很重要,當你了解了下文後,你将會明白這三個向量扮演者什麼的角色。

2、計算self-attention的分數值,該分數值決定了當我們在某個位置encode一個詞時,對輸入句子的其他部分的關注程度。這個分數值的計算方法是Query與Key做點乘,以下圖為例,首先我們需要針對Thinking這個詞,計算出其他詞對于該詞的一個分數值,首先是針對于自己本身即q1·k1,然後是針對于第二個詞即q1·k2

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

3、接下來,把點成的結果除以一個常數,這裡我們除以8,這個值一般是采用上文提到的矩陣的第一個次元的開方即64的開方8,當然也可以選擇其他的值,然後把得到的結果做一個softmax的計算。得到的結果即是每個詞對于目前位置的詞的相關性大小,當然,目前位置的詞相關性肯定會會很大

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

4、下一步就是把Value和softmax得到的值進行相乘,并相加,得到的結果即是self-attetion在目前節點的值。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

在實際的應用場景,為了提高計算速度,我們采用的是矩陣的方式,直接計算出Query, Key, Value的矩陣,然後把embedding的值與三個矩陣直接相乘,把得到的新矩陣Q與K相乘,乘以一個常數,做softmax操作,最後乘上V矩陣

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)
一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

這種通過 query 和 key 的相似性程度來确定 value 的權重分布的方法被稱為scaled dot-product attention。其實scaled dot-Product attention就是我們常用的使用點積進行相似度計算的attention,隻是多除了一個(為K的次元)起到調節作用,使得内積不至于太大。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

Multi-Headed Attention

這篇論文更厲害的地方是給self-attention加入了另外一個機制,被稱為“multi-headed” attention,該機制了解起來很簡單,就是說不僅僅隻初始化一組Q、K、V的矩陣,而是初始化多組,tranformer是使用了8組,是以最後得到的結果是8個矩陣。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)
一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

這給我們留下了一個小的挑戰,前饋神經網絡沒法輸入8個矩陣呀,這該怎麼辦呢?是以我們需要一種方式,把8個矩陣降為1個,首先,我們把8個矩陣連在一起,這樣會得到一個大的矩陣,再随機初始化一個矩陣和這個組合好的矩陣相乘,最後得到一個最終的矩陣。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

這就是multi-headed attention的全部流程了,這裡其實已經有很多矩陣了,我們把所有的矩陣放到一張圖内看一下總體的流程。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

多頭attention(Multi-head attention)整個過程可以簡述為:Query,Key,Value首先進過一個線性變換,然後輸入到放縮點積attention(注意這裡要做h次,其實也就是所謂的多頭,每一次算一個頭,而且每次Q,K,V進行線性變換的參數W是不一樣的),然後将h次的放縮點積attention結果進行拼接,再進行一次線性變換得到的值作為多頭attention的結果。可以看到,google提出來的多頭attention的不同之處在于進行了h次計算而不僅僅算一次,論文中說到這樣的好處是可以允許模型在不同的表示子空間裡學習到相關的資訊,後面還會根據attention可視化來驗證。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

那麼在整個模型中,是如何使用attention的呢?如下圖,首先在編碼器到解碼器的地方使用了多頭attention進行連接配接,K,V,Q分别是編碼器的層輸出(這裡K=V)和解碼器中都頭attention的輸入。其實就和主流的機器翻譯模型中的attention一樣,利用解碼器和編碼器attention來進行翻譯對齊。然後在編碼器和解碼器中都使用了多頭自注意力self-attention來學習文本的表示。Self-attention即K=V=Q,例如輸入一個句子,那麼裡面的每個詞都要和該句子中的所有詞進行attention計算。目的是學習句子内部的詞依賴關系,捕獲句子的内部結構。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

對于使用自注意力機制的原因,論文中提到主要從三個方面考慮(每一層的複雜度,是否可以并行,長距離依賴學習),并給出了和RNN,CNN計算複雜度的比較。可以看到,如果輸入序列n小于表示次元d的話,每一層的時間複雜度self-attention是比較有優勢的。當n比較大時,作者也給出了一種解決方案self-attention(restricted)即每個詞不是和所有詞計算attention,而是隻與限制的r個詞去計算attention。在并行方面,多頭attention和CNN一樣不依賴于前一時刻的計算,可以很好的并行,優于RNN。在長距離依賴上,由于self-attention是每個詞和所有詞都要計算attention,是以不管他們中間有多長距離,最大的路徑長度也都隻是1。可以捕獲長距離依賴關系。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

現在我們已經接觸了attention的header,讓我們重新審視我們之前的例子,看看例句中的“it”這個單詞在不同的attention header情況下會有怎樣不同的關注點(這裡不同顔色代表attention不同頭的結果,顔色越深attention值越大)。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

當我們對“it”這個詞進行編碼時,一個注意力的焦點主要集中在“animal”上,而另一個注意力集中在“tired”(兩個heads)

但是,如果我們将所有注意力添加到圖檔中,可能有點難了解:

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

Positional Encoding

到目前為止,transformer模型中還缺少一種解釋輸入序列中單詞順序的方法。為了處理這個問題,transformer給encoder層和decoder層的輸入添加了一個額外的向量Positional Encoding,次元和embedding的次元一樣,這個向量采用了一種很獨特的方法來讓模型學習到這個值,這個向量能決定目前詞的位置,或者說在一個句子中不同的詞之間的距離。這個位置向量的具體計算方法有很多種,論文中的計算方法如下

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

其中pos是指目前詞在句子中的位置,i是指向量中每個值的index,可以看出,在偶數位置,使用正弦編碼,在奇數位置,使用餘弦編碼。最後把這個Positional Encoding與embedding的值相加,作為輸入送到下一層。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

為了讓模型捕捉到單詞的順序資訊,我們添加位置編碼向量資訊(POSITIONAL ENCODING),位置編碼向量不需要訓練,它有一個規則的産生方式(上圖公式)。

如果我們的嵌入次元為4,那麼實際上的位置編碼就如下圖所示:

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

那麼生成位置向量需要遵循怎樣的規則呢?

觀察下面的圖形,每一行都代表着對一個矢量的位置編碼。是以第一行就是我們輸入序列中第一個字的嵌入向量,每行都包含512個值,每個值介于1和-1之間。我們用顔色來表示1,-1之間的值,這樣友善可視化的方式表現出來:

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

這是一個20個字(行)的(512)列位置編碼示例。你會發現它咋中心位置被分為了2半,這是因為左半部分的值是一由一個正弦函數生成的,而右半部分是由另一個函數(餘弦)生成。然後将它們連接配接起來形成每個位置編碼矢量。

Layer normalization

在transformer中,每一個子層(self-attetion,ffnn)之後都會接一個殘差子產品,并且有一個Layer normalization

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

在進一步探索其内部計算方式,我們可以将上面圖層可視化為下圖:

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

殘差子產品相信大家都很清楚了,這裡不再講解,主要講解下Layer normalization。Normalization有很多種,但是它們都有一個共同的目的,那就是把輸入轉化成均值為0方差為1的資料。我們在把資料送入激活函數之前進行normalization(歸一化),因為我們不希望輸入資料落在激活函數的飽和區。

說到 normalization,那就肯定得提到 Batch Normalization。BN的主要思想就是:在每一層的每一批資料上進行歸一化。我們可能會對輸入資料進行歸一化,但是經過該網絡層的作用後,我們的資料已經不再是歸一化的了。随着這種情況的發展,資料的偏差越來越大,我的反向傳播需要考慮到這些大的偏差,這就迫使我們隻能使用較小的學習率來防止梯度消失或者梯度爆炸。

BN的具體做法就是對每一小批資料,在批這個方向上做歸一化。如下圖所示:

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

可以看到,右半邊求均值是沿着資料 batch_size的方向進行的,其計算公式如下:

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

那麼什麼是 Layer normalization 呢?它也是歸一化資料的一種方式,不過 LN 是在每一個樣本上計算均值和方差,而不是BN那種在批方向計算均值和方差!

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

下面看一下 LN 的公式:

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

到這裡為止就是全部encoders的内容了,如果把兩個encoders疊加在一起就是這樣的結構,在self-attention需要強調的最後一點是其采用了殘差網絡中的short-cut結構,目的是解決深度學習中的退化問題。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

Decoder層

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

上圖是transformer的一個詳細結構,相比本文一開始結束的結構圖會更詳細些,接下來,我們會按照這個結構圖講解下decoder部分。

可以看到decoder部分其實和encoder部分大同小異,不過在最下面額外多了一個masked mutil-head attetion,這裡的mask也是transformer一個很關鍵的技術,我們一起來看一下。

Mask

mask 表示掩碼,它對某些值進行掩蓋,使其在參數更新時不産生效果。Transformer 模型裡面涉及兩種 mask,分别是 padding mask 和 sequence mask。

其中,padding mask 在所有的 scaled dot-product attention 裡面都需要用到,而 sequence mask 隻有在 decoder 的 self-attention 裡面用到。

Padding Mask

什麼是 padding mask 呢?因為每個批次輸入序列長度是不一樣的也就是說,我們要對輸入序列進行對齊。具體來說,就是給在較短的序列後面填充 0。但是如果輸入的序列太長,則是截取左邊的内容,把多餘的直接舍棄。因為這些填充的位置,其實是沒什麼意義的,是以我們的attention機制不應該把注意力放在這些位置上,是以我們需要進行一些處理。

具體的做法是,把這些位置的值加上一個非常大的負數(負無窮),這樣的話,經過 softmax,這些位置的機率就會接近0!

而我們的 padding mask 實際上是一個張量,每個值都是一個Boolean,值為 false 的地方就是我們要進行處理的地方。

Sequence mask

文章前面也提到,sequence mask 是為了使得 decoder 不能看見未來的資訊。也就是對于一個序列,在 time_step 為 t 的時刻,我們的解碼輸出應該隻能依賴于 t 時刻之前的輸出,而不能依賴 t 之後的輸出。是以我們需要想一個辦法,把 t 之後的資訊給隐藏起來。

那麼具體怎麼做呢?也很簡單:産生一個上三角矩陣,上三角的值全為0。把這個矩陣作用在每一個序列上,就可以達到我們的目的。

  • 對于 decoder 的 self-attention,裡面使用到的 scaled dot-product attention,同時需要padding mask 和 sequence mask 作為 attn_mask,具體實作就是兩個mask相加作為attn_mask。
  • 其他情況,attn_mask 一律等于 padding mask。

編碼器通過處理輸入序列啟動。然後将頂部編碼器的輸出轉換為一組注意向量k和v。每個解碼器将在其“encoder-decoder attention”層中使用這些注意向量,這有助于解碼器将注意力集中在輸入序列中的适當位置:

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

完成編碼階段後,我們開始解碼階段。解碼階段的每個步驟從輸出序列(本例中為英語翻譯句)輸出一個元素。

以下步驟重複此過程,一直到達到表示解碼器已完成輸出的符号。每一步的輸出在下一個時間步被送入底部解碼器,解碼器像就像我們對編碼器輸入所做操作那樣,我們将位置編碼嵌入并添加到這些解碼器輸入中,以表示每個字的位置。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

輸出層

當decoder層全部執行完畢後,怎麼把得到的向量映射為我們需要的詞呢,很簡單,隻需要在結尾再添加一個全連接配接層和softmax層,假如我們的詞典是1w個詞,那最終softmax會輸入1w個詞的機率,機率值最大的對應的詞就是我們最終的結果。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

BERT原理詳解

從創新的角度來看,bert其實并沒有過多的結構方面的創新點,其和GPT一樣均是采用的transformer的結構,相對于GPT來說,其是雙向結構的,而GPT是單向的,如下圖所示

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

elmo:将上下文當作特征,但是無監督的語料和我們真實的語料還是有差別的,不一定的符合我們特定的任務,是一種雙向的特征提取。

openai gpt就做了一個改進,也是通過transformer學習出來一個語言模型,不是固定的,通過任務 finetuning,用transfomer代替elmo的lstm。

openai gpt其實就是缺少了encoder的transformer。當然也沒了encoder與decoder之間的attention。

openAI gpt雖然可以進行fine-tuning,但是有些特殊任務與pretraining輸入有出入,單個句子與兩個句子不一緻的情況,很難解決,還有就是decoder隻能看到前面的資訊。

其次bert在多方面的nlp任務變現來看效果都較好,具備較強的泛化能力,對于特定的任務隻需要添加一個輸出層來進行fine-tuning即可。

結構

先看下bert的内部結構,官網最開始提供了兩個版本,L表示的是transformer的層數,H表示輸出的次元,A表示mutil-head attention的個數

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

如今已經增加了多個模型,中文是其中唯一一個非英語的模型。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

從模型的層數來說其實已經很大了,但是由于transformer的殘差(residual)子產品,層數并不會引起梯度消失等問題,但是并不代表層數越多效果越好,有論點認為低層偏向于文法特征學習,高層偏向于語義特征學習。

預訓練模型

首先我們要了解一下什麼是預訓練模型,舉個例子,假設我們有大量的維基百科資料,那麼我們可以用這部分巨大的資料來訓練一個泛化能力很強的模型,當我們需要在特定場景使用時,例如做文本相似度計算,那麼,隻需要簡單的修改一些輸出層,再用我們自己的資料進行一個增量訓練,對權重進行一個輕微的調整。

預訓練的好處在于在特定場景使用時不需要用大量的語料來進行訓練,節約時間效率高效,bert就是這樣的一個泛化能力較強的預訓練模型。

BERT的預訓練過程

接下來我們看看BERT的預訓練過程,BERT的預訓練階段包括兩個任務,一個是Masked Language Model,還有一個是Next Sentence Prediction。

Masked Language Model

MLM可以了解為完形填空,作者會随機mask每一個句子中15%的詞,用其上下文來做預測,例如:

my dog is hairy → my dog is [MASK]

此處将hairy進行了mask處理,然後采用非監督學習的方法預測mask位置的詞是什麼,但是該方法有一個問題,因為是mask15%的詞,其數量已經很高了,這樣就會導緻某些詞在fine-tuning階段從未見過,為了解決這個問題,作者做了如下的處理:

  • 80%的時間是采用[mask],my dog is hairy → my dog is [MASK]
  • 10%的時間是随機取一個詞來代替mask的詞,my dog is hairy -> my dog is apple
  • 10%的時間保持不變,my dog is hairy -> my dog is hairy

那麼為啥要以一定的機率使用随機詞呢?這是因為transformer要保持對每個輸入token分布式的表征,否則Transformer很可能會記住這個[MASK]就是"hairy"。至于使用随機詞帶來的負面影響,文章中解釋說,所有其他的token(即非"hairy"的token)共享15%*10% = 1.5%的機率,其影響是可以忽略不計的。Transformer全局的可視,又增加了資訊的擷取,但是不讓模型擷取全量資訊。

注意:

  • 有參數dupe_factor決定資料duplicate的次數。
  • 其中,create_instance_from_document函數,是構造了一個sentence-pair的樣本。對每一句,先生成[CLS]+A+[SEP]+B+[SEP],有長(0.9)有短(0.1),再加上mask,然後做成樣本類object。
  • create_masked_lm_predictions函數傳回的tokens是已經被遮擋詞替換之後的tokens
  • masked_lm_labels則是遮擋詞對應位置真實的label。

Next Sentence Prediction

選擇一些句子對A與B,其中50%的資料B是A的下一條句子,剩餘50%的資料B是語料庫中随機選擇的,學習其中的相關性,添加這樣的預訓練的目的是目前很多NLP的任務比如QA和NLI都需要了解兩個句子之間的關系,進而能讓預訓練的模型更好的适應這樣的任務。

個人了解:

  • Bert先是用Mask來提高視野範圍的資訊擷取量,增加duplicate再随機Mask,這樣跟RNN類方法依次訓練預測沒什麼差別了除了mask不同位置外;
  • 全局視野極大地降低了學習的難度,然後再用A+B/C來作為樣本,這樣每條樣本都有50%的機率看到一半左右的噪聲;
  • 但直接學習Mask A+B/C是沒法學習的,因為不知道哪些是噪聲,是以又加上next_sentence預測任務,與MLM同時進行訓練,這樣用next來輔助模型對噪聲/非噪聲的辨識,用MLM來完成語義的大部分的學習。
    一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

輸入

bert的輸入可以是單一的一個句子或者是句子對,實際的輸入值是segment embedding與position embedding相加,具體的操作流程可參考上面的transformer講解。

BERT的輸入詞向量是三個向量之和:

Token Embedding:WordPiece tokenization subword詞向量。

Segment Embedding:表明這個詞屬于哪個句子(NSP需要兩個句子)。

Position Embedding:學習出來的embedding向量。這與Transformer不同,Transformer中是預先設定好的值。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

總結

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

BERT的去除實驗表明,雙向LM和NSP帶了的提升最大。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

另一個結論是,增加模型參數數量可以提升模型效果。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

BERT預訓練模型的輸出結果,無非就是一個或多個向量。下遊任務可以通過精調(改變預訓練模型參數)或者特征抽取(不改變預訓練模型參數,隻是把預訓練模型的輸出作為特征輸入到下遊任務)兩種方式進行使用。BERT原論文使用了精調方式,但也嘗試了特征抽取方式的效果,比如在NER任務上,最好的特征抽取方式隻比精調差一點點。但特征抽取方式的好處可以預先計算好所需的向量,存下來就可重複使用,極大提升下遊任務模型訓練的速度。

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

後來也有其他人針對ELMo和BERT比較了這兩種使用方式的精度差異。下面列出基本結論:

一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)
一文讀懂BERT(原理篇)一文讀懂BERT(原理篇)

總結下BERT的主要貢獻:

  • 引入了Masked LM,使用雙向LM做模型預訓練。
  • 為預訓練引入了新目标NSP,它可以學習句子與句子間的關系。
  • 進一步驗證了更大的模型效果更好: 12 --> 24 層。
  • 為下遊任務引入了很通用的求解架構,不再為任務做模型定制。
  • 重新整理了多項NLP任務的記錄,引爆了NLP無監督預訓練技術。

BERT是谷歌團隊糅合目前已有的NLP知識集大成者,重新整理11條賽道彰顯了無與倫比的實力,且極容易被用于多種NLP任務。宛若一束煙花點亮在所有NLP從業者心中。更為可貴的是谷歌選擇了開源這些,讓所有從業者看到了在各行各業落地的更多可能性。

BERT優點

  • Transformer Encoder因為有Self-attention機制,是以BERT自帶雙向功能
  • 因為雙向功能以及多層Self-attention機制的影響,使得BERT必須使用Cloze版的語言模型Masked-LM來完成token級别的預訓練
  • 為了擷取比詞更進階别的句子級别的語義表征,BERT加入了Next Sentence Prediction來和Masked-LM一起做聯合訓練
  • 為了适配多任務下的遷移學習,BERT設計了更通用的輸入層和輸出層
  • 微調成本小

BERT缺點

  • task1的随機遮擋政策略顯粗犷,推薦閱讀《Data Nosing As Smoothing In Neural Network Language Models》
  • [MASK]标記在實際預測中不會出現,訓練時用過多[MASK]影響模型表現;
  • 每個batch隻有15%的token被預測,是以BERT收斂得比left-to-right模型要慢(它們會預測每個token)
  • BERT對硬體資源的消耗巨大(大模型需要16個tpu,曆時四天;更大的模型需要64個tpu,曆時四天。

關于BERT最新的各領域應用推薦張俊林的Bert時代的創新(應用篇)

思考

  • 個人并不認為文章是模型的改進,更認可為任務的設計改進。
  • 論文作者隻比較了有沒有task1的影響,并沒有針對task2對比試驗。提升是否來自好的預訓練任務設計沒有明說。
  • bert對nlp領域目前已有知識的有效“整合”,在硬體配置足夠的情況下能提高nlp多領域性能

BERT适用場景

第一,如果NLP任務偏向在語言本身中就包含答案,而不特别依賴文本外的其它特征,往往應用Bert能夠極大提升應用效果。典型的任務比如QA和閱讀了解,正确答案更偏向對語言的了解程度,了解能力越強,解決得越好,不太依賴語言之外的一些判斷因素,是以效果提升就特别明顯。反過來說,對于某些任務,除了文本類特征外,其它特征也很關鍵,比如搜尋的使用者行為/連結分析/内容品質等也非常重要,是以Bert的優勢可能就不太容易發揮出來。再比如,推薦系統也是類似的道理,Bert可能隻能對于文本内容編碼有幫助,其它的使用者行為類特征,不太容易融入Bert中。

第二,Bert特别适合解決句子或者段落的比對類任務。就是說,Bert特别适合用來解決判斷句子關系類問題,這是相對單文本分類任務和序列标注等其它典型NLP任務來說的,很多實驗結果表明了這一點。而其中的原因,我覺得很可能主要有兩個,一個原因是:很可能是因為Bert在預訓練階段增加了Next Sentence Prediction任務,是以能夠在預訓練階段學會一些句間關系的知識,而如果下遊任務正好涉及到句間關系判斷,就特别吻合Bert本身的長處,于是效果就特别明顯。第二個可能的原因是:因為Self Attention機制自帶句子A中單詞和句子B中任意單詞的Attention效果,而這種細粒度的比對對于句子比對類的任務尤其重要,是以Transformer的本質特性也決定了它特别适合解決這類任務。

從上面這個Bert的擅長處理句間關系類任務的特性,我們可以繼續推理出以下觀點:

既然預訓練階段增加了Next Sentence Prediction任務,就能對下遊類似性質任務有較好促進作用,那麼是否可以繼續在預訓練階段加入其它的新的輔助任務?而這個輔助任務如果具備一定通用性,可能會對一類的下遊任務效果有直接促進作用。這也是一個很有意思的探索方向,當然,這種方向因為要動Bert的第一個預訓練階段,是以屬于NLP屆土豪們的工作範疇,窮人們還是散退、旁觀、鼓掌、叫好為妙。

第三,Bert的适用場景,與NLP任務對深層語義特征的需求程度有關。感覺越是需要深層語義特征的任務,越适合利用Bert來解決;而對有些NLP任務來說,淺層的特征即可解決問題,典型的淺層特征性任務比如分詞,POS詞性标注,NER,文本分類等任務,這種類型的任務,隻需要較短的上下文,以及淺層的非語義的特征,貌似就可以較好地解決問題,是以Bert能夠發揮作用的餘地就不太大,有點殺雞用牛刀,有力使不出來的感覺。

這很可能是因為Transformer層深比較深,是以可以逐層捕獲不同層級不同深度的特征。于是,對于需要語義特征的問題和任務,Bert這種深度捕獲各種特征的能力越容易發揮出來,而淺層的任務,比如分詞/文本分類這種任務,也許傳統方法就能解決得比較好,因為任務特性決定了,要解決好它,不太需要深層特征。

第四,Bert比較适合解決輸入長度不太長的NLP任務,而輸入比較長的任務,典型的比如文檔級别的任務,Bert解決起來可能就不太好。主要原因在于:Transformer的self attention機制因為要對任意兩個單詞做attention計算,是以時間複雜度是n平方,n是輸入的長度。如果輸入長度比較長,Transformer的訓練和推理速度掉得比較厲害,于是,這點限制了Bert的輸入長度不能太長。是以對于輸入長一些的文檔級别的任務,Bert就不容易解決好。結論是:Bert更适合解決句子級别或者段落級别的NLP任務。

如果有小夥伴堅持看到這裡的話深表感謝,本來要繼續寫源碼分析和具體的實踐了。時間關系,等下周再抽時間寫源碼分析與實踐部分吧。本文僅用于筆者自己總結自己BERT學習之路,期間引用很多專家學者的觀點思路,深表感謝。第一次駕馭這麼長的技術文章,每個知識點都想寫點,感覺越寫越亂。若有讀者在閱讀本文期間有不好的閱讀體驗深表歉意。

繼續閱讀