【深度學習】小白看得懂的 BERT 原理

0. 導語

自 google 在 2018 年 10 月底公佈 BERT 在 11 項 nlp 任務中的卓越表現後,BERT(Bidirectional Encoder Representation from Transformers) 就成爲 NLP 領域大火,在本文中,我們將研究 BERT 模型,理解它的工作原理,這個是 NLP(自然語言處理)的非常重要的部分。

備註:前面的文章講了 transformer 的原理

作者:jinjiajia95

出處:https://blog.csdn.net/weixin_40746796/article/details/89951967

原作者:Jay Alammar

原鏈接:https://jalammar.github.io/illustrated-bert/

正文開始

前言

2018 年可謂是自然語言處理(NLP)的元年,在我們如何以最能捕捉潛在語義關係的方式  來輔助計算機對的句子概念性的理解 這方面取得了極大的發展進步。此外, NLP 領域的一些開源社區已經發布了很多強大的組件,我們可以在自己的模型訓練過程中免費的下載使用。(可以說今年是 NLP 的 ImageNet 時刻,因爲這和幾年前計算機視覺的發展很相似)

上圖中,最新發布的 BERT 是一個 NLP 任務的里程碑式模型,它的發佈勢必會帶來一個 NLP 的新時代。BERT 是一個算法模型,它的出現打破了大量的自然語言處理任務的記錄。在 BERT 的論文發佈不久後,Google 的研發團隊還開放了該模型的代碼,並提供了一些在大量數據集上預訓練好的算法模型下載方式。Goole 開源這個模型,並提供預訓練好的模型,這使得所有人都可以通過它來構建一個涉及 NLP 的算法模型,節約了大量訓練語言模型所需的時間,精力,知識和資源。

BERT 集成了最近一段時間內 NLP 領域中的一些頂尖的思想,包括但不限於 Semi-supervised Sequence Learning (by Andrew Dai and Quoc Le), ELMo (by Matthew Peters and researchers from AI2 and UW CSE), ULMFiT (by fast.ai founder Jeremy Howard and Sebastian Ruder), and the OpenAI transformer (by OpenAI researchers Radford, Narasimhan, Salimans, and Sutskever), and the Transformer (Vaswani et al).。

你需要注意一些事情才能恰當的理解 BERT 的內容,不過,在介紹模型涉及的概念之前可以使用 BERT 的方法。

示例:句子分類
使用 BERT 最簡單的方法就是做一個文本分類模型,這樣的模型結構如下圖所示:

爲了訓練一個這樣的模型,(主要是訓練一個分類器),在訓練階段 BERT 模型發生的變化很小。該訓練過程稱爲微調,並且源於 Semi-supervised Sequence Learning 和 ULMFiT.。

爲了更方便理解,我們下面舉一個分類器的例子。分類器是屬於監督學習領域的,這意味着你需要一些標記的數據來訓練這些模型。對於垃圾郵件分類器的示例,標記的數據集由郵件的內容和郵件的類別 2 部分組成(類別分爲 “垃圾郵件” 或“非垃圾郵件”)。

這種用例的其他示例包括:

情感分析

輸入:電影 / 產品評論。輸出:評論是正面還是負面?
示例數據集:SST
事實查證
輸入:句子。輸出:“索賠” 或 “不索賠”
更雄心勃勃 / 未來主義的例子:
輸入:句子。輸出:“真” 或 “假”

模型架構

現在您已經瞭解瞭如何使用 BERT 的示例,讓我們仔細瞭解一下他的工作原理。

BERT 的論文中介紹了 2 種版本:

BERT 的基礎集成單元是 Transformer 的 Encoder。關於 Transformer 的介紹可以閱讀作者之前的文章:The Illustrated Transformer,該文章解釋了 Transformer 模型 - BERT 的基本概念以及我們接下來要討論的概念。

