いろは2986023 views
高校化学2913383 views
小学算数1194618 views
MathPython491378 views
世界の国560595 views
高校生物549842 views
高校物理158224 views
中学数学621382 views
高校倫理1433119 views
雑学1472593 views
Help
Tools

English

TensorFlow の損失関数とオプティマイザ

モデルの訓練とは、損失関数が返す値を小さくするようにパラメータを調整する作業にほかならない。損失関数が「どれだけ間違っているか」を測り、オプティマイザが「どう直すか」を決める。この 2 つはモデルの学習能力を左右する重要な要素であり、タスクに合った組み合わせを選ぶことが精度向上の第一歩になる。

損失関数の役割

損失関数はモデルの予測値と正解ラベルの「ズレ」を 1 つの数値にまとめる関数だ。この数値が小さいほど予測が正解に近いことを意味する。訓練ではこの値を最小化する方向にパラメータが更新されていく。

モデルが予測を出力

損失関数が予測と正解のズレを計算

オプティマイザがズレを小さくする方向に重みを更新

損失関数の選択を誤ると、モデルがまったく学習しなかったり、見当違いの方向に最適化されたりする。タスクの種類に応じた正しい選択が不可欠だ。

分類タスクの損失関数

分類タスクでは交差エントロピー(cross entropy)系の損失関数を使う。正解クラスに割り当てられた確率が高いほど損失は小さくなり、低いほど大きくなるという仕組みだ。

binary_crossentropy

2 クラス分類用。出力層のユニット数は 1、活性化関数は sigmoid を使う。メールのスパム判定や病気の陽性 / 陰性判定など、答えが 2 択の場合に選ぶ。

sparse_categorical_crossentropy

多クラス分類用で、ラベルが整数(0, 1, 2, …)の場合に使う。MNIST の手書き数字(0〜9)のように、ラベルがそのまま整数で与えられる場面で便利だ。

categorical_crossentropy

多クラス分類用で、ラベルが one-hot ベクトル([0, 0, 1, 0] など)の場合に使う。sparse 版と数学的には等価だが、ラベルの形式だけが異なる。

sparse と通常版のどちらを使うかは、ラベルの形式で機械的に決まる。整数ラベルなら sparse、one-hot ラベルなら通常版を選べばよい。

2 クラス分類の例

スパム判定のような 2 クラス分類では、出力層に sigmoid を置き、損失関数に binary_crossentropy を指定する。

model = keras.Sequential([
    layers.Dense(64, activation="relu", input_shape=(100,)),
    layers.Dense(32, activation="relu"),
    layers.Dense(1, activation="sigmoid"),
])

model.compile(
    optimizer="adam",
    loss="binary_crossentropy",
    metrics=["accuracy"],
)

sigmoid は出力を 0〜1 の範囲に押し込む関数で、「クラス 1 に属する確率」と解釈できる。0.5 を閾値にして 0 か 1 に分類するのが一般的な使い方だ。

多クラス分類の例

出力層に softmax を置くと、各クラスの確率分布が得られる。すべての出力の合計は 1 になる。

model = keras.Sequential([
    layers.Dense(128, activation="relu", input_shape=(784,)),
    layers.Dense(64, activation="relu"),
    layers.Dense(10, activation="softmax"),
])

model.compile(
    optimizer="adam",
    loss="sparse_categorical_crossentropy",
    metrics=["accuracy"],
)
binary_crossentropy + sigmoid

出力は 1 つの確率値(0〜1)。2 クラス分類専用。

sparse_categorical_crossentropy + softmax

出力はクラス数ぶんの確率分布。多クラス分類に対応。

回帰タスクの損失関数

回帰タスクでは、予測値と正解値の数値的な距離を損失として計算する。

損失関数計算方法特徴
mse誤差の 2 乗の平均外れ値に敏感
mae誤差の絶対値の平均外れ値に頑健
huber小さい誤差は mse、大きい誤差は mae両者の中間的な性質

住宅価格の予測を例にとると、次のようになる。

model = keras.Sequential([
    layers.Dense(64, activation="relu", input_shape=(13,)),
    layers.Dense(32, activation="relu"),
    layers.Dense(1),
])

model.compile(
    optimizer="adam",
    loss="mse",
    metrics=["mae"],
)

回帰の出力層には活性化関数を指定しない。値の範囲に制約を設けず、任意の実数を出力させるためだ。

オプティマイザの役割

