numpy で線形回帰
最も単純な問題、面積から住宅価格を予測することから始めます。一本の直線をモデルにし、平均二乗誤差で良し悪しを測り、最も愚直な方法で 9 万本の直線を一本ずつ試して、「学習」がいったい何を探しているのかをはっきり見ます。
- 約 35 分
- 難易度:入門
- 検証:2026-09-14 numpy 2.5、乱数シード固定
コードと実行結果は実際に動かしたときのまま載せているため、コメントと出力は中国語です。
第 1 部では、ずっと学習済みの LLM を使ってきました。第 2 部では一つの問いに答えます。モデルはどうやって学習されるのか。
最も単純な例から始めます。ニューラルネットワークでも LLM でもなく、ただの一本の直線です。侮らないでください。この後の数課のすべての概念、損失、勾配、学習率、誤差逆伝播法は、どれもまずこの直線ではっきり見ることができ、それからそのままニューラルネットワークに、最後には GPT に使えます。
この課に必要なのは numpy だけです。
uv add numpy
問題:面積から住宅価格を予測する
50 軒の家の面積と成約価格を集めたとします。そこから規則を見つけ出して、今後家の面積を見れば価格を見積もれるようにしたいのです。
データは自分で作ります。そうすれば「正解」がわかっているので、確かめやすくなります。
import numpy as np
rng = np.random.default_rng(0)
# 造一组数据:房价(万元)= 1.2 × 面积(平方米)+ 20,再加上一些随机的波动
area = rng.uniform(40, 150, size=50)
price = 1.2 * area + 20 + rng.normal(0, 12, size=50)
default_rng(0) で乱数のシードを固定しているので、あなたが実行して得るデータは私のものとまったく同じです。本当の規則は「1 平方メートルあたり 1.2 万元、それに 20 万元を足す」ですが、どの家にも少しランダムなずれ(標準偏差 12 万元)があります。現実でも向き、階数、内装で価格が上下するのと同じです。(コードでの価格の単位は万元です。)
最初の 5 軒はこうなっています。
前 5 套房子:
110.1 平方米 156.4 万元
69.7 平方米 89.1 万元
44.5 平方米 73.4 万元
41.8 平方米 78.1 万元
129.5 平方米 159.9 万元
モデル:一本の直線
最も単純な推測は、価格と面積の間に直線の関係があるというものです。
预测价格 = w × 面积 + b
w は傾きで、1 平方メートル増えるごとに価格がいくら上がるかを表します。b は切片で、面積が 0 のときの価格(固定の基本価格と考えられます)を表します。この二つの数をモデルのパラメータと呼びます。
def predict(w, b, x):
"""模型:一条直线。w 是斜率(每平方米多少万),b 是截距。"""
return w * x + b
「モデルを学習させる」とは、つまるところ最もよいパラメータの組を探すことです。このモデルでいえば、最もよい w と b を探すことです。
GPT のような LLM も同じで、ただパラメータが 2 個ではなく数十億、数千億個あり、モデルも直線ではなく極めて複雑な関数です。モジュール 09 では 100 万個を超えるパラメータを持つ小さな GPT を自分の手で学習させますが、本質的にしていることはやはりこれです。
損失:「よい」をどう測るか
「最もよい直線」とは何でしょうか。具体的で、数字として計算できる基準が必要です。
家ごとに、モデルは予測価格を出し、それと本当の価格の間には差があります。すべての差を二乗して平均を取った数を、平均二乗誤差(Mean Squared Error、MSE)と呼びます。
均方误差 = 平均值( (预测价格 - 真实价格)² )
def mse(w, b):
"""损失:预测值和真实值之差的平方,取平均。"""
errors = predict(w, b, area) - price
return np.mean(errors ** 2)
なぜ二乗するのでしょうか。理由は二つあります。一つ目に、差にはプラスもマイナスもあり、そのまま平均すると打ち消し合ってしまいますが、二乗すればすべてプラスになります。二つ目に、二乗すると大きな誤差がより「目立ち」ます。差が 10 なら二乗は 100、差が 30 なら二乗は 900 です。モデルは、とんでもなく外れている点を優先して面倒を見ざるをえなくなります。
この「モデルがどれだけ悪いか」を測る数を、まとめて損失(loss)と呼びます。損失が小さいほど、モデルはよいのです。学習の目標はもっと正確に言えます。損失が最も小さくなるパラメータを探すことです。
適当にいくつか推測する
まず直感でいくつか w と b の組を推測し、損失がいくつになるか見てみます。
for w, b in [(1.0, 0.0), (1.0, 30.0), (1.5, 0.0), (1.2, 20.0)]:
print(f" w={w:<4} b={b:<5} 均方误差 {mse(w, b):9.1f}")
随手猜几条直线,看看误差:
w=1.0 b=0.0 均方误差 1810.1
w=1.0 b=30.0 均方误差 310.8
w=1.5 b=0.0 均方误差 284.5
w=1.2 b=20.0 均方误差 146.6
w=1.0, b=0 の直線はデータから遠く離れていて、損失は 1810 です。切片を 30 万足すと、損失は 311 に下がります。w=1.2, b=20 はデータを作るのに使った本当の規則そのもので、損失はわずか 146.6 です。
本当の規則でも損失は 0 にならない点に注意してください。データにランダムな揺らぎがあるので、どんな直線もすべての点を通ることはできません。損失は決して 0 まで下がりません。これは実際の問題ではごく普通のことです。
最も愚直な方法:全部試す
損失が計算できるなら、ありうる w と b を全部試して、損失が最も小さい組を選べばよいのです。w は 0 から 3 まで 0.01 刻みで、b は -50 から 100 まで 0.5 刻みで試します。
best = (None, None, float("inf"))
tries = 0
for w in np.arange(0.0, 3.0, 0.01):
for b in np.arange(-50.0, 100.0, 0.5):
tries += 1
loss = mse(w, b)
if loss < best[2]:
best = (w, b, loss)
网格搜索:试了 90000 条直线,用了 0.2 秒
最好的一条:w=1.26 b=14.5,均方误差 143.1
9 万本の直線を試して見つかった最もよい一本は w=1.26, b=14.5 で、損失は 143.1、本当の規則(w=1.2, b=20)の 146.6 より少し低いくらいです。これは不思議ではありません。データ点は 50 個しかなく、しかもランダムな揺らぎがあるので、この 50 点に最もよく当てはまる直線が、それを生成した直線と一致するとは限らないのです。
見つかった w と b が本当の値と完全には一致しないということは、この先ずっとついて回ります。モデルが学ぶのは「目の前のデータを最もよく説明できる」パラメータで、データに偏りがあれば、学んだパラメータにも偏りが出ます。
グリッドサーチには目立たない問題がもう一つあります。格子の上の点しか見つけられないことです。w を 0.01 刻みで試すなら、本当に最もよい w が 1.2571 でも、1.26 しか出せません。格子を細かくすれば、試す回数は何倍にも増えます。次の課の勾配降下法にはこの制限がなく、最もよい値にどこまでも近づいていけます。
この方法ではなぜだめなのか
パラメータが 2 個で、それぞれ数百の値を試せば、9 万通りの組み合わせで、0.2 秒かかりました。
パラメータが 3 個なら数千万通りの組み合わせになり、10 個なら組み合わせの数は天文学的な数字になって、宇宙の寿命でも試しきれません。最小のニューラルネットワークでも数十から百個以上のパラメータがあり、モジュール 09 の小さな GPT には 100 万個を超えるパラメータがあります。
ずっと賢い方法が必要です。やみくもに試すのではなく、一歩ごとにパラメータをどちらの方向にどれだけ変えればよいかがわかる方法。それが次の課の勾配降下法です。
練習問題
- データのランダムな揺らぎを 12 から 0 に変えて(
rng.normal(0, 0, size=50))実行し直してください。最もよい直線はちょうどw=1.2, b=20になりますか。損失はいくつですか。 - 損失関数を「平均絶対誤差」
np.mean(np.abs(errors))に替えてもう一度グリッドサーチをしてください。見つかった直線は、平均二乗誤差で見つけたものと同じですか。 - データに極端な点を一つ加えてください。60 平方メートルの家が 500 万元で売れた(
area = np.append(area, 60); price = np.append(price, 500))。平均二乗誤差と平均絶対誤差でそれぞれグリッドサーチをすると、どちらがこの点の影響をより大きく受けますか。なぜでしょうか。
確認テスト
1. 「モデルを学習させる」とは何を指しますか?
最もよいパラメータの組を探し、手元のデータでのモデルの損失を最も小さくすることです。一本の直線なら、最もよい傾き w と切片 b を探すことです。LLM も同じで、ただパラメータの数がずっと多く、モデルの形がずっと複雑なだけです。
2. 平均二乗誤差では、なぜ誤差をそのまま平均するのではなく、二乗するのですか?
誤差にはプラスもマイナスもあり、そのまま平均すると打ち消し合って、とても悪いモデルでも平均誤差が 0 に近くなることがあります。二乗すればすべてプラスになり、しかも大きな誤差ほど大きく拡大されるので、モデルはとんでもなく外れた予測を優先して減らすようになります。
3. この例ではグリッドサーチに 0.2 秒しかかかりませんでした。なぜニューラルネットワークの学習には使えないと言えるのですか?
試すべき組み合わせの数が、パラメータの数に対して指数関数的に増えるからです。パラメータ 2 個で 9 万通り、3 個なら数千万通りになり、ニューラルネットワークには数百、数千、さらには数十億のパラメータがあるので、組み合わせの数は天文学的な数字になり、到底試しきれません。
質問と議論
このレッスンでつまずいたところは、ここで質問してください。他の人の質問に答えるのも歓迎です。
質問で 3 ポイント、回答で 6 ポイント。審査を通過すると公開されます。
議論を読み込んでいます…