本文へスキップ
ひもとくAI

過学習と過少適合:バイアスとバリアンス

レッスン 1/7

この章で学ぶこと:訓練データでよくても、新しいデータで悪いとき

第5章で、訓練データを丸暗記してしまい、新しいデータで正解率が下がる 過学習 を学びました。第6・7章では、ニューラルネットワークを学習させました。この章では、なぜ過学習が起きるのか、どうすれば防げるのか、そして 学習をどうすれば速く、安定して進められるのか を、実験の数値を根拠に学びます。

実験:少ない点に、曲線を当てはめる

本当の関係は y=sin⁡xy = \sin x という波の形で、そこに誤差(ばらつき)が加わった15個の点があるとします。sin⁡x\sin x は、xx が0から大きくなるにつれて、0 → 1 → 0 → −1 → 0 と波のように変わる関数です(式の中身は、この章では気にしなくてかまいません)。この15点から、元の波の形を当てはめることを考えます。

当てはめる式として、次の 多項式 を使います。

  • 1次式: y=a1x+a0y = a_1 x + a_0(第4章の直線)
  • 2次式: y=a2x2+a1x+a0y = a_2 x^2 + a_1 x + a_0(中学3年の放物線に、直線と数を足したもの)
  • 3次式: y=a3x3+a2x2+a1x+a0y = a_3 x^3 + a_2 x^2 + a_1 x + a_0

xx を何乗まで使うかを 次数 と呼びます。次数を上げるほど、曲線はくねくねと曲がれるようになります。係数 a0,a1,…a_0, a_1, \ldots は、第4章と同じく、訓練データの誤差の2乗の平均が最も小さくなるように決めます(このような決め方を 最小二乗法 と呼びます)。

xy0123456-2-1012
  • 1次式
  • 3次式
  • 9次式
15個の点(○)に、1次式・3次式・9次式を当てはめた曲線。1次式は右下がりの直線で、点の波の形を表せていない。3次式は点の間をなめらかに通る波の形。9次式は点の近くを通るが、点のない0.5〜1.5のあたりで、どの点よりも高い2.0まで大きくふくらみ、最後の点より右(5.7〜6)では急に跳ね上がっている

訓練誤差とテスト誤差

当てはめに使った15点での誤差を 訓練誤差、当てはめに使っていない別の200点での誤差を テスト誤差 と呼びます(どちらも、誤差の2乗の平均)。

次数訓練誤差テスト誤差
1次式0.2080.403
3次式0.0250.128
9次式0.0180.367
14次式0.000約1億5000万

(14次式は、点のない場所で値がグラフの上下の端の1万倍以上まで飛び出してしまうため、図には9次式を描いています)

次数を上げるほど、訓練誤差は小さくなり、14次式では0になりました(15個の係数で、15点をすべて通れるため)。ところが、テスト誤差は3次式が最も小さく、14次式では爆発しています。

新しいデータでの誤差を 汎化誤差(はんかごさ)と呼びます。機械学習の目的は、訓練誤差ではなく、汎化誤差を小さくすることです。テスト誤差は、汎化誤差を見積もったものです。

過学習と過少適合、バイアスとバリアンス

前のスライドの3つの式は、それぞれ次の状態にあります。

  • 1次式: 過少適合(かしょうてきごう)。式が単純すぎて、訓練データの波の形さえ表せていない。訓練誤差もテスト誤差も大きい
  • 3次式: ちょうどよい。訓練誤差は少し残るが、テスト誤差が最も小さい
  • 14次式: 過学習(過剰適合とも呼ぶ)。訓練データの誤差(ばらつき)まで覚えてしまい、訓練誤差は0なのに、テスト誤差がとても大きい

実験:データが少し変わると、当てはめはどう変わるか

15点の xx はそのままで、誤差(ばらつき)だけを変えたデータを20通り作り、それぞれに当てはめ直しました。x=3x = 3 での予測を比べます。本当の値は sin⁡3≈0.141\sin 3 \approx 0.141 です。

次数20回の予測の平均20回の予測のばらつき(標準偏差)
1次式−0.33-0.330.08
3次式0.1370.12
14次式7754091

