ひとことで言うと
BERTの事前学習は、ラベルなしテキストから「周囲の文脈を使って欠けた語を当てる」MLMと、「2つのテキストスパンが続いているかを判定する」NSPを同時に学ばせる設計です。ポイントは、単語を左から右へ生成する目的ではなく、入力の一部を壊して復元させることで、左右の文脈を同時に使わせることです。
校正前の文章を渡し、数か所だけ伏せ字にして復元させる作業に似ています。伏せ字の位置を当てるだけではなく、前後の語、文章どうしのつながりまで使わないと解けないように、課題を二段に分けて設計しています。
なぜ必要か
通常の言語モデルは、次の語を予測するなら左側だけ、前の語を予測するなら右側だけを見るという方向制約を持ちます。両側を自由に見せると、予測対象の語そのものが隠れた経路から入力に入り、答えを見て答える課題になります。BERTの狙いは、Transformerの自己注意で左右を同時に参照できる表現を作ることでした。そのために、正解語を入力から除いた位置だけを予測対象にします。
ただし、入力から正解語を必ず同じ記号へ置き換えると、別の問題が生まれます。事前学習では [MASK] を見るのに、下流タスクの入力には通常その記号が現れません。これが pre-train/fine-tune の不一致です。原論文は、予測対象を15%の位置に絞ったうえで、その全てを同じ形にはせず、実際の入力に近い場合も混ぜて影響を和らげました。つまりマスク率は、計算量の都合だけでなく、双方向性と入力分布の折り合いで決まります。
文単位の言語モデルだけでは、質問と文章、前提と仮説のような二つのスパンの関係を直接課題にできません。そこでNSPを加え、文脈が連続しているかを二値分類させます。MLMがトークン内部の関係を、NSPがスパン間の関係を担当するという分担です。
| 課題 | 直接学ばせたい関係 | 入力に対する操作 |
|---|---|---|
| MLM | トークンと左右の文脈 | 一部の位置を変換して元の語を予測 |
| NSP | 二つのテキストスパンの連続性 | 後続スパンとランダムスパンを二値分類 |
仕組み
まずコーパスから二つのテキストスパンA、Bを取り、WordPieceトークン化した後に、合計長が512トークン以下になるよう一つの学習例を作ります。BはAの実際の後続スパンである場合と、コーパス中から無関係に選んだスパンである場合を半分ずつにします。この二値ラベルがNSPの教師です。特殊トークンや埋め込みの構成そのものは隣接ノートの範囲なので、ここではタスク用の入力を作る順序だけに注目します。
MLMでは、トークン位置の集合 を全体の15%から一様に選びます。入力トークン列を 、位置 の正解トークンを 、モデルが出す語彙分布を とすると、損失は選ばれた位置だけで計算します。
はモデルのパラメータ、 は一部を変換した入力、 は予測対象位置の集合です。全トークンを復元するデノイジングではなく、選んだ15%だけを予測する点が重要です。選ばれなかった位置の出力を損失に入れないため、1バッチで得られる教師信号は少なく、論文も左から右へ全語を予測する場合より収束がやや遅くなると述べています。
選ばれた位置の変換は次の比率です。80%は [MASK]、10%はランダムなトークン、残り10%は元のトークンをそのまま入力します。いずれの場合も、正解ラベルは元の です。元の語を残す例は一見すると自己参照に見えますが、どの位置が予測対象かをモデルには知らせません。したがって、全入力について文脈表現を作る必要があり、[MASK] だけに特化するのを避けます。ランダム置換の実効割合は全トークンの1.5%です。
NSPの損失を とすると、論文の事前学習損失は二つの平均尤度に対応する項の和です。
ここでNSPの正例はBがAの直後、負例はコーパスからランダムに選んだBです。入力生成、マスク、二つの損失の計算をこの順に分けて考えると、マスク対象のラベルとNSPラベルを混同しません。
試験でどう問われるか
| 問われ方 | 正解に寄る条件 | 引っかけ |
|---|---|---|
| MLMでマスクする理由 | 双方向に条件付けすると正解語を見てしまうため、予測位置を入力から壊す | 単に語彙を減らすため/左から右の生成を速くするため |
| MLMの予測対象 | 全体の15%を選び、選択位置の正解トークンだけで損失を計算する | 全トークンを復元する/15%を [MASK] にする |
| 80/10/10の意味 | [MASK]、ランダム語、元の語をそれぞれ入力に使う比率 | ラベルを80/10/10で変える |
| pre-train/fine-tune不一致 | [MASK] が下流入力に現れない問題を混合置換で緩和する | 不一致はNSPが作るとする |
| NSPのデータ生成 | Aの実際の後続BとランダムなBを50%ずつ作る | 常に実際の後続文を使う/文の長さを当てさせる |
実装で確かめる
次のコードは、トークン列から15%の位置を選び、論文の比率で入力を変換します。乱数シードを固定しているため、表示される対象位置と変換後の列は実行結果と一致します。実際のWordPiece分割やモデルの損失までは含めず、入力作成の境界を確認する最小例です。
import numpy as np
rng = np.random.default_rng(7)
tokens = np.array(["the", "model", "reads", "both", "sides", "here", "!"])
chosen = rng.choice(len(tokens), size=1, replace=False)
masked = tokens.copy()
for i in chosen:
r = rng.random()
if r < 0.8:
masked[i] = "[MASK]"
elif r < 0.9:
masked[i] = rng.choice(tokens)
print("target:", chosen.tolist())
print("input:", masked.tolist())
この処理で保持している tokens[i] が正解ラベルで、masked[i] がモデルに見せる入力です。元の語を残す分岐でもラベルは変更しません。実装で最も起きやすい誤りは、置換後の値を正解として保存してしまうこと、または選ばれていない位置までMLM損失に含めることです。
取り違えやすいもの
| 手法・概念 | 事前学習タスクとの違い |
|---|---|
| 左から右の言語モデル | 各位置の予測時に右側を見ない。自己参照は避けやすいが、MLMのような左右同時の条件付けではない |
| デノイジングオートエンコーダ | 壊した入力全体の復元を目指す。BERTのMLMは選択した位置だけを予測する |
| ランダム置換 | 80/10/10の一部であり、独立した学習タスクではない。正解ラベルは常に元のトークン |
| NSP | 文中の欠損語ではなく、二つのスパンの順序・連続性を二値で学ぶ |
| ファインチューニング | 事前学習済み表現を下流ラベルで調整する段階。MLMとNSPの教師をそのまま使う段階ではない |
想起チェック
双方向の言語モデルで正解語をそのまま入力すると何が起きるか
左右の文脈から対象語へ情報が流れ、モデルが正解を間接的に見てしまいます。そこで対象位置を壊してから元の語を予測させます。
15%と80/10/10はそれぞれ何の比率か
15%は予測対象として選ぶ位置の割合です。80/10/10は、選ばれた位置を [MASK]、ランダム語、元の語のどれで入力するかの割合で、ラベルの割合ではありません。
NSPの正例と負例はどう作るか
Aの実際の後続スパンをBにする正例と、コーパスからランダムに選んだBにする負例を、50%ずつ作ります。
MLM損失に全トークンを入れない理由は何か
正解を隠した選択位置だけを予測する課題だからです。選ばれていない位置まで損失に入れると、MLMではなく入力全体の再構成に近い別の目的になります。