2 個 BERT 的模型都有一個很大的編碼器層數,(論文裏面將此稱爲 Transformer Blocks) - 基礎版本就有 12 層,進階版本有 24 層。同時它也有很大的前饋神經網絡( 768 和 1024 個隱藏層神經元),還有很多 attention heads(12-16 個)。這超過了 Transformer 論文中的參考配置參數(6 個編碼器層,512 個隱藏層單元,和 8 個注意頭)

模型輸入


輸入的第一個字符爲 [CLS],在這裏字符[CLS] 表達的意思很簡單 - Classification (分類)。

BERT 與 Transformer 的編碼方式一樣。將固定長度的字符串作爲輸入,數據由下而上傳遞計算,每一層都用到了 self attention,並通過前饋神經網絡傳遞其結果,將其交給下一個編碼器。

這樣的架構,似乎是沿用了 Transformer 的架構(除了層數,不過這是我們可以設置的參數)。那麼 BERT 與 Transformer 不同之處在哪裏呢?可能在模型的輸出上,我們可以發現一些端倪。

模型輸出

每個位置返回的輸出都是一個隱藏層大小的向量(基本版本 BERT 爲 768)。以文本分類爲例,我們重點關注第一個位置上的輸出(第一個位置是分類標識 [CLS]) 。如下圖

該向量現在可以用作我們選擇的分類器的輸入,在論文中指出使用單層神經網絡作爲分類器就可以取得很好的效果。原理如下。:

例子中只有垃圾郵件和非垃圾郵件,如果你有更多的 label,你只需要增加輸出神經元的個數即可,另外把最後的激活函數換成 softmax 即可。

Parallels with Convolutional Nets(BERT VS 卷積神經網絡)
對於那些具有計算機視覺背景的人來說,這個矢量切換應該讓人聯想到 VGGNet 等網絡的卷積部分與網絡末端的完全連接的分類部分之間發生的事情。你可以這樣理解,實質上這樣理解也很方便。

詞嵌入的新時代〜

BERT 的開源隨之而來的是一種詞嵌入的更新。到目前爲止,詞嵌入已經成爲 NLP 模型處理自然語言的主要組成部分。諸如 Word2vec 和 Glove 等方法已經廣泛的用於處理這些問題,在我們使用新的詞嵌入之前,我們有必要回顧一下其發展。

詞嵌入的回顧

爲了讓機器可以學習到文本的特徵屬性,我們需要一些將文本數值化的表示的方式。Word2vec 算法通過使用一組固定維度的向量來表示單詞,計算其方式可以捕獲到單詞的語義及單詞與單詞之間的關係。使用 Word2vec 的向量化表示方式可以用於判斷單詞是否相似,對立,或者說判斷 “男人‘與’女人” 的關係就如同 “國王” 與“王后”。(這些話是不是聽膩了〜 emmm 水文必備)。另外還能捕獲到一些語法的關係,這個在英語中很實用。例如 “had” 與“has”的關係如同 “was” 與“is”的關係。

這樣的做法,我們可以使用大量的文本數據來預訓練一個詞嵌入模型,而這個詞嵌入模型可以廣泛用於其他 NLP 的任務,這是個好主意,這使得一些初創公司或者計算資源不足的公司,也能通過下載已經開源的詞嵌入模型來完成 NLP 的任務。

ELMo:語境問題

上面介紹的詞嵌入方式有一個很明顯的問題,因爲使用預訓練好的詞向量模型,那麼無論上下文的語境關係如何,每個單詞都只有一個唯一的且已經固定保存的向量化形式。“Wait a minute “- 出自 (Peters et. al., 2017, McCann et. al., 2017, and yet again Peters et. al., 2018 in the ELMo paper)

這和中文的同音字其實也類似,用這個舉一個例子吧, ‘長’ 這個字,在 ‘長度’ 這個詞中表示度量,在 ‘長高’ 這個詞中表示增加。那麼爲什麼我們不通過” 長’周圍是度或者是高來判斷它的讀音或者它的語義呢?嗖嘎,這個問題就派生出語境化的詞嵌入模型。

