ニューラルネットワークの学習を始めるとき、全ての重みの初期値をどう設定すべきでしょうか。「全てゼロ」で初期化するとどうなるか考えてみましょう。全てのユニットが同じ入力を受け取り、同じ出力を出し、同じ勾配で更新されます。つまり、何ユニットあっても実質1ユニットと同じ — これを対称性の破れの失敗と呼びます。
では「ランダムに」初期化すればいいのでしょうか。確かに対称性は破れますが、ランダムの「スケール」を間違えると致命的です。大きすぎると出力が発散して勾配が爆発し、小さすぎると出力がゼロ付近に張り付いて勾配が消失します。100層のネットワークで各層の出力の分散がわずか1.1倍ずつ増えるだけでも、最終層では $1.1^{100} \approx 13{,}781$ 倍に膨れ上がります。
適切な重み初期化は、各層の出力の分散を一定に保つことで、勾配が安定して流れる条件を作り出します。
重み初期化の理論を理解すると、以下のことが可能になります。
- 学習の失敗を防ぐ: 勾配消失・爆発の原因の多くは不適切な初期化に起因する
- 活性化関数との整合性: ReLU、tanh、GELUそれぞれに最適な初期化を選択できる
- 新しいアーキテクチャの設計: カスタムネットワークで初期化スキームを導出できる
- 学習速度の改善: 適切な初期化は学習の収束を大幅に加速する
本記事の内容
- なぜ初期化のスケールが重要か — 分散の伝播
- Xavier初期化(Glorot初期化)の導出
- He初期化の導出 — ReLUへの対応
- 各活性化関数に対する最適な初期化
- Pythonでの実験的検証
前提知識
この記事を読む前に、以下の記事を読んでおくと理解が深まります。
- ニューラルネットワークの基礎 — 多層パーセプトロンの構造
- 活性化関数の全体像 — 各活性化関数の性質
- 誤差逆伝播法の理論と実装 — 勾配消失問題の背景
分散の伝播 — 問題の定式化
セットアップ
$L$ 層の全結合ネットワークを考えます。$l$ 層目のユニット数を $n_l$、入力を $\bm{h}^{(l-1)} \in \mathbb{R}^{n_{l-1}}$、出力を $\bm{h}^{(l)} \in \mathbb{R}^{n_l}$ とします。
$$ \begin{align} z_j^{(l)} &= \sum_{i=1}^{n_{l-1}} w_{ji}^{(l)} h_i^{(l-1)} + b_j^{(l)} \\ h_j^{(l)} &= \sigma(z_j^{(l)}) \end{align} $$
初期化の目標は、ネットワークの順伝播と逆伝播の両方で、信号の分散が層を通じて一定に保たれることです。
基本的な仮定
分析を簡潔にするため、以下を仮定します。
- 重み $w_{ji}^{(l)}$ は互いに独立で、平均0、分散 $\text{Var}[w]$ の同一分布に従う
- バイアス $b_j^{(l)} = 0$(初期値を0とする)
- 入力 $h_i^{(l-1)}$ と重み $w_{ji}^{(l)}$ は独立
- 入力 $h_i^{(l-1)}$ は互いに独立で同一の分散を持つ
活性化関数なしの場合
まず活性化関数を無視して、線形変換 $z_j^{(l)} = \sum_{i} w_{ji}^{(l)} h_i^{(l-1)}$ での分散の伝播を計算します。
$E[w] = 0$ なので
$$ E[z_j^{(l)}] = \sum_{i=1}^{n_{l-1}} E[w_{ji}^{(l)}] \cdot E[h_i^{(l-1)}] = 0 $$
独立性の仮定から、$z_j$ の分散を計算します。$E[w] = 0$ であり、$w$ と $h$ が独立なので
$$ \text{Var}[z_j^{(l)}] = \sum_{i=1}^{n_{l-1}} \text{Var}[w_{ji}^{(l)}] \cdot E[(h_i^{(l-1)})^2] $$
ここで $E[(h_i^{(l-1)})^2] = \text{Var}[h_i^{(l-1)}] + (E[h_i^{(l-1)}])^2$ です。$h_i$ の平均が0の場合は
$$ \text{Var}[z_j^{(l)}] = n_{l-1} \cdot \text{Var}[w] \cdot \text{Var}[h^{(l-1)}] $$
分散を一定に保つ条件 $\text{Var}[z^{(l)}] = \text{Var}[h^{(l-1)}]$ から
$$ \begin{equation} n_{l-1} \cdot \text{Var}[w] = 1 \quad \Rightarrow \quad \text{Var}[w] = \frac{1}{n_{l-1}} \end{equation} $$
これが重み初期化の出発点です。各層の入力ユニット数 $n_{l-1}$ に応じて重みの分散を設定すれば、順伝播で信号の分散が保存されます。
活性化関数を考慮すると、この条件はどう変わるのでしょうか。まず、tanh や シグモイドを使う場合のXavier初期化から導出していきましょう。
Xavier初期化(Glorot初期化)
順伝播での分散保存
Xavier初期化は2010年にGlorotとBengioによって提案されました。tanh やシグモイドなど、原点付近でほぼ線形な活性化関数を対象としています。
活性化関数 $\sigma$ が原点付近で $\sigma(z) \approx z$(線形近似)とみなせるとき、$h_j^{(l)} = \sigma(z_j^{(l)}) \approx z_j^{(l)}$ なので
$$ \text{Var}[h^{(l)}] \approx \text{Var}[z^{(l)}] = n_{l-1} \cdot \text{Var}[w^{(l)}] \cdot \text{Var}[h^{(l-1)}] $$
順伝播で分散を保存するには $n_{l-1} \cdot \text{Var}[w^{(l)}] = 1$ が必要です。
逆伝播での分散保存
逆伝播でも同様の分析ができます。$l$ 層目の誤差信号は
$$ \delta_i^{(l)} = \sigma'(z_i^{(l)}) \sum_{j=1}^{n_{l+1}} w_{ji}^{(l+1)} \delta_j^{(l+1)} $$
$\sigma'(z) \approx 1$(原点付近)とすると
$$ \text{Var}[\delta^{(l)}] \approx n_{l+1} \cdot \text{Var}[w^{(l+1)}] \cdot \text{Var}[\delta^{(l+1)}] $$
逆伝播で分散を保存するには $n_{l+1} \cdot \text{Var}[w^{(l+1)}] = 1$、つまり $\text{Var}[w^{(l)}] = 1/n_l$ が必要です。
順伝播と逆伝播の妥協
順伝播の条件 $\text{Var}[w] = 1/n_{l-1}$ と逆伝播の条件 $\text{Var}[w] = 1/n_l$ は、一般に $n_{l-1} \neq n_l$ のとき両立しません。GlorotとBengioは、両者の調和平均を取ることを提案しました。
$$ \begin{equation} \text{Var}[w^{(l)}] = \frac{2}{n_{l-1} + n_l} \end{equation} $$
これがXavier初期化(Glorot初期化)です。
実装では、以下の2つの方法が使われます。
正規分布版:
$$ w_{ji}^{(l)} \sim N\left(0, \frac{2}{n_{l-1} + n_l}\right) $$
一様分布版:
$$ w_{ji}^{(l)} \sim U\left(-\sqrt{\frac{6}{n_{l-1} + n_l}}, \sqrt{\frac{6}{n_{l-1} + n_l}}\right) $$
一様分布 $U(-a, a)$ の分散は $a^2/3$ なので、$a = \sqrt{6/(n_{l-1} + n_l)}$ とすれば $\text{Var}[w] = 2/(n_{l-1} + n_l)$ が成り立ちます。
Xavier初期化はtanh活性化関数との組み合わせで良好に機能しますが、ReLU活性化関数ではうまくいきません。ReLUは負の入力を0にするため、出力の分散が半分になってしまうからです。
He初期化
ReLUの影響を考慮する
He初期化は2015年にHe, Zhang, Ren, Sunによって提案されました。ReLU活性化関数を使う場合に、Xavier初期化を修正します。
ReLU $\sigma(z) = \max(0, z)$ を適用すると、$z$ が標準正規分布に近い分布に従う場合、負の部分が切り捨てられるため
$$ E[\text{ReLU}(z)^2] = \frac{1}{2} E[z^2] = \frac{1}{2} \text{Var}[z] $$
最初の等号は、$z$ が対称な分布に従うとき、正の部分の二乗平均が全体の半分になることから導かれます。
したがって、ReLU後の分散は
$$ \text{Var}[h^{(l)}] = \frac{1}{2} \text{Var}[z^{(l)}] = \frac{1}{2} n_{l-1} \cdot \text{Var}[w^{(l)}] \cdot \text{Var}[h^{(l-1)}] $$
ここで $E[h^{(l)}] \neq 0$(ReLUの出力は非負)なので、厳密には $E[(h^{(l)})^2]$ を使っています。
He初期化の導出
分散を保存する条件 $\text{Var}[h^{(l)}] = \text{Var}[h^{(l-1)}]$ から
$$ \frac{1}{2} n_{l-1} \cdot \text{Var}[w^{(l)}] = 1 $$
これを解くと
$$ \begin{equation} \text{Var}[w^{(l)}] = \frac{2}{n_{l-1}} \end{equation} $$
これがHe初期化です。Xavier初期化の $1/n_{l-1}$ と比較して、2倍の分散を持ちます。
正規分布版:
$$ w_{ji}^{(l)} \sim N\left(0, \frac{2}{n_{l-1}}\right) $$
一様分布版:
$$ w_{ji}^{(l)} \sim U\left(-\sqrt{\frac{6}{n_{l-1}}}, \sqrt{\frac{6}{n_{l-1}}}\right) $$
Leaky ReLU の場合
Leaky ReLU $\sigma(z) = \max(\alpha z, z)$ の場合、$E[\text{Leaky ReLU}(z)^2] = \frac{1+\alpha^2}{2} E[z^2]$ なので
$$ \text{Var}[w^{(l)}] = \frac{2}{(1 + \alpha^2) n_{l-1}} $$
$\alpha = 0$ のとき He初期化、$\alpha = 1$ のとき Xavier初期化に帰着します。
各活性化関数に対する初期化のまとめ
| 活性化関数 | 推奨初期化 | $\text{Var}[w]$ | PyTorchの関数 |
|---|---|---|---|
| tanh | Xavier | $\frac{2}{n_{l-1} + n_l}$ | nn.init.xavier_normal_ |
| Sigmoid | Xavier | $\frac{2}{n_{l-1} + n_l}$ | nn.init.xavier_normal_ |
| ReLU | He (fan_in) | $\frac{2}{n_{l-1}}$ | nn.init.kaiming_normal_ |
| Leaky ReLU | He (修正版) | $\frac{2}{(1+\alpha^2)n_{l-1}}$ | nn.init.kaiming_normal_ |
| SELU | LeCun | $\frac{1}{n_{l-1}}$ | nn.init.lecun_normal_ (手動) |
| GELU | He に近い | $\frac{2}{n_{l-1}}$ | He初期化を使用 |
活性化関数によって最適な初期化が異なることがわかりました。次に、これらの理論をPythonで実験的に検証してみましょう。
Pythonでの実験的検証
分散の伝播を可視化する
まず、異なる初期化スケールでの分散の伝播を可視化し、理論予測と比較します。
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
# --- 異なる初期化での分散の伝播 ---
n_layers = 20
n_units = 256
n_samples = 1000
def forward_pass(init_scale, activation, n_layers, n_units, n_samples):
"""順伝播で各層の出力分散を記録"""
x = np.random.randn(n_units, n_samples)
variances = [np.var(x)]
for l in range(n_layers):
W = np.random.randn(n_units, n_units) * init_scale
z = W @ x
if activation == "linear":
x = z
elif activation == "sigmoid":
x = 1 / (1 + np.exp(-np.clip(z, -500, 500)))
elif activation == "tanh":
x = np.tanh(z)
elif activation == "relu":
x = np.maximum(0, z)
variances.append(np.var(x))
return variances
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
# (a) 線形ネットワーク: 異なるスケール
ax = axes[0, 0]
scales = [0.5/np.sqrt(n_units), 1.0/np.sqrt(n_units), 2.0/np.sqrt(n_units)]
labels = [r"$0.5/\sqrt{n}$", r"$1/\sqrt{n}$ (Xavier)", r"$2/\sqrt{n}$"]
colors = ["tab:blue", "tab:green", "tab:red"]
for scale, label, color in zip(scales, labels, colors):
variances = forward_pass(scale, "linear", n_layers, n_units, n_samples)
ax.semilogy(variances, "o-", linewidth=2, markersize=3,
color=color, label=label)
ax.set_xlabel("Layer", fontsize=12)
ax.set_ylabel("Variance (log scale)", fontsize=12)
ax.set_title("Linear Network: Effect of Init Scale", fontsize=13)
ax.legend(fontsize=10)
ax.grid(True, alpha=0.3)
# (b) tanh + Xavier vs 不適切な初期化
ax = axes[0, 1]
configs = [
(1.0/np.sqrt(n_units), "tanh", r"Xavier ($1/\sqrt{n}$)"),
(0.01, "tanh", "Too small (0.01)"),
(1.0, "tanh", "Too large (1.0)"),
]
colors = ["tab:green", "tab:blue", "tab:red"]
for (scale, act, label), color in zip(configs, colors):
variances = forward_pass(scale, act, n_layers, n_units, n_samples)
ax.semilogy(variances, "o-", linewidth=2, markersize=3,
color=color, label=label)
ax.set_xlabel("Layer", fontsize=12)
ax.set_ylabel("Variance (log scale)", fontsize=12)
ax.set_title("tanh Network: Xavier vs Others", fontsize=13)
ax.legend(fontsize=10)
ax.grid(True, alpha=0.3)
# (c) ReLU + He vs Xavier
ax = axes[1, 0]
configs = [
(np.sqrt(2.0/n_units), "relu", r"He ($\sqrt{2/n}$)"),
(np.sqrt(1.0/n_units), "relu", r"Xavier ($\sqrt{1/n}$)"),
(0.01, "relu", "Too small (0.01)"),
]
colors = ["tab:green", "tab:orange", "tab:blue"]
for (scale, act, label), color in zip(configs, colors):
variances = forward_pass(scale, act, n_layers, n_units, n_samples)
ax.semilogy(variances, "o-", linewidth=2, markersize=3,
color=color, label=label)
ax.set_xlabel("Layer", fontsize=12)
ax.set_ylabel("Variance (log scale)", fontsize=12)
ax.set_title("ReLU Network: He vs Xavier", fontsize=13)
ax.legend(fontsize=10)
ax.grid(True, alpha=0.3)
# (d) 各層の出力のヒストグラム(ReLU + He初期化)
ax = axes[1, 1]
x = np.random.randn(n_units, n_samples)
layer_indices = [0, 5, 10, 19]
colors_hist = ["tab:blue", "tab:orange", "tab:green", "tab:red"]
for l in range(n_layers):
W = np.random.randn(n_units, n_units) * np.sqrt(2.0 / n_units)
z = W @ x
x = np.maximum(0, z)
if l in layer_indices:
# 正の値のみの分布を表示
positive_vals = x[x > 0].flatten()
ax.hist(positive_vals, bins=50, density=True, alpha=0.5,
color=colors_hist[layer_indices.index(l)],
label=f"Layer {l+1}")
ax.set_xlabel("Activation value", fontsize=12)
ax.set_ylabel("Density", fontsize=12)
ax.set_title("ReLU Activation Distribution (He init)", fontsize=13)
ax.legend(fontsize=10)
ax.grid(True, alpha=0.3)
ax.set_xlim(0, 5)
plt.tight_layout()
plt.savefig("weight_init_variance.png", dpi=150, bbox_inches="tight")
plt.show()
この実験結果から、重み初期化のスケールが分散の伝播に与える影響が明確に確認できます。
-
左上(線形ネットワーク): Xavier初期化 $1/\sqrt{n}$ では分散がほぼ一定に保たれていますが、スケールが小さすぎると分散が指数的に減少(勾配消失)、大きすぎると指数的に増大(勾配爆発)しています。理論通り、$\text{Var}[w] = 1/n$ のとき分散が保存されます
-
右上(tanh + 各初期化): Xavier初期化(緑)は20層を通じて分散を安定に保っています。初期化スケールが小さすぎる場合(青)は出力がすぐに0に近づき、大きすぎる場合(赤)はtanhの飽和領域に入って勾配が消失します
-
左下(ReLU + He vs Xavier): He初期化(緑)は ReLU ネットワークで分散を安定に保っています。Xavier初期化(オレンジ)を ReLU に適用すると、各層で分散が半分に減少していくため、20層では大きく減衰しています。これは ReLU が負の入力を0にすることで出力の二乗平均が半分になるためです
-
右下(ReLU + He初期化の出力分布): He初期化を使った場合、層が深くなっても活性化値の分布がほぼ同じ形を保っています。各層のヒストグラムが重なっていることから、分散の保存が実現されていることが確認できます
学習実験:初期化が収束速度に与える影響
次に、異なる初期化方法が実際の学習にどう影響するかを実験します。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_moons
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
np.random.seed(42)
def sigmoid(z):
return 1 / (1 + np.exp(-np.clip(z, -500, 500)))
class DeepMLP:
"""可変深さのMLP"""
def __init__(self, dims, init_method="he", lr=0.01):
self.Ws = []
self.bs = []
self.lr = lr
for i in range(len(dims) - 1):
n_in, n_out = dims[i], dims[i+1]
if init_method == "he":
scale = np.sqrt(2.0 / n_in)
elif init_method == "xavier":
scale = np.sqrt(2.0 / (n_in + n_out))
elif init_method == "small":
scale = 0.01
elif init_method == "large":
scale = 1.0
else:
scale = np.sqrt(1.0 / n_in)
self.Ws.append(np.random.randn(n_out, n_in) * scale)
self.bs.append(np.zeros((n_out, 1)))
def forward(self, X):
self.hs = [X]
self.zs = []
h = X
for i in range(len(self.Ws)):
z = self.Ws[i] @ h + self.bs[i]
self.zs.append(z)
if i < len(self.Ws) - 1:
h = np.maximum(0, z) # ReLU
else:
h = sigmoid(z) # 出力層
self.hs.append(h)
return h
def backward(self, t):
m = t.shape[1]
delta = self.hs[-1] - t
for i in range(len(self.Ws) - 1, -1, -1):
dW = (1/m) * delta @ self.hs[i].T
db = (1/m) * np.sum(delta, axis=1, keepdims=True)
if i > 0:
delta = (self.Ws[i].T @ delta) * (self.zs[i-1] > 0).astype(float)
self.Ws[i] -= self.lr * dW
self.bs[i] -= self.lr * db
def compute_loss(self, y, t):
eps = 1e-8
return -np.mean(t * np.log(y + eps) + (1-t) * np.log(1-y + eps))
# データ準備
X_data, y_data = make_moons(n_samples=1000, noise=0.2, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(
X_data, y_data, test_size=0.2, random_state=42)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
X_tr = X_train.T
t_tr = y_train.reshape(1, -1)
X_te = X_test.T
t_te = y_test.reshape(1, -1)
# --- 深いネットワーク(8隠れ層)での比較 ---
dims = [2, 64, 64, 64, 64, 64, 64, 64, 64, 1]
init_methods = ["he", "xavier", "small", "large"]
init_labels = ["He init", "Xavier init", "Small (0.01)", "Large (1.0)"]
colors = ["tab:green", "tab:orange", "tab:blue", "tab:red"]
epochs = 3000
fig, axes = plt.subplots(1, 2, figsize=(14, 5.5))
# (a) 損失曲線
ax = axes[0]
results = {}
for method, label, color in zip(init_methods, init_labels, colors):
np.random.seed(42)
model = DeepMLP(dims, init_method=method, lr=0.1)
losses = []
for epoch in range(epochs):
y_pred = model.forward(X_tr)
loss = model.compute_loss(y_pred, t_tr)
model.backward(t_tr)
losses.append(loss)
ax.plot(losses, linewidth=2, color=color, label=label, alpha=0.8)
y_test_pred = (model.forward(X_te) > 0.5).astype(int)
acc = np.mean(y_test_pred == t_te)
results[label] = acc
ax.set_xlabel("Epoch", fontsize=12)
ax.set_ylabel("Loss", fontsize=12)
ax.set_title("Training Loss (8 hidden layers, ReLU)", fontsize=13)
ax.set_yscale("log")
ax.legend(fontsize=10)
ax.grid(True, alpha=0.3)
ax.set_ylim(1e-3, 2)
# (b) テスト精度
ax = axes[1]
bars = ax.bar(results.keys(), results.values(), color=colors, alpha=0.8,
edgecolor="gray", linewidth=1)
for bar, acc in zip(bars, results.values()):
ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.01,
f"{acc:.1%}", ha="center", fontsize=11, fontweight="bold")
ax.set_ylabel("Test Accuracy", fontsize=12)
ax.set_title("Test Accuracy by Init Method", fontsize=13)
ax.set_ylim(0, 1.1)
ax.grid(True, alpha=0.3, axis="y")
plt.xticks(rotation=15)
plt.tight_layout()
plt.savefig("weight_init_learning.png", dpi=150, bbox_inches="tight")
plt.show()
この学習実験の結果から、初期化方法が深いネットワークの学習に決定的な影響を与えることがわかります。
-
損失曲線(左図): He初期化(緑)は最も速く損失を減少させており、学習が順調に進んでいます。Xavier初期化(オレンジ)はReLUネットワークでは若干遅いですが、最終的にはある程度の損失まで下がります。小さすぎる初期化(青, 0.01)は勾配消失のため学習が極めて遅く、大きすぎる初期化(赤, 1.0)は最初から不安定で学習が進みません
-
テスト精度(右図): He初期化が最も高い精度を達成しています。ReLUネットワークにはHe初期化が理論的に正しい選択であることが、実験的にも裏付けられています。不適切な初期化では精度が大幅に低下するか、学習自体が失敗します
実装上のポイント
PyTorchでの初期化
PyTorchでは torch.nn.init モジュールを通じて各種初期化を利用できます。
import numpy as np
# PyTorchでの初期化例(概念的なコード)
# import torch
# import torch.nn as nn
#
# layer = nn.Linear(256, 128)
#
# # He初期化(ReLU用)
# nn.init.kaiming_normal_(layer.weight, mode='fan_in', nonlinearity='relu')
#
# # Xavier初期化(tanh用)
# nn.init.xavier_normal_(layer.weight)
#
# # バイアスはゼロ初期化
# nn.init.zeros_(layer.bias)
# NumPyでの同等実装
n_in, n_out = 256, 128
# He初期化(fan_in モード)
W_he = np.random.randn(n_out, n_in) * np.sqrt(2.0 / n_in)
# Xavier初期化
W_xavier = np.random.randn(n_out, n_in) * np.sqrt(2.0 / (n_in + n_out))
print(f"He init: Var(W) = {np.var(W_he):.6f}, "
f"理論値 = {2.0/n_in:.6f}")
print(f"Xavier init: Var(W) = {np.var(W_xavier):.6f}, "
f"理論値 = {2.0/(n_in+n_out):.6f}")
このコードの出力から、実際の分散が理論値にほぼ一致していることが確認できます。初期化の理論が正しく機能していることの簡易的な検証です。
fan_in vs fan_out
He初期化の mode パラメータは、入力ユニット数(fan_in)と出力ユニット数(fan_out)のどちらを使うかを指定します。
fan_in(デフォルト): 順伝播で分散を保存。推論時の安定性を重視fan_out: 逆伝播で分散を保存。学習時の勾配の安定性を重視
実用的には fan_in がデフォルトで、多くの場合これで十分です。
BatchNormとの関係
BatchNormを使うと、各層の出力が強制的に平均0・分散1に正規化されるため、初期化の影響が大幅に緩和されます。BatchNormが一般化した現代のネットワーク設計では、初期化の選択がモデル性能に与える影響は相対的に小さくなっています。
ただし、BatchNormなしで深いネットワークを学習する場合(例: ResNet without BN, SELU ネットワーク)や、BatchNormの初期の学習段階では、適切な初期化は依然として重要です。
まとめ
本記事では、ニューラルネットワークの重み初期化の理論をXavier初期化からHe初期化まで導出しました。
- 重み初期化の目標は各層の出力分散を一定に保つことであり、これにより勾配消失・爆発を防ぐ
- Xavier初期化: $\text{Var}[w] = 2/(n_\text{in} + n_\text{out})$。tanh やシグモイド(原点付近で線形に近似できる活性化関数)に最適
- He初期化: $\text{Var}[w] = 2/n_\text{in}$。ReLU が負の入力を0にすることで出力分散が半分になる効果を補正
- 不適切な初期化(小さすぎ・大きすぎ)は深いネットワークで学習を完全に失敗させ得る
- BatchNormは初期化の影響を緩和するが、BNなしの場合は適切な初期化が必須
次のステップとして、以下の記事も参考にしてください。
- BatchNorm vs LayerNorm — 正規化層による学習の安定化
- ResNetとスキップ接続 — 深いネットワークの学習を可能にする残差接続
- 過学習の対策まとめ — 正則化との組み合わせ