Xavier初期化 / He初期化 ぐざびえしょきか / へーしょきか
Xavier初期化He初期化Glorot初期化Kaiming初期化重みの初期化活性化関数
Xavier初期化 / He初期化について教えて
簡単に言うとこんな感じ!
重みの初期値を「層の入出力のニューロン数に合わせた適切な分散でランダムに設定する」のがXavier初期化だよ。HeはReLU専用に改良したバージョン。どちらも「信号が大きくなりすぎず・小さくなりすぎず」を実現する賢い初期化なんだ!
Xavier初期化 / He初期化とは
Xavier初期化(グロット初期化) は、2010年にXavier GlorotとYoshua Bengioが提案した初期化手法です。活性化関数にSigmoidやtanhを使う場合に適していて、各層の出力の分散が入力の分散と等しくなるよう重みを設定します。ファンイン(入力数)とファンアウト(出力数)の両方を考慮しています。
He初期化(カイミング初期化) は、2015年にKaiming He(ResNetの開発者)らが提案したReLU向けの改良版です。ReLUは負の値を0にするため、情報の半分が失われます。この「情報の損失分」を補うため、Xavier初期化の約2倍の分散で初期化します。
正しい初期化を使わないと、信号が層を通るたびに指数関数的に縮小(勾配消失)または拡大(勾配爆発)してしまい、深いネットワークでは学習が機能しなくなります。
Xavier / He初期化の数式
| 手法 | 一様分布 | 正規分布(標準偏差) |
|---|---|---|
| Xavier | U(-√(6/(fan_in+fan_out)), +√(6/(fan_in+fan_out))) | √(2/(fan_in+fan_out)) |
| He | U(-√(6/fan_in), +√(6/fan_in)) | √(2/fan_in) |
import torch.nn as nn
import torch
# モデル定義と初期化の例
class MyModel(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(784, 256) # fan_in=784, fan_out=256
self.fc2 = nn.Linear(256, 128)
self.relu = nn.ReLU()
self._initialize_weights()
def _initialize_weights(self):
for m in self.modules():
if isinstance(m, nn.Linear):
# ReLUを使う場合はHe初期化
nn.init.kaiming_normal_(m.weight, mode='fan_in', nonlinearity='relu')
nn.init.zeros_(m.bias)
歴史と背景
- 2010年:Glorotらが「Understanding the difficulty of training deep feedforward neural networks」でXavier初期化を発表
- 2015年:HeらがResNetと同じ論文「Delving Deep into Rectifiers」でHe初期化を発表
- 以後:TensorFlow・PyTorchのデフォルト初期化として実装され、コードを書かなくても自動適用される
- 現在:新しいアーキテクチャ(Transformer等)では論文で個別に初期化方式が指定されることが多い
どちらを選ぶべきか
| 活性化関数 | 推奨初期化 | 理由 |
|---|---|---|
| Sigmoid | Xavier | 対称な出力範囲に適合 |
| tanh | Xavier | Sigmoidと同様 |
| ReLU | He | 負値カットによる情報損失を補正 |
| Leaky ReLU | He(slope考慮) | ReLUに準じる |
| ELU | He | ReLUに近い特性 |
| GELU | Xavier or He | Transformerでよく使用 |
関連用語
- 重みの初期化 — 初期化全般の解説
- 勾配消失 / 勾配爆発 — 初期化が不適切な場合に起きる問題
- ResNet — He初期化の提案者が開発した深層ネットワーク
- 残差接続(Residual Connection) — He初期化と組み合わせて深いネットを実現