EMLo 改變 Word2vec 類的將單詞固定爲指定長度的向量的處理方式,它是在爲每個單詞分配詞向量之前先查看整個句子,然後使用 bi-LSTM 來訓練它對應的詞向量。

ELMo 爲解決 NLP 的語境問題作出了重要的貢獻,它的 LSTM 可以使用與我們任務相關的大量文本數據來進行訓練,然後將訓練好的模型用作其他 NLP 任務的詞向量的基準。
ELMo 的祕密是什麼?

ELMo 會訓練一個模型,這個模型接受一個句子或者單詞的輸入, 輸出最有可能出現在後面的一個單詞。想想輸入法,對啦,就是這樣的道理。這個在 NLP 中我們也稱作 Language Modeling。這樣的模型很容易實現,因爲我們擁有大量的文本數據且我們可以在不需要標籤的情況下去學習。

上圖介紹了 ELMo 預訓練的過程的步驟的一部分:我們需要完成一個這樣的任務:輸入 “Lets stick to”,預測下一個最可能出現的單詞,如果在訓練階段使用大量的數據集進行訓練,那麼在預測階段我們可能準確的預測出我們期待的下一個單詞。比如輸入 “機器”,在‘’學習‘和‘買菜’中它最有可能的輸出會是‘學習’而不是‘買菜’。

從上圖可以發現,每個展開的 LSTM 都在最後一步完成預測。

對了真正的 ELMo 會更進一步,它不僅能判斷下一個詞,還能預測前一個詞。(Bi-Lstm)

ELMo 通過下圖的方式將 hidden states(的初始的嵌入)組合咋子一起來提煉出具有語境意義的詞嵌入方式(全連接後加權求和)

ULM-FiT:NLP 領域應用遷移學習

ULM-FiT 機制讓模型的預訓練參數得到更好的利用。所利用的參數不僅限於 embeddings,也不僅限於語境 embedding,ULM-FiT 引入了 Language Model 和一個有效微調該 Language Model 來執行各種 NLP 任務的流程。這使得 NLP 任務也能像計算機視覺一樣方便的使用遷移學習。

The Transformer:超越 LSTM 的結構

Transformer 論文和代碼的發佈,以及其在機器翻譯等任務上取得的優異成果,讓一些研究人員認爲它是 LSTM 的替代品,事實上卻是 Transformer 比 LSTM 更好的處理 long-term dependancies(長程依賴)問題。Transformer Encoding 和 Decoding 的結構非常適合機器翻譯,但是怎麼利用他來做文本分類的任務呢?實際上你只用使用它來預訓練可以針對其他任務微調的語言模型即可。

OpenAI Transformer:用於語言模型的 Transformer 解碼器預訓練

事實證明,我們並不需要一個完整的 transformer 結構來使用遷移學習和一個很好的語言模型來處理 NLP 任務。我們只需要 Transformer 的解碼器就行了。The decoder is a good choice because it’s a natural choice for language modeling (predicting the next word) since it’s built to mask future tokens – a valuable feature when it’s generating a translation word by word.
該模型堆疊了十二個 Decoder 層。由於在該設置中沒有 Encoder,因此這些 Decoder 將不具有 Transformer Decoder 層具有的 Encoder - Decoder attention 層。然而,取而代之的是一個 self attention 層(masked so it doesn’t peak at future tokens)。

通過這種結構調整,我們可以繼續在相似的語言模型任務上訓練模型:使用大量的未標記數據集訓練,來預測下一個單詞。舉個列子:你那 7000 本書餵給你的模型,(書籍是極好的訓練樣本~ 比博客和推文好很多。)訓練框架如下:

Transfer Learning to Downstream Tasks

通過 OpenAI 的 transformer 的預訓練和一些微調後,我們就可以將訓練好的模型,用於其他下游 NLP 任務啦。(比如訓練一個語言模型,然後拿他的 hidden state 來做分類。),下面就介紹一下這個騷操作。(還是如上面例子:分爲垃圾郵件和非垃圾郵件)

