なぜ重みの初期化が重要なのか?

ニューラルネットワークは、学習前にランダムな重みを持ちます。この「重みの初期化」が不適切だと、以下のような問題が発生します:

  • 勾配消失・爆発によって学習が進まない
  • 出力がすぐに0や1で飽和し、活性化関数の意味がなくなる
  • 層の役割が固定されてしまい、ネットワーク全体が学習できなくなる

そのため、適切な初期化手法を選ぶことが、深層学習では非常に重要です。


活性化関数の仕組みと重みの関係

ReLU(f(x) = max(0, x))などの活性化関数は、**前の層の出力に対して“通す or 切る”**という判断を行います。
この「出力を活かすかどうか」は、前段の重み付き和(wx + b)に依存しています。

例えば:

# ReLUの例
import torch
x = torch.tensor([-1.0, 0.0, 0.8])
relu = torch.nn.ReLU()
print(relu(x))  # tensor([0.0000, 0.0000, 0.8000])

また、以下は双曲線正接関数 tanh の例です:

# tanhの例
import torch
x = torch.tensor([-1.0, 0.0, 1.0])
tanh = torch.nn.Tanh()
print(tanh(x))  # tensor([-0.7616,  0.0000,  0.7616])

これらの関数の入力値は、重みによって変化します。つまり、重みの初期値が偏っていると、活性化関数の入力が偏ってしまい、学習がスムーズに進まないことがあるのです。

ここの例だと [-1.0, 0.0, 1.0] が重み付き和を計算した結果の値に相当します。

もし初期の重みが偏っていると、この入力値が [-10.0, -20.0, -5.0] といった極端な値になってしまい、ReLU の出力は常に [0.0, 0.0, 0.0]、tanh の出力は常に [-0.999, -0.999, -0.999] のように飽和してしまいます。こうなると、勾配が流れず学習が進まなくなるのです。

なお、活性化関数に入力される「重み付き和」は、層の出力に強く影響します。たとえば、画像の中で犬の足の部分を認識するタスクでは、ある層では足の輪郭が重要でも、別の層ではその情報が重要でないこともあります。このような異なる層での判断を柔軟にするためには、重み付き和が広い範囲で適切に分布していることが必要です。


重み付き和とは?

重み付き和(weighted sum)とは、ニューラルネットワークの各ニューロンで行われる基本的な計算で、以下の式で表されます:

ここで:

  • :入力値(例:画像のピクセルや音声特徴量)
  • :各入力の重み(重要度)
  • :バイアス項

この計算結果 が、ReLUやtanhなどの活性化関数に渡され、最終的な出力が決まります。画像や音声、テキストなど、すべてのAIタスクで使われる基礎処理です。


バイアスも初期化すべき?

はい。通常、初期値0.0で問題がないことが多いですが、バイアスも重みと同様に学習されるパラメータであり、必要に応じて明示的に初期化されることがあります。

多くのケースでは PyTorch によりゼロで初期化されますが、以下のように手動で設定することも可能です:

# バイアスを定数で初期化
nn.init.constant_(layer.bias, 0.0)

一方、重みは活性化関数との相性や勾配消失・爆発の問題を防ぐために、XavierやKaimingなどの手法で明示的に初期化することが多いのが実情です。


よく使われる初期化方法

1. Xavier初期化(Glorot初期化)

中間層がtanhなど対称な活性化関数を使う場合に有効。

import torch.nn as nn
nn.init.xavier_uniform_(layer.weight)

2. Kaiming初期化(He初期化)

ReLU系の活性化関数と相性がよく、最近のモデルで主流。

nn.init.kaiming_normal_(layer.weight, mode='fan_in', nonlinearity='relu')

PyTorchで初期化を適用するには?

自作のモデルに対して、以下のようにapply()を使うと、全層に初期化が可能です。

def init_weights(m):
    if isinstance(m, nn.Linear):
        nn.init.kaiming_normal_(m.weight, mode='fan_in', nonlinearity='relu')
        if m.bias is not None:
            nn.init.constant_(m.bias, 0.0)

model = MyModel()
model.apply(init_weights)

初期化 vs シード固定:違いは?

初期化は「どんな重みやバイアスで学習を始めるか」を決める処理。一方で、シードの固定は再現性のために「毎回同じ乱数を使う」設定です。

import torch, random, numpy as np

def set_seed(seed=42):
    torch.manual_seed(seed)
    random.seed(seed)
    np.random.seed(seed)

初期化の精度検証や比較には、シード固定が必須です。


学習が進まないときにチェックすべきこと

  1. 活性化関数と初期化方法が適切か?
  2. 重みとバイアスの初期化が適用されているか?
  3. シードが固定されているか?(再現性の確認)

まとめ

重みとバイアスの初期化は、モデル学習の「出発点」。スタート地点が偏っていると、ゴールにはたどり着けません。PyTorchでは簡単に設定できるので、自分のモデルに適切な初期化を試してみましょう。

また、活性化関数が意味を持つためには、前段の重み付き和が適切に分布していることが重要です。正しい初期化で、効率の良い学習をスタートさせましょう。

投稿者 kojiro777

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です