---
# System prepended metadata

title: BERT

---

# BERT

## 過去回
[第１回：NLP Outline](https://hackmd.io/uD2hEISAShqVHD6IRtceUw)
[第２回：Word2Vec](https://hackmd.io/T2QJsuwsROSQluklguDOow)
[第３回：Doc2Vec](https://hackmd.io/LIT2hp_jQ56Dvn-imOVemg)
[第４回：Seq2Seq](https://hackmd.io/UGLHXO6-RweY_Bys2Dp4mA)
[第５回：Seq2Seq Attention](https://hackmd.io/D8xqAyHjRte3A0oENtLXeQ)
[第６回：Transformer](https://hackmd.io/DcxZgK3uShiuh2kt76xeUA)

## 元論文
https://arxiv.org/pdf/1810.04805.pdf

## 参考
Openai-GPTの解説
https://data-analytics.fun/2020/04/18/understanding-openai-gpt/
GPT2
https://note.com/npaka/n/nbfd4f4c09abf
BERT解説
https://deepsquare.jp/2020/09/bert/
https://www.ogis-ri.co.jp/otc/hiroba/technical/similar-document-search/part3.html
GLUE解説
https://note.com/npaka/n/n5086fc19c5fc
ULMFiT解説
https://qiita.com/kogecoo/items/49dd9019bf9268bd8e38

## 要点
* **BERTはTransformerのEncoderを使ったモデル**
* **あらゆるNLPタスクにファインチューニング可能なモデル**


## 事前学習/転移学習/ファインチューニング

言葉の定義について記載。

例えば、私達が使っているDetectron2のモデルは、CocoDataset の train_2017 のデータを使って訓練したモデルのWeightを使っている。
そのモデルは==事前学習モデル==と言える。
そして、別のモデルを作っているので、ファインチューニングしていると言える
※厳密には、Layerを追加してはいないので、ファインチューニングとは言わないかもしれないが、本質的には同じ事だと思う

![](https://i.imgur.com/TT1M7ix.png)

## 事前学習→ファインチューニング

最近の言語モデルは、事前学習とファインチューニングがセットでの学習となっているのがほとんど。
==Universal Language Model Fine-tuning for Text Classification (ULMFiT)== はその走りとなったモデル。
Wikipediaのような入手しやすい言語資源を利用することで、少量のラベル付きデータで良い性能を出せることを示している

![](https://i.imgur.com/vOwddqT.png)

ざっくり説明すると
1. 大量のコーパスで教師なし学習(==pre-training==)
2. 目的となるタスクのコーパスで教師なし学習(==fine-tuning==)
3. 目的となるタスクのコーパスで教師あり学習(==fine-tuning==)

のステップ。2. と 3. は一緒にやることもあるが、初期のこのモデルでは別ステップで学習していた


## Transformer Encoder/Decoder Meaning

最近の多くの言語モデルはTransformerのEncoderかDecoderのどちらかのBlockを採用している。

BERTは==Encoderのみ==を使っているが、Openai-GPTは==Decoderのみ==を使っている。
構造的には同じであるが、それぞれが示す意味合いが異なるので解説しておく。

### Transformer Decoder

先に分かりやすい方から。ここで、Decoderという記述は、==Masked== Self-Attention かどうかである。

![](https://i.imgur.com/B0KuCv3.png)

Maskedというのは、Self-Attention 時に未来の単語情報をMaskしている意味である。

![](https://i.imgur.com/KMCqMZ3.png)

次項のOpenAI-GPTで説明するが、Maskするという行為は、==Sequentialな単語生成をする上で重要==である

### Transformer Encoder

未来の単語情報をMaskしないSelf-Attention を使っている、という意味である。
※Padding 情報に関してはどちらもMaskしているので注意。

## OpenAI-GPT(Generative Pre-Training)

BERTを理解するのに、先にこちらを理解しておくと良い。

### 元論文
https://s3-us-west-2.amazonaws.com/openai-assets/research-covers/language-unsupervised/language_understanding_paper.pdf

### Architecture

Transformerの==Decoder== ブロックを１２個繋げた構造を使っている。つまり、学習時は未来の単語情報をMaskしている。

![](https://i.imgur.com/994H9hN.png)

### Pre-Training

Wikipediaのような巨大コーパス内の文章を取り出し、直前のK個の単語から、次の単語を予測する学習を行う。
**BERTは双方向の学習であるが、OpenAI-GPTが順方向の学習しかしていないと言われているのは、この事前学習のためである**

![](https://i.imgur.com/c6c0WcK.png)

![](https://i.imgur.com/3WtnLvI.png)

ちなみに、Transformerでは $sin\theta$と$cos\theta$で Positional Encoding を行っていたが、GPTではそれもNNで学習しているみたい

### Prediction

GPT-3では驚くほどの性能を見せているが、共通しているのは、==言語モデルで文を生成している点==であると言える。

これは、勝手な理解なので鵜呑みにしてほしくないが、Transformer Decoder を用いての学習は、==文を自動生成できる点==にある。

GPTで言うと、==BOS==をGPTに渡せば、とりあえず勝手に文を生成できる。これが、BERTとの明確な違いと思っている。

例）
[状況]何でもいいから文章を作ってほしいとき
[GPT入力①] [BOS] → GPT
[GPT出力①] This(80%), I(15%), ... → This
[GPT入力②] This → GPT
[GPT出力②] is(55%), was(40), ... → was
...

## BERT(Pre-training of Deep Bidirectional Transformers for Language Understanding)
では、いよいよBERT

### Architecture

Transformerの==Encoder== ブロックを使っている。つまり、未来の言語情報をMaskしないSelf-Attentionである。

![](https://i.imgur.com/MhkuKq9.png)

### Bidirectionalとは

GPTやELMo との比較。**この絵が非常に分かりづらかった**。というか、混乱した

![](https://i.imgur.com/ZyL4vAe.png)

これは、BERTが双方向(Bidirectional)な学習ができているという説明の絵である。
まず、注意点として
**Transformerは横には繋がっていない**。これは、RNNとの対比としての説明である

この、$E_i$(Embedding)されたベクトルから出る矢印が全て集まり合っているのは、==未来語をMaskしないSelf-Attention== のためである。

![](https://i.imgur.com/o9WLyes.png)

GPTの場合は、未来をMaskするので、単方向の矢印になっている。

![](https://i.imgur.com/JcH42EM.png)


## Pre-Training

Transformer Encoderを採用した事で、双方向という多様性は獲得できるが、未来の情報を入力することで簡単に訓練がリークしてしまう事に気をつけて、事前学習をする必要がある。
BERTが優れていたのは、この==２種類の事前学習の工夫==にある

### Input

事前学習時のBERTへの入力は次のような規則をつける
* [CLS]を先頭につける
* 文をペアで入力する（２文入力する）
* 文の最後に[SEP]をつける。つまり、必ず２個入る

### Embedding

Token を 1024(Baseは768) dimension に落とした後、２個の値を加算している
* Position Embeddings. Transformer の Positional Encoding と同じ。ただ、これがGPTと同じく学習で獲得しているかは謎
* Segment Embeddings. １文目か２文目かの情報を加算する。値の詳細は謎。これも学習で獲得しているかもしれない.

![](https://i.imgur.com/vzq5k1E.png)

### Masked LM. (pre-training 1)

入力シーケンスから”[CLS]”、”[SEP]”を省いて無作為抽出した15%を以下のように置き換えた上で、置きかえられる前の語は何であったかを予測する

* 80% を “[MASK]” に差し替え
* 10% を ランダムな語彙に差し替え
* 10% はオリジナルのまま（ファインチューニング時は”[MASK]”が発生しない為、その差異を緩和する処理)

![](https://i.imgur.com/DRP9eeb.png)

ここで、GPTとは違い、Transformer Encoderを使っているため、==[MASK]以外の文字とランダム文字以外は簡単に予測できる==事に注意する。
正解ラベルを入力しているので、当然といえば当然である。なので、それらのlossは無視する

### Next Sentence Prediction. (pre-training 2)

学習サンプルの50%をセンテンスA、Bが連続したもの、50%を不連続なものとします。そして、先頭の“[CLS]”に対応する出力から連続／不連続を予測します。

![](https://i.imgur.com/CIUDaia.png)

例えば上図の例では、２つの文章は連続している(=True)なので、BinaryCrossEntropyLoss で２クラス分類しているはず。
これは予想の域を出ないが、おそらく[CLS]に該当するレイヤーをさらに縮めていると思われる。そうすることで、[CLS]箇所の出力には、２文を表す意味のベクトル表現になっているはず

## Fine-Tuning

膨大な量のコーパスから、上の２種類の事前学習を行うことで、言語に関する根本的なものを学んだ言語モデルができあがった。
あとは、それを使って様々なタスクに適応していくだけである。

![](https://i.imgur.com/KooVf6Y.png)

### GLUE

言語モデル（英語限定・・・？）のベンチマーク。
https://gluebenchmark.com/

複数のタスクと、それ用のデータ・セットが用意されている
![](https://i.imgur.com/FceiTMI.png)
https://gluebenchmark.com/tasks

* MNLI 多分類タスク：前提文と仮説文が含意/矛盾/中立のいずれかに分類
* QQP 二値分類タスク：2つの疑問文が意味的に同一かを分類
* QNLI 二値分類タスク：文と質問のペアが渡され、文に答えが含まれるかどうかを分類
* SST-2 二値分類タスク：映画レビューのポジ/ネガの感情分析
* CoLA 多分類タスク：文が文法的に正しいか否かを分類
* STS-B 多分類タスク：2文の類似度を1~5で分類
* MRPC 二値分類タスク：ニュースに含まれる2文が意味的に同じかを分類
* RTE 分類タスク：文書が含意しているか否かを分類

### Fine-Tuning for GLUE Tasks

事前学習で得られたモデルに対して、GLUEそれぞれのタスクに適用してFine-Tuningすることで、それぞれのタスクのベンチマークを出している。
詳細は省くが、BERTが優れている点として、Fine-Tuning時のArchitectureの変更の少なさと言えると思う。

![](https://i.imgur.com/cNPViIb.png)

## SimpleなBERTの使い方

[BERT入力] [CLS] This is [MASK]
[BERT出力] dog(35%), cat(30%), ... → dog