クリーム色の背景、色付き表示、高コントラスト、大きな文字のほうが読みやすいですか?配色と文字を選ぶと、すべてのページに一度で反映されます。

無料レッスン

トランスフォーマーのブロックの中身

このレッスンのあとで: 1つのトークンが、トランスフォーマーのブロックの手順を通る様子をたどることができる。

65分のレッスンコマンド2件JupyterLab データサイエンスラボ:pandas、Matplotlib、scikit-learn をブラウザーで

言語モデルがくり返す部品

トランスフォーマーのブロックは、言語モデルを組み立てる単位です。モデルは、同じブロックを何段も積み重ねたものです。ブロックには、複数のヘッドを持つマスク付きの注意と、トークンごとの小さなネットワークがあります。その両方を、近道と大きさの調整が囲みます。

ブロックを1つ理解すれば、モデル全体の形が分かります。

このレッスンのゴール

メモ

1つのトークンが、トランスフォーマーのブロックの手順を通る様子をたどることができる。

キーワード

ことばいみ
因果マスクトークンが後ろのトークンを見ないようにするもの
ヘッド自分のクエリ、キー、バリューの表を持つ1つの注意
フィードフォワード各トークンに1つずつかける小さなネットワーク
残差接続手順の入力をその出力に足すこと
正規化ベクトルの数が一定の大きさに収まるよう調整すること
ブロック注意とフィードフォワードと残差をまとめた、積み重ねる単位

学生が入力するセルは、このプレビューでは空白です。

因果マスクは先を隠す

言語モデルは、次のトークンを当てることを学びます。トークンが自分より後ろを見られたら、答えが見えてしまいます。

そこで因果マスクで、各トークンが自分と前のトークンだけを見るようにします。後ろのトークンの重みは0です。実際には、softmax の前にそのスコアをマイナス無限大にします。e のマイナス無限大乗は0だからです。

例: 先を隠したときの重み

トークンスコア見てよい相手重み
1番目1, 2, 01番目だけ1, 0, 0
2番目2, 1, 11番目と2番目0.731, 0.269, 0
3番目0, 1, 33つすべて0.042, 0.114, 0.844

学生が入力するセルは、このプレビューでは空白です。

Python で先を隠す

コード: python
import math

# scores[i][j]: トークン i のクエリとトークン j のキーの合い具合。
scores = [[1, 2, 0], [2, 1, 1], [0, 1, 3]]

for i in range(3):
    powers = []
    for j in range(3):
        if j <= i:
            powers.append(math.exp(scores[i][j]))
        else:
            # 後ろのトークンは隠すので、重みはまったくありません。
            powers.append(0)
    total = sum(powers)
    weights = []
    for p in powers:
        weights.append(round(p / total, 3))
    print("トークン", i, "重み", weights)
# j <= i を True に変えて(何も隠さずに)実行してください。
# 1番目のトークンの行はどう変わり、なぜそれがずるいのですか。

NumPy で同じマスクをかける

コマンド
docker exec jupyter python3 -c "import numpy as np; S = np.array([[1, 2, 0], [2, 1, 1], [0, 1, 3]], dtype=float); S[np.triu(np.ones((3, 3), dtype=bool), 1)] = -np.inf; W = np.exp(S) / np.exp(S).sum(axis=1, keepdims=True); print(W.round(3).tolist())"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

複数のヘッドは違うものを探す

1つの注意は、1通りの混ぜ方しかできません。そこでブロックでは、複数のヘッドを並べて動かします。ヘッドはそれぞれ、自分のクエリ、キー、バリューの表を持ちます。

あるヘッドは、語を直前の語と結び付けるかもしれません。別のヘッドは、「の」の前後のような、持ち主と持ち物を結び付けるかもしれません。各ヘッドの出力を端から端へつなぎ、学習で決まる表をもう1つかけて、ふつうの長さに戻します。

例: 2つのヘッドをつなぐ

手順トークン 猫 では
ヘッド1の出力7.88, 2.12
ヘッド2の出力1, 3
端から端へつなぐ7.88, 2.12, 1, 3
混ぜる表をかけた後ふつうの長さに戻る

学生が入力するセルは、このプレビューでは空白です。

フィードフォワード、残差、正規化

注意の後、各トークンは1つずつ、小さなフィードフォワードを通ります。ディープラーニングで学んだとおり、間に ReLU をはさんだ2つの層です。

残差接続は、各手順の入力を出力に足すので、すでに分かっていることが失われません。正規化は、各ベクトルの数の平均を0にし、広がりを一定にします。どちらも、深く積んだモデルを学習できるようにします。

例: 残差の後に正規化する

手順数
猫 の入力1, 2
注意の出力7.88, 2.12
残差: 足す8.88, 4.12
正規化: 平均01, -1

学生が入力するセルは、このプレビューでは空白です。

NumPy でベクトルを正規化する

コマンド
docker exec jupyter python3 -c "import numpy as np; x = np.array([2.0, 4.0, 6.0]); print(x.mean(), ((x - x.mean()) / x.std()).round(2).tolist())"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

よくある間違い

注意

フィードフォワードで、トークンどうしがやり取りすると考えがちです。実際は、各トークンに1つずつ働きます。トークンが情報を分け合うのは注意の中だけなので、ほかのトークンの事実は、先に注意で届いている必要があります。

このラボとソースについて: JupyterLab データサイエンスラボ:pandas、Matplotlib、scikit-learn をブラウザーで

授業で使いますか?このモジュールを学生に割り当てると、教員用ガイド、自動採点つきの課題、学生ごとのラボを使えます。