(標準偏差は、第3章で学んだ「ばらつきの大きさ」です)

  • 1次式 は、毎回ほとんど同じ予測をします(ばらつき0.08)。ところが、平均が −0.33-0.33 で、本当の値0.141から大きくずれています。何度やり直しても、同じ方向に外れます
  • 14次式 は、平均も本当の値からかけ離れていて、しかもデータが少し変わるだけで、予測が −7931 から 9634 まで激しく変わりました

この2種類の外れ方には、名前があります。

  • バイアス: 平均して、本当の値からどれだけずれているか。モデルが単純すぎると大きくなる(1次式)
  • バリアンス: データが変わったとき、予測がどれだけばらつくか。モデルが複雑すぎる(自由に曲がれすぎる)と大きくなる(14次式)

汎化誤差は、おおまかに「バイアスによる誤差」と「バリアンスによる誤差」と「データそのものの誤差(どんなモデルでも消せない)」を合わせたものになります。モデルを複雑にするとバイアスは減りますが、バリアンスが増えます。この バイアスとバリアンスのトレードオフ(片方を減らすと、もう片方が増える関係)の、ちょうどよいところを探すのが、モデル作りです。

データを増やすと、過学習は減る

バリアンスは、データが少ないほど大きくなります。第6章の手書き数字で、隠れ層128個のネットワークの訓練データの枚数を変えると、次のようになりました。

訓練データの枚数501002004008001347
訓練データでの正解率1.0001.0001.0001.0001.0001.000
テストデータでの正解率0.8440.9220.9510.9640.9710.980

どの枚数でも、訓練データは全問正解しています。それでも、枚数が増えるほどテストの正解率が上がり、訓練との差(過学習の度合い)が小さくなります。データを増やすことは、過学習への最も確実な対策です。ただ、データを集めるのは大変なので、次のレッスンからは、データを増やさずに過学習を防ぐ方法を学びます。

Pythonで確かめる、よくある誤解と振り返り

NumPyの np.polyfit を使うと、多項式の当てはめを1行で計算できます。

import numpy as np

x = np.array([0.02, 0.10, 0.20, 0.25, 1.62, 3.26, 3.64, 3.82,
              4.38, 4.38, 4.88, 4.90, 5.14, 5.48, 5.61])
y = np.array([-0.20, -0.06, 0.11, 0.37, 1.31, -0.16, -0.07, -0.83,
              -0.84, -0.67, -0.96, -1.21, -1.18, -0.86, -0.56])

coefs = np.polyfit(x, y, 3)        # 3次式を当てはめる(係数は、次数の高い方から並ぶ)
pred = np.polyval(coefs, x)        # 当てはめた式で、x での値を計算する
train_error = np.mean((pred - y) ** 2)
print(train_error)                 # → 約0.025(前のスライドの表と同じ)
  • np.polyfit(x, y, 次数) は、誤差の2乗の平均が最も小さくなる係数を求めます。第4章の線形回帰と同じ考え方を、曲線に広げたものです
  • np.polyval(係数, x) は、求めた式に xx を入れた値を計算します
  • テスト誤差を求めるときは、当てはめに使っていない点で np.polyval を計算して、同じように誤差の2乗の平均をとります

機械学習でどう使われるか

ニューラルネットワークでも、まったく同じことが起きます。層やニューロンを増やすと、どんな形でも表せるようになる(バイアスが減る)一方で、データが少ないと過学習しやすくなります(バリアンスが増える)。第7章のCNNが、少ない重みで普通のニューラルネットワークと同じくらいの正解率を出せたのは、重みの共有で「画像に合った決まり」を組み込み、バリアンスを抑えていたからだと考えられます。

よくある誤解

  • 「訓練誤差が小さいほど、よいモデル」: 14次式の訓練誤差は0でしたが、テスト誤差は爆発しました。モデルのよさは、訓練に使っていないデータで測ります
  • 「複雑なモデルほど、よいモデル」: 複雑にするとバイアスは減りますが、バリアンスが増えます。データの量に見合った複雑さが必要です
  • 「過学習するのは、ニューラルネットワークだけ」: 多項式でも、決定木(第5章)でも、どんなモデルでも起きます

振り返り

  • 訓練誤差は小さいのにテスト誤差が大きいのが過学習、どちらも大きいのが過少適合
  • バイアスは「平均して、どれだけずれるか」、バリアンスは「データが変わると、どれだけばらつくか」。モデルを複雑にすると、バイアスは減りバリアンスは増える
  • データを増やすと、過学習は減る

演習

演習を読み込んでいます…