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

無料レッスン

とても小さな言語モデルを学習させる

このレッスンのあとで: 次の文字を当てる小さなモデルを学習させ、その損失を読むことができる。

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

次の文字を当てることを学ぶ

言語モデルは、次のトークンの予測で学習します。次のトークンを当て、正しいものを見て、もっとよく当たるように数を少し動かします。膨大な文章でこれをくり返すことが、学習のすべてです。

ここでは、短い1行でとても小さなモデルを数秒で学習させ、予測がよくなる様子を見ます。

このレッスンのゴール

メモ

次の文字を当てる小さなモデルを学習させ、その損失を読むことができる。

キーワード

ことばいみれい
次のトークンの予測次に来るトークンを当てること
正解実際に次に来るトークンか の後の な
確率モデルが1つのトークンに与える0から1の割合
損失モデルが正解にどれだけ驚いたか
学習の1回すべてのスコアを少しずつ動かすこと
学習率1回に動かす大きさ2.0

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

文章のどの場所も1つの問いになる

「さかな、さかなや、たかな、さかなや、さかな」の1行を使います。読点も1つのトークンです。どの場所でも、問いは「次に何が来るか」です。答えの正解は、文章の次の文字です。

だから21文字から20の問いができ、手で答えを付ける必要はありません。モデルがどんな文章からでも学べるのは、このためです。

例: 最初の6つの問い

場所このトークン正解
0さか
1かな
2な、
3、さ
4さか
5かな

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

このモデルは1つ前のトークンだけを見る

この小さなモデルは、スコアの表です。このトークンごとに1行、次に来うるトークンごとに1列があります。softmax で、1行を確率に変えます。6種類のトークンなので、表のスコアは36個です。

このモデルは、直前のトークンしか見ません。トランスフォーマーは、マスク付きの注意で、前のすべてのトークンを見ます。学習のしかたは同じです。

損失は驚きを測る

1つの問いの損失は、モデルが正解に与えた確率の log にマイナスを付けたものです。自信を持って当てれば、ほとんど0です。正解に小さな確率しか与えなければ、大きくなります。

始めはすべてのスコアが0なので、6種類のトークンがそれぞれ 0.17 ずつ受け取ります。このとき損失は、どの問いでも 1.79 です。

例: 正解の確率と損失

正解に与えた確率損失
1.00
0.90.11
0.50.69
6分の1(約 0.17)1.79
0.12.30

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

学習の1回でスコアを少し動かす

問いごとに、このトークンの行を見ます。その行の各スコアは、自分の確率の分だけ下がります。正解のスコアだけは、さらに1だけ上がります。

この押し具合を20の問いで足し、20で割ります。それに学習率をかけて当てはめます。これが学習の1回です。くり返すと、損失が下がります。

小さなモデルを50回学習させる

コード: python
import math

text = "さかな、さかなや、たかな、さかなや、さかな"
chars = ["、", "か", "さ", "た", "な", "や"]   # 語彙は6種類
pairs = len(text) - 1   # このトークンと次のトークンの組が20
table = []              # スコアはすべて0から
for i in range(6):
    table.append([0.0] * 6)
for step in range(51):
    loss = 0
    for a in range(6):  # 直前のトークンごとに、行を1つずつ直す
        powers = []
        for s in table[a]:
            powers.append(math.exp(s))
        total = sum(powers)
        nudge = [0.0] * 6
        for k in range(pairs):
            if text[k] == chars[a]:
                b = chars.index(text[k + 1])   # 正しい次のトークン
                loss = loss - math.log(powers[b] / total)
                nudge[b] = nudge[b] - 1
                for j in range(6):
                    nudge[j] = nudge[j] + powers[j] / total
        for j in range(6):
            table[a][j] = table[a][j] - 2.0 * nudge[j] / pairs   # 2.0 を 0.5 に変えて試す
        if a == 0:
            sa = powers[2] / total   # 読点の後に さ が来る確率
    if step % 10 == 0:
        print("回", step, "損失", round(loss / pairs, 3), "読点の後の さ", round(sa, 2))

例: 学習が進むと損失はどうなるか

回01020304050
損失1.7920.6420.4500.3800.3450.324

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

よくある間違い

注意

モデルは読んだ文を覚えていて、それを調べていると考えがちです。このモデルが持つのは36個のスコアで、文章は持っていません。学んだのは、か の後にはいつも な が来る、という傾向です。モデルは傾向を数で持ち、だから自信満々に間違えることもあります。

学習の台本をラボに書く

コマンド
docker exec jupyter sh -c "printf '%s\n' 'import numpy as np' 'text = \"sa ka na ten sa ka na ya ten ta ka na ten sa ka na ya ten sa ka na\".split()' 'chars = [\"ten\", \"ka\", \"sa\", \"ta\", \"na\", \"ya\"]' 'ids = np.array([chars.index(c) for c in text])' 'x, y = ids[:-1], ids[1:]' 'W = np.random.default_rng(0).normal(0, 0.1, (6, 6))' 'for step in range(101):' '    p = np.exp(W[x]) / np.exp(W[x]).sum(axis=1, keepdims=True)' '    if step % 25 == 0:' '        print(\"step\", step, \"loss\", round(-np.log(p[np.arange(20), y]).mean(), 3))' '    p[np.arange(20), y] -= 1' '    np.add.at(W, x, -2.0 * p / 20)' 'p = np.exp(W[0]) / np.exp(W[0]).sum()' 'print(\"after ten:\", dict(zip(chars, p.round(2).tolist())))' > steps/tiny.py"

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

種を決めた乱数から学習させる

コマンド
docker exec jupyter python3 steps/tiny.py

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

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

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