OpenAI 論文概述了許多 Transformer 使用遷移學習來處理不同類型 NLP 任務的例子。如下圖例子所示:

BERT: From Decoders to Encoders

OpenAI transformer 爲我們提供了基於 Transformer 的精密的預訓練模型。但是從 LSTM 到 Transformer 的過渡中,我們發現少了些東西。ELMo 的語言模型是雙向的,但是 OpenAI 的 transformer 是前向訓練的語言模型。我們能否讓我們的 Transformer 模型也具有 Bi-Lstm 的特性呢?

R-BERT:“Hold my beer”

Masked Language Model
BERT 說:“我要用 transformer 的 encoders”

Ernie 不屑道:“呵呵,你不能像 Bi-Lstm 一樣考慮文章”

BERT 自信回答道:“我們會用 masks”

解釋一下 Mask:

語言模型會根據前面單詞來預測下一個單詞,但是 self-attention 的注意力只會放在自己身上,那麼這樣 100% 預測到自己,毫無意義,所以用 Mask,把需要預測的詞給擋住。

如下圖:


Two-sentence Tasks

我們回顧一下 OpenAI transformer 處理不同任務的輸入轉換,你會發現在某些任務上我們需要 2 個句子作爲輸入,並做一些更爲智能的判斷,比如是否相似,比如 給出一個維基百科的內容作爲輸入,同時在放入一條針對該條目的問題,那麼我們的算法模型能夠處理這個問題嗎?

爲了使 BERT 更好的處理 2 個句子之間的關係,預訓練的過程還有一個額外的任務:給定 2 個句子(A 和 B),A 與 B 是否相似?(0 或者 1)

特殊 NLP 任務

BERT 的論文爲我們介紹了幾種 BERT 可以處理的 NLP 任務:

  1. 短文本相似

  2. 文本分類

  3. QA 機器人

  4. 語義標註

BERT 用做特徵提取

微調方法並不是使用 BERT 的唯一方法,就像 ELMo 一樣,你可以使用預選訓練好的 BERT 來創建語境化詞嵌入。然後你可以將這些嵌入提供給現有的模型。

哪個向量最適合作爲上下文嵌入?我認爲這取決於任務。本文考察了六種選擇(與微調模型相比,得分爲 96.4):

如何使用 BERT

使用 BERT 的最佳方式是通過 BERT FineTuning with Cloud TPUs 谷歌雲上託管的筆記

(https://colab.research.google.com/github/tensorflow/tpu/blob/master/tools/colab/bert_finetuning_with_cloud_tpus.ipynb)。

如果你未使用過谷歌雲 TPU 可以試試看,這是個不錯的嘗試。另外 BERT 也適用於 TPU,CPU 和 GPU

下一步是查看 BERT 倉庫中的代碼:

  1. 該模型在 modeling.py  (BertModel 類)中構建,與 vanilla Transformer 編碼器完全相同。

    (https://github.com/google-research/bert/blob/master/modeling.py)

  2. run_classifier.py 是微調過程的一個示例。

    它還構建了監督模型的分類層。

    (https://github.com/google-research/bert/blob/master/run_classifier.py)

    如果要構建自己的分類器,請查看該文件中的 create_model() 方法。

  3. 可以下載幾種預先訓練的模型。

    涵蓋 102 種語言的多語言模型,這些語言都是在維基百科的數據基礎上訓練而成的。

    BERT 不會將單詞視爲 tokens。

    相反,它注重 WordPieces。

    tokenization.py 是將你的單詞轉換爲適合 BERT 的 wordPieces 的 tokensizer。

    (https://github.com/google-research/bert/blob/master/tokenization.py)

您還可以查看 BERT 的 PyTorch 實現。

(https://github.com/huggingface/pytorch-pretrained-BERT)

AllenNLP 庫使用此實現允許將 BERT 嵌入與任何模型一起使用。

(https://github.com/allenai/allennlp)

(https://github.com/allenai/allennlp/pull/2067)

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/2dCPQBWmohs4C5E5mqjeDw