Dense層では、重みの初期化方法によって学習の安定性や収束速度が大きく変わります。 本記事では、Kerasでよく使われる Xavier 初期化と He 初期化について、 実際の学習曲線を比較しながら違いを解説します。
この記事を読むメリット
- 深層学習における「学習の遅延」や「勾配消失」の原因を理解できる。
- He初期化とXavier初期化の理論と使い分けが明確になる。
- Kerasで各種初期化を実装するPythonコードが手に入る。
なぜ初期化が重要なのか?(勾配消失・勾配爆発)
深層学習で「lossが全然下がらない」「勾配がNaNになる」——そんな経験はありませんか? その原因の多くは「重みの初期化」にあります。今回は、代表的な2つの初期化手法「Xavier」と「He」をKerasで実験し、違いを明確に検証します。
ニューラルネットワーク、とくにDense層(全結合層)が多層に重なる深いモデルでは、重みの初期値が不適切だと学習が始まる前から問題が発生します。それが勾配消失(Gradient Vanishing)と勾配爆発(Gradient Exploding)です。
初期化が不適切だと、層を通過するごとに信号が極端に小さく(あるいは大きく)なり、重みが更新されなくなったり、計算が破綻したりして学習が進まなくなります。
Dense層そのものの役割や、CNNにおける位置づけについては、 Dense層とは何か?畳み込み層との違いを解説した記事 で先に確認しておくと理解しやすくなります。
代表的な初期化手法と使い分け
| 初期化手法 | 考案者 | 推奨される活性化関数 | 目的 |
|---|---|---|---|
| Xavier(Glorot) | Glorotら (2010) | Sigmoid, Tanh | 入力と出力の分散を等しく保つ |
| He(Kaiming) | Heら (2015) | ReLU, Leaky ReLU | ReLU適用後の分散を等しく保つ |
Xavier:ザビエル(Glorot)の特徴
Xavier初期化は、層の入力数 (n_in) と出力数 (n_out) の平均に基づいて重みを調整します。主にSigmoidやTanhのように、中央値付近で勾配が大きくなる対称的な活性化関数に適しています。
initializer = tf.keras.initializers.GlorotUniform()
He(Kaiming)の特徴
He初期化は、ReLUのように負の値がゼロになる非対称な活性化関数向けに設計されました。入力数 (n_in) のみに依存して重みを調整し、ReLUで信号が半減する問題を補正します。
initializer = tf.keras.initializers.HeNormal()
Kerasでの実験(ReLUと初期化の比較)
ここでは、ReLUを使ったシンプルなDenseモデルを構築し、「He初期化」と「Xavier初期化」で学習の違いを比較します。
実験用Pythonコード
import tensorflow as tf
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.models import Sequential
import matplotlib.pyplot as plt
import numpy as np
# === 実験パラメータ ===
INPUT_DIM = 784
NUM_CLASSES = 10
EPOCHS = 10
# === データ準備 (MNISTを使用) ===
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
x_train = x_train.reshape(-1, INPUT_DIM).astype('float32') / 255.0
x_test = x_test.reshape(-1, INPUT_DIM).astype('float32') / 255.0
y_train = tf.keras.utils.to_categorical(y_train, NUM_CLASSES)
y_test = tf.keras.utils.to_categorical(y_test, NUM_CLASSES)
# === モデル構築関数 ===
def build_model(initializer_name):
"""指定した初期化手法でモデルを構築"""
if initializer_name == "He":
initializer = tf.keras.initializers.HeNormal()
else:
initializer = tf.keras.initializers.GlorotUniform()
model = Sequential([
Input(shape=(INPUT_DIM,)),
Dense(512, activation='relu', kernel_initializer=initializer),
Dense(256, activation='relu', kernel_initializer=initializer),
Dense(10, activation='softmax', kernel_initializer='glorot_uniform')
])
model.compile(
optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy']
)
return model
# === 学習実行 ===
print("Training with Xavier")
model_xavier = build_model("Xavier")
history_xavier = model_xavier.fit(x_train, y_train, validation_data=(x_test, y_test), epochs=EPOCHS, verbose=1)
print("Training with He")
model_he = build_model("He")
history_he = model_he.fit(x_train, y_train, validation_data=(x_test, y_test), epochs=EPOCHS, verbose=1)
# === 結果出力 ===
print("=== 最終精度比較 ===")
print(f"Xavier精度: {history_xavier.history['val_accuracy'][-1]:.4f}")
print(f"He精度: {history_he.history['val_accuracy'][-1]:.4f}")
# === 学習曲線をプロット ===
plt.figure(figsize=(10, 4))
# 精度の比較
plt.subplot(1, 2, 1)
plt.plot(history_xavier.history['accuracy'], label='Xavier - Train')
plt.plot(history_xavier.history['val_accuracy'], label='Xavier - Val')
plt.plot(history_he.history['accuracy'], label='He - Train')
plt.plot(history_he.history['val_accuracy'], label='He - Val')
plt.title('Accuracy Comparison')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend()
plt.grid(True)
# 損失の比較
plt.subplot(1, 2, 2)
plt.plot(history_xavier.history['loss'], label='Xavier - Train')
plt.plot(history_xavier.history['val_loss'], label='Xavier - Val')
plt.plot(history_he.history['loss'], label='He - Train')
plt.plot(history_he.history['val_loss'], label='He - Val')
plt.title('Loss Comparison')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
上記コードでは、He初期化とXavier初期化を比較し、学習曲線(Accuracy・Loss)を並べてプロットします。 実行結果から、ReLUを使用したモデルではHe初期化の方が早く収束しやすく、安定した精度に到達する傾向が見られます。
学習結果
学習過程
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz 11490434/11490434 ━━━━━━━━━━━━━━━━━━━━ 0s 0us/step Training with Xavier Epoch 1/10 1875/1875 ━━━━━━━━━━━━━━━━━━━━ 15s 6ms/step - accuracy: 0.9044 - loss: 0.3152 - val_accuracy: 0.9707 - val_loss: 0.0891 Epoch 2/10 1875/1875 ━━━━━━━━━━━━━━━━━━━━ 11s 6ms/step - accuracy: 0.9761 - loss: 0.0776 - val_accuracy: 0.9757 - val_loss: 0.0844 Epoch 3/10 1875/1875 ━━━━━━━━━━━━━━━━━━━━ 15s 3ms/step - accuracy: 0.9844 - loss: 0.0513 - val_accuracy: 0.9780 - val_loss: 0.0711 Epoch 4/10 1875/1875 ━━━━━━━━━━━━━━━━━━━━ 5s 3ms/step - accuracy: 0.9872 - loss: 0.0388 - val_accuracy: 0.9766 - val_loss: 0.0789 Epoch 5/10 1875/1875 ━━━━━━━━━━━━━━━━━━━━ 5s 2ms/step - accuracy: 0.9905 - loss: 0.0290 - val_accuracy: 0.9814 - val_loss: 0.0683 Epoch 6/10 1875/1875 ━━━━━━━━━━━━━━━━━━━━ 5s 3ms/step - accuracy: 0.9922 - loss: 0.0240 - val_accuracy: 0.9803 - val_loss: 0.0702 Epoch 7/10 1875/1875 ━━━━━━━━━━━━━━━━━━━━ 5s 3ms/step - accuracy: 0.9928 - loss: 0.0224 - val_accuracy: 0.9797 - val_loss: 0.0768 Epoch 8/10 1875/1875 ━━━━━━━━━━━━━━━━━━━━ 5s 2ms/step - accuracy: 0.9944 - loss: 0.0168 - val_accuracy: 0.9794 - val_loss: 0.0859 Epoch 9/10 1875/1875 ━━━━━━━━━━━━━━━━━━━━ 5s 3ms/step - accuracy: 0.9948 - loss: 0.0155 - val_accuracy: 0.9772 - val_loss: 0.1029 Epoch 10/10 1875/1875 ━━━━━━━━━━━━━━━━━━━━ 5s 2ms/step - accuracy: 0.9954 - loss: 0.0134 - val_accuracy: 0.9794 - val_loss: 0.1044 Training with He Epoch 1/10 1875/1875 ━━━━━━━━━━━━━━━━━━━━ 7s 3ms/step - accuracy: 0.9050 - loss: 0.3042 - val_accuracy: 0.9653 - val_loss: 0.1126 Epoch 2/10 1875/1875 ━━━━━━━━━━━━━━━━━━━━ 5s 3ms/step - accuracy: 0.9744 - loss: 0.0796 - val_accuracy: 0.9747 - val_loss: 0.0825 Epoch 3/10 1875/1875 ━━━━━━━━━━━━━━━━━━━━ 5s 3ms/step - accuracy: 0.9833 - loss: 0.0523 - val_accuracy: 0.9788 - val_loss: 0.0804 Epoch 4/10 1875/1875 ━━━━━━━━━━━━━━━━━━━━ 5s 2ms/step - accuracy: 0.9876 - loss: 0.0368 - val_accuracy: 0.9791 - val_loss: 0.0720 Epoch 5/10 1875/1875 ━━━━━━━━━━━━━━━━━━━━ 11s 6ms/step - accuracy: 0.9910 - loss: 0.0285 - val_accuracy: 0.9820 - val_loss: 0.0627 Epoch 6/10 1875/1875 ━━━━━━━━━━━━━━━━━━━━ 14s 2ms/step - accuracy: 0.9929 - loss: 0.0210 - val_accuracy: 0.9750 - val_loss: 0.1060 Epoch 7/10 1875/1875 ━━━━━━━━━━━━━━━━━━━━ 5s 3ms/step - accuracy: 0.9930 - loss: 0.0213 - val_accuracy: 0.9722 - val_loss: 0.1106 Epoch 8/10 1875/1875 ━━━━━━━━━━━━━━━━━━━━ 5s 3ms/step - accuracy: 0.9942 - loss: 0.0180 - val_accuracy: 0.9809 - val_loss: 0.0821 Epoch 9/10 1875/1875 ━━━━━━━━━━━━━━━━━━━━ 5s 2ms/step - accuracy: 0.9946 - loss: 0.0156 - val_accuracy: 0.9791 - val_loss: 0.1026 Epoch 10/10 1875/1875 ━━━━━━━━━━━━━━━━━━━━ 5s 3ms/step - accuracy: 0.9959 - loss: 0.0126 - val_accuracy: 0.9800 - val_loss: 0.1011 === 最終精度比較 === Xavier精度: 0.9794 He精度: 0.9800
グラフのプロット
損失グラフでは、He初期化(赤線)はエポック5以降で一時的にバラつきが見られます。これはReLU特有の非対称性による活性化の偏りが原因で、初期値依存性が強いことを示しています。
実行結果の考察
=== 最終精度比較 ===
Xavier精度: 0.9794
He精度: 0.9800
結論: ReLUではHe初期化の方が安定して高い精度を示す。
結果を見ると、ReLUを使用する場合はHe初期化の方が安定して勾配を伝えやすく、高い精度を達成する傾向があります。
考察:Xavier(Glorot)とHe(Kaiming)の比較
両手法とも最終的な学習精度は非常に高く僅差ですが、学習の安定性や検証損失(val_loss)の挙動に差が見られます。
要点のまとめ
- 最終的な検証精度(val_accuracy)は両者とも高くほぼ同等(Xavier: 約0.9794、He: 約0.9800)。
- Xavierは学習曲線が滑らかで安定している一方、Heは途中でval_lossが乱高下する場面があり、やや不安定な挙動が見られる。
- Heは一時的に高いval_accuracyを示すことがあるが、val_lossの乱れは過学習や勾配の局所的不安定性を示唆する。
ログから読み取れる観察点
- 学習立ち上がり: 両手法とも初期エポックで学習が速く進んでおり、訓練精度は急速に上昇しています。これはデータ(MNIST相当)とモデル構成が学習に適しているためと考えられます。
- 検証損失の挙動: Xavierではval_lossが比較的滑らかに減少〜安定しています。Heでは一時的にval_lossが跳ね上がる(例:Epoch 6〜7付近)場面があり、訓練損失とのギャップが広がる傾向が観察されます。
- 汎化の一貫性: Xavierはval_accuracyの推移が一貫して安定しているため、再現性・汎化の観点でやや有利に見えます。Heは最高値は出しやすいものの、安定性に欠ける局面があるためハイパーパラメータ調整が重要です。
なぜXavierに利点があるのか(理論的な補足)
Xavier初期化は「層の入力と出力の分散を等しく保つ」ことを目的に設計されています。これにより、順伝播・逆伝播の信号が各層で極端に縮小または増幅されにくく、結果として以下の利点が現れやすくなります:
- 学習の安定性:初期エポックにおける勾配の振れ幅が小さく、学習曲線が滑らかになりやすい。
- 過学習の抑制:初期重みが過度に大きくならないため、初期段階での過度なフィッティングを抑えられる。
- 活性化関数への適応性:Sigmoid/Tanhだけでなく、ReLU系でも浅〜中程度の層深では十分に有効で、汎用的に使える。
実務的な示唆(今回のログに基づく推奨)
- モデル安定性や再現性を重視する場合: Xavier初期化を第一候補とする価値があります。特に実運用で安定した挙動を求める際は有効です。
- 最大性能(わずかな精度差)を追う場合: He初期化はReLU系で最良の性能を引き出せることが多いので、ハイパーパラメータ(学習率・正則化・バッチサイズ等)を丁寧にチューニングできる環境で有効です。
- 実験の次のステップ: val_lossが乱れるHe側について、ドロップアウト強度の調整、L2正則化、学習率スケジューラ、または早期終了(EarlyStopping)を適用して比較すると、より本質的な差が見えてきます。
結論
今回の実験ログでは、最終的な精度に大きな差はないものの、Xavierは「安定した学習挙動と一貫した汎化性能」を示しやすいという重要な利点が確認できます。 一方で、ReLUに最適化されたHe初期化は「攻めの設定」として高精度を達成しやすい反面、ハイパーパラメータ管理が不十分だとval_lossの乱れ(=過学習や不安定性)を引き起こすことがあります。
実運用ではまずXavierで安定性を確かめ、必要に応じてHeを試してハイパーパラメータを詰める、という段階的な戦略が現実的です。 また、今回のモデルはDense層が中心なので、Dense層特有の挙動(活性化・正則化・重み減衰など)にも注目してチューニングしてください。
まとめ
Dense層の初期化は、ディープラーニングモデルの性能を左右する重要な要素です。
- ReLUを使うなら → He初期化(
kernel_initializer='he_normal') - Sigmoid/Tanhを使うなら → Xavier初期化(
kernel_initializer='glorot_uniform')
特にDense層に関する理解を深めたい方は、関連する以下の記事もおすすめです: 【関連】Dense層とは?仕組みと実装をわかりやすく解説



0 件のコメント:
コメントを投稿