Xavier初期化、He初期化
Xavier初期化とHe初期化:ニューラルネットワークの重み初期化手法
ニューラルネットワークを学習させる際、重みの初期化は非常に重要な要素といわれています。
適切な初期化を行わないと、勾配消失問題や勾配爆発問題が発生し、効率的な学習ができません。
今回は、これらの問題を解決する代表的な手法であるXavier初期化とHe初期化について調べてみました。
なぜ重み初期化が重要なのか?
勾配消失・勾配爆発問題
ニューラルネットワークでは、誤差逆伝播法を使用して重みを更新します。しかし、重みの初期値が不適切だと以下の問題が発生します:
- 勾配消失問題: 勾配が層を遡るにつれて指数的に小さくなり、初期層の重みがほとんど更新されない
- 勾配爆発問題: 勾配が層を遡るにつれて指数的に大きくなり、学習が不安定になる
解決のアプローチ
これらの問題を解決するために、各層の出力のばらつき(分散)を適切に保つことが重要です。つまり:
- 順伝播時:各層の出力の分散を一定に保つ
- 逆伝播時:各層の勾配の分散を一定に保つ
Xavier初期化(Glorot初期化)
基本概念
Xavier初期化は、2010年にXavier Glorotらによって提案された手法です。
線形活性化関数や双曲線正接(tanh)関数、シグモイド関数などの対称な活性化関数に適しています。
数学的な導出
記号の定義
まず、使用する記号を定義します:
-
:x^{(l-1)} 層の出力(l-1 層への入力)l -
:W^{(l)} 層の重み行列l -
:z^{(l)} = W^{(l)} x^{(l-1)} 層の線形結合(活性化関数適用前)l -
:y^{(l)} = f(z^{(l)}) 層の出力(活性化関数適用後)l -
:n_{in}^{(l)} 層への入力数l -
:n_{out}^{(l)} 層からの出力数l
基本仮定
Xavier初期化では以下の仮定を置きます:
-
独立性: 入力
と重みx_i は互いに独立W_{ij} -
平均ゼロ:
E[x_i] = E[W_{ij}] = 0 - 同一分布: 同一層内の重みと入力は同じ分布に従う
順伝播の分析
この分散を計算します:
重みと入力が独立なので:
(
重みと入力が同一分布に従うとすると:
順伝播の条件: 各層で分散を保持したい場合:
これより:
逆伝播の分析
逆伝播では、誤差の勾配が各層を遡って伝播されます。
活性化関数が線形またはほぼ線形(勾配≈1)の場合:
したがって:
この分散を計算:
逆伝播の条件: 勾配の分散を保持したい場合:
これより:
Xavier初期化の妥協案
順伝播条件:
逆伝播条件:
両方を同時に満たすことは一般的に不可能なので、Xavierは調和平均を提案:
これは以下の式とも表現できます:
実装方法
一様分布を使用する場合
import numpy as np
def xavier_uniform(n_in, n_out):
limit = np.sqrt(6 / (n_in + n_out))
return np.random.uniform(-limit, limit, (n_in, n_out))
正規分布を使用する場合
def xavier_normal(n_in, n_out):
std = np.sqrt(2 / (n_in + n_out))
return np.random.normal(0, std, (n_in, n_out))
He初期化(Kaiming初期化)
基本概念
He初期化は、2015年にKaiming Heらによって提案された手法です。ReLU系の活性化関数(ReLU、Leaky ReLU、ELUなど)に最適化されています。
なぜXavier初期化では不十分なのか?
ReLU関数は非対称な活性化関数です:
- 入力が正の場合:そのまま出力
- 入力が負の場合:0を出力
この非対称性により、ReLUを使用する場合、Xavier初期化では分散が半分になってしまいます。
数学的な導出
ReLU関数の特性分析
ReLU関数は以下のように定義されます:
重要な特性:
- 非対称性: 負の入力を0にクリップ
-
確率的振る舞い: 入力が正規分布
に従う場合、出力の期待値と分散が変化N(0, \sigma^2)
入力が正規分布に従う場合の分析
入力
期待値:
この積分を計算すると:
分散:
したがって:
近似的に:
He初期化の導出
ここで、
前層の出力が
分散保持条件:
より一般的な分析:fan_in vs fan_out
逆伝播を考慮した場合:
-
fan_in mode: 順伝播を重視 →
\text{Var}(W) = \frac{2}{n_{in}} -
fan_out mode: 逆伝播を重視 →
\text{Var}(W) = \frac{2}{n_{out}}
実際のフレームワークでは用途に応じて選択可能です。
一般化:異なる活性化関数への拡張
He初期化は、活性化関数の「有効な勾配」を考慮して一般化できます:
ここで、
-
ReLU:
\text{gain} = \sqrt{2} -
Leaky ReLU (negative_slope=
):\alpha \text{gain} = \sqrt{\frac{2}{1+\alpha^2}} -
SELU:
\text{gain} = \frac{3}{4}
従って、ReLUの場合:
ただし、一般的な実装では簡略化して
実装方法
一様分布を使用する場合
def he_uniform(n_in, n_out):
limit = np.sqrt(6 / n_in)
return np.random.uniform(-limit, limit, (n_in, n_out))
正規分布を使用する場合
def he_normal(n_in, n_out):
std = np.sqrt(2 / n_in)
return np.random.normal(0, std, (n_in, n_out))
実践的な使い分け
Xavier初期化を使用する場合
- 活性化関数: tanh、sigmoid、線形関数
- ネットワーク: 比較的浅いネットワーク
- 用途: 従来的なフィードフォワードネットワーク
He初期化を使用する場合
- 活性化関数: ReLU、Leaky ReLU、ELU、Swish
- ネットワーク: 深いネットワーク(ResNet、DenseNetなど)
- 用途: 現代的な深層学習モデル
深層学習フレームワークでの実装
PyTorch
import torch.nn as nn
# Xavier初期化
nn.init.xavier_uniform_(layer.weight)
nn.init.xavier_normal_(layer.weight)
# He初期化
nn.init.kaiming_uniform_(layer.weight, mode='fan_in', nonlinearity='relu')
nn.init.kaiming_normal_(layer.weight, mode='fan_in', nonlinearity='relu')
TensorFlow/Keras
from tensorflow.keras.initializers import GlorotUniform, GlorotNormal, HeUniform, HeNormal
# Xavier初期化
initializer = GlorotUniform() # または GlorotNormal()
# He初期化
initializer = HeUniform() # または HeNormal()
# 層に適用
Dense(64, kernel_initializer=initializer)
実験結果の比較
適切な初期化手法を選択することで、以下のような改善が期待できます:
- 収束速度の向上: より少ないエポック数で最適解に到達
- 安定した学習: 勾配の爆発や消失を防止
- 最終精度の向上: より良いローカル最適解への到達
まとめ
重みの初期化は、ニューラルネットワークの学習成功の鍵となる重要な要素です。活性化関数に応じて適切な初期化手法を選択することで、効率的で安定した学習が可能になります。
- 対称な活性化関数(tanh、sigmoid): Xavier初期化
- ReLU系の活性化関数: He初期化
現代の深層学習では、ReLU系の活性化関数が主流であるため、He初期化がデフォルトの選択肢となることが多いです。ただし、具体的な問題やアーキテクチャに応じて、最適な初期化手法を実験的に確認することも重要です。
参考
https://cvml-expertguide.net/terms/dl/optimization/weight-initialization/
Discussion