損失関数が「現在の誤差」を教えてくれるのに対し、オプティマイザは「パラメータをどの方向にどれだけ動かすか」を決定する。すべてのオプティマイザは勾配降下法を基盤としており、損失関数の勾配(傾き)を手がかりに重みを更新していく。

勾配降下法の基本的な更新式は で表される。 は重み、学習率 は損失の勾配だ。

1 回の更新でパラメータをどれだけ動かすかを制御するハイパーパラメータ。大きすぎると発散し、小さすぎると収束が遅い。

主要なオプティマイザ

SGD(確率的勾配降下法)

もっとも基本的なオプティマイザ。勾配の方向にそのまま重みを更新する。momentum を加えると過去の勾配を考慮し、振動を抑えながら収束を速められる。シンプルなぶん挙動が予測しやすく、学習率のスケジューリングと組み合わせると高い最終精度を出すことがある。

Adam(Adaptive Moment Estimation)

勾配の平均(1 次モーメント)と勾配の 2 乗の平均(2 次モーメント)を使い、パラメータごとに学習率を自動調整する。デフォルト設定のまま幅広いタスクで安定した結果を出すため、最初に試すオプティマイザとして定番になっている。

RMSprop

勾配の 2 乗の移動平均で学習率を調整する。Adam から 1 次モーメントの補正を除いたような構造をしており、RNN 系のタスクで特に有効とされている。

オプティマイザの使い分け

文字列で指定するとデフォルト設定が適用される。ハイパーパラメータを細かく調整したい場合はオブジェクトで渡す。

# 文字列で指定(デフォルト設定)
model.compile(optimizer="adam", loss="mse")

# オブジェクトで指定(学習率を変更)
model.compile(
    optimizer=keras.optimizers.Adam(learning_rate=0.0001),
    loss="mse",
)

# SGD + momentum
model.compile(
    optimizer=keras.optimizers.SGD(learning_rate=0.01, momentum=0.9),
    loss="mse",
)

Adam のデフォルト学習率は 0.001 で、多くのケースではこの値で十分に機能する。精度が伸び悩んだときに 0.0001 や 0.0005 に下げてみるのは有効なアプローチだ。

学習率の影響

学習率はオプティマイザの中でもっとも重要なハイパーパラメータだ。値によって訓練の挙動は大きく変わる。

学習率が大きすぎる場合

損失が振動したり発散したりして、モデルが収束しない。最適解の周囲を飛び越えてしまう。

学習率が小さすぎる場合

損失は安定して下がるが、収束に非常に時間がかかる。局所最適解に捕まりやすくもなる。

学習率を訓練の途中で動的に変化させるスケジューリングという手法もある。たとえば最初は大きめの学習率で素早く収束に近づき、後半で小さくして精密に調整するやり方だ。

lr_schedule = keras.optimizers.schedules.ExponentialDecay(
    initial_learning_rate=0.01,
    decay_steps=1000,
    decay_rate=0.9,
)

model.compile(
    optimizer=keras.optimizers.Adam(learning_rate=lr_schedule),
    loss="sparse_categorical_crossentropy",
    metrics=["accuracy"],
)

ExponentialDecay は指定したステップごとに学習率を指数的に減衰させる。1000 ステップごとに学習率が 0.9 倍になるため、訓練の後半では自動的に細かい調整に切り替わる。

タスク別の推奨設定

最後に、タスクの種類と損失関数・出力層・オプティマイザの典型的な組み合わせをまとめておく。

タスク損失関数出力層
2 クラス分類binary_crossentropysigmoid(1 ユニット)
多クラス分類sparse_categorical_crossentropysoftmax(クラス数)
回帰mse または mae活性化なし(1 ユニット)

オプティマイザは迷ったら Adam から始め、精度が頭打ちになったら学習率の調整や SGD + momentum への切り替えを検討する。損失関数とオプティマイザの正しい選択は、モデルの構造設計と同じくらい訓練の成否を左右する要素だ。

ラベルが整数(0〜9)で与えられる 10 クラス分類で、適切な損失関数はどれか?

  • binary_crossentropy
  • mse
  • sparse_categorical_crossentropy
  • huber
__RESULT__

整数ラベルの多クラス分類には sparse_categorical_crossentropy を使う。one-hot ベクトルに変換してあるなら categorical_crossentropy を選ぶ。binary_crossentropy は 2 クラス専用、mse と huber は回帰タスク向けだ。