はじめに
ディープラーニングにおいて、Batch Size(バッチサイズ)は学習の効率や精度に大きく影響する重要なハイパーパラメータです。
しかし実際には「小さすぎると時間がかかる」「大きすぎると不安定になる」といったトレードオフがあり、最適な値を見極めるのは簡単ではありません。
本記事では、Keras を使ってバッチサイズを 16, 32, 64, 128 に変化させながら、MNIST 手書き数字分類タスクの精度・学習時間・損失の推移を比較し、その違いを図表とともに解説します。
実験環境とモデル構成
- データセット:MNIST(手書き数字画像)
- モデル:シンプルな CNN(Conv2D → MaxPool → Flatten → Dense)
- Optimizer:Adam(学習率デフォルト)
- エポック数:10
- バッチサイズ:16, 32, 64, 128 の 4 種類
from tensorflow import keras
from tensorflow.keras import layers
import numpy as np
# データセット読み込み
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
x_train = x_train[..., np.newaxis] / 255.0
x_test = x_test[..., np.newaxis] / 255.0
# モデル定義
model = keras.Sequential([
keras.layers.Input(shape=(28, 28, 1)),
keras.layers.Conv2D(32, (3, 3), activation='relu'),
keras.layers.MaxPooling2D(),
keras.layers.Flatten(),
keras.layers.Dense(64, activation='relu'),
keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
実験コード
同じ初期重みを使うため、各バッチサイズごとにモデルを再生成して訓練します。
results = {}
histories = {}
for bs in [16, 32, 64, 128]:
print(f"Batch Size: {bs}")
histories[bs] = model.fit(
x_train, y_train,
batch_size=bs, # ← ここでバッチサイズ切り替え
epochs=10,
validation_split=0.2
)
test_loss, test_acc = model.evaluate(x_test, y_test, verbose=0)
results[bs] = {
"val_acc": histories[bs].history["val_accuracy"][-1],
"test_acc": test_acc
}
訓練結果
Batch Size: 16 Epoch 1/10 3000/3000 ━━━━━━━━━━━━━━━━━━━━ 9s 3ms/step - accuracy: 0.9986 - loss: 0.0048 - val_accuracy: 0.9834 - val_loss: 0.0846 Epoch 2/10 3000/3000 ━━━━━━━━━━━━━━━━━━━━ 10s 3ms/step - accuracy: 0.9988 - loss: 0.0036 - val_accuracy: 0.9847 - val_loss: 0.0969 Epoch 3/10 3000/3000 ━━━━━━━━━━━━━━━━━━━━ 9s 3ms/step - accuracy: 0.9981 - loss: 0.0051 - val_accuracy: 0.9870 - val_loss: 0.0787 Epoch 4/10 3000/3000 ━━━━━━━━━━━━━━━━━━━━ 10s 3ms/step - accuracy: 0.9992 - loss: 0.0028 - val_accuracy: 0.9870 - val_loss: 0.0686 Epoch 5/10 3000/3000 ━━━━━━━━━━━━━━━━━━━━ 10s 3ms/step - accuracy: 0.9990 - loss: 0.0028 - val_accuracy: 0.9864 - val_loss: 0.0856 Epoch 6/10 3000/3000 ━━━━━━━━━━━━━━━━━━━━ 9s 3ms/step - accuracy: 0.9990 - loss: 0.0036 - val_accuracy: 0.9854 - val_loss: 0.0897 Epoch 7/10 3000/3000 ━━━━━━━━━━━━━━━━━━━━ 9s 3ms/step - accuracy: 0.9992 - loss: 0.0025 - val_accuracy: 0.9853 - val_loss: 0.0875 Epoch 8/10 3000/3000 ━━━━━━━━━━━━━━━━━━━━ 9s 3ms/step - accuracy: 0.9995 - loss: 0.0017 - val_accuracy: 0.9849 - val_loss: 0.1009 Epoch 9/10 3000/3000 ━━━━━━━━━━━━━━━━━━━━ 9s 3ms/step - accuracy: 0.9997 - loss: 0.0011 - val_accuracy: 0.9846 - val_loss: 0.0985 Epoch 10/10 3000/3000 ━━━━━━━━━━━━━━━━━━━━ 11s 3ms/step - accuracy: 0.9991 - loss: 0.0029 - val_accuracy: 0.9852 - val_loss: 0.1023 Batch Size: 32 Epoch 1/10 1500/1500 ━━━━━━━━━━━━━━━━━━━━ 6s 3ms/step - accuracy: 0.9997 - loss: 9.8968e-04 - val_accuracy: 0.9866 - val_loss: 0.0857 Epoch 2/10 1500/1500 ━━━━━━━━━━━━━━━━━━━━ 9s 3ms/step - accuracy: 1.0000 - loss: 5.7384e-05 - val_accuracy: 0.9873 - val_loss: 0.0863 Epoch 3/10 1500/1500 ━━━━━━━━━━━━━━━━━━━━ 6s 3ms/step - accuracy: 1.0000 - loss: 1.2405e-05 - val_accuracy: 0.9873 - val_loss: 0.0889 Epoch 4/10 1500/1500 ━━━━━━━━━━━━━━━━━━━━ 5s 3ms/step - accuracy: 1.0000 - loss: 5.5474e-06 - val_accuracy: 0.9872 - val_loss: 0.0902 Epoch 5/10 1500/1500 ━━━━━━━━━━━━━━━━━━━━ 5s 3ms/step - accuracy: 1.0000 - loss: 3.3598e-06 - val_accuracy: 0.9874 - val_loss: 0.0930 Epoch 6/10 1500/1500 ━━━━━━━━━━━━━━━━━━━━ 5s 3ms/step - accuracy: 1.0000 - loss: 2.1214e-06 - val_accuracy: 0.9874 - val_loss: 0.0957 Epoch 7/10 1500/1500 ━━━━━━━━━━━━━━━━━━━━ 11s 4ms/step - accuracy: 1.0000 - loss: 1.0058e-06 - val_accuracy: 0.9876 - val_loss: 0.0983 Epoch 8/10 1500/1500 ━━━━━━━━━━━━━━━━━━━━ 10s 3ms/step - accuracy: 1.0000 - loss: 5.8998e-07 - val_accuracy: 0.9877 - val_loss: 0.1024 Epoch 9/10 1500/1500 ━━━━━━━━━━━━━━━━━━━━ 4s 3ms/step - accuracy: 1.0000 - loss: 2.9769e-07 - val_accuracy: 0.9878 - val_loss: 0.1059 Epoch 10/10 1500/1500 ━━━━━━━━━━━━━━━━━━━━ 6s 3ms/step - accuracy: 1.0000 - loss: 1.7629e-07 - val_accuracy: 0.9868 - val_loss: 0.1169 Batch Size: 64 Epoch 1/10 750/750 ━━━━━━━━━━━━━━━━━━━━ 4s 4ms/step - accuracy: 0.9989 - loss: 0.0044 - val_accuracy: 0.9844 - val_loss: 0.1087 Epoch 2/10 750/750 ━━━━━━━━━━━━━━━━━━━━ 2s 3ms/step - accuracy: 0.9998 - loss: 3.1455e-04 - val_accuracy: 0.9864 - val_loss: 0.0962 Epoch 3/10 750/750 ━━━━━━━━━━━━━━━━━━━━ 3s 3ms/step - accuracy: 1.0000 - loss: 1.0214e-05 - val_accuracy: 0.9863 - val_loss: 0.0964 Epoch 4/10 750/750 ━━━━━━━━━━━━━━━━━━━━ 5s 3ms/step - accuracy: 1.0000 - loss: 5.1206e-06 - val_accuracy: 0.9863 - val_loss: 0.0974 Epoch 5/10 750/750 ━━━━━━━━━━━━━━━━━━━━ 2s 3ms/step - accuracy: 1.0000 - loss: 3.9402e-06 - val_accuracy: 0.9862 - val_loss: 0.0979 Epoch 6/10 750/750 ━━━━━━━━━━━━━━━━━━━━ 2s 3ms/step - accuracy: 1.0000 - loss: 2.8684e-06 - val_accuracy: 0.9864 - val_loss: 0.0985 Epoch 7/10 750/750 ━━━━━━━━━━━━━━━━━━━━ 3s 4ms/step - accuracy: 1.0000 - loss: 1.9861e-06 - val_accuracy: 0.9863 - val_loss: 0.0992 Epoch 8/10 750/750 ━━━━━━━━━━━━━━━━━━━━ 5s 3ms/step - accuracy: 1.0000 - loss: 1.6821e-06 - val_accuracy: 0.9864 - val_loss: 0.0998 Epoch 9/10 750/750 ━━━━━━━━━━━━━━━━━━━━ 2s 3ms/step - accuracy: 1.0000 - loss: 1.3144e-06 - val_accuracy: 0.9864 - val_loss: 0.1006 Epoch 10/10 750/750 ━━━━━━━━━━━━━━━━━━━━ 3s 3ms/step - accuracy: 1.0000 - loss: 1.0312e-06 - val_accuracy: 0.9868 - val_loss: 0.1015 Batch Size: 128 Epoch 1/10 375/375 ━━━━━━━━━━━━━━━━━━━━ 3s 7ms/step - accuracy: 1.0000 - loss: 6.7372e-07 - val_accuracy: 0.9866 - val_loss: 0.1020 Epoch 2/10 375/375 ━━━━━━━━━━━━━━━━━━━━ 1s 4ms/step - accuracy: 1.0000 - loss: 6.0283e-07 - val_accuracy: 0.9865 - val_loss: 0.1026 Epoch 3/10 375/375 ━━━━━━━━━━━━━━━━━━━━ 3s 4ms/step - accuracy: 1.0000 - loss: 5.4752e-07 - val_accuracy: 0.9868 - val_loss: 0.1031 Epoch 4/10 375/375 ━━━━━━━━━━━━━━━━━━━━ 3s 5ms/step - accuracy: 1.0000 - loss: 4.9129e-07 - val_accuracy: 0.9868 - val_loss: 0.1035 Epoch 5/10 375/375 ━━━━━━━━━━━━━━━━━━━━ 2s 4ms/step - accuracy: 1.0000 - loss: 4.1864e-07 - val_accuracy: 0.9869 - val_loss: 0.1041 Epoch 6/10 375/375 ━━━━━━━━━━━━━━━━━━━━ 2s 4ms/step - accuracy: 1.0000 - loss: 3.6648e-07 - val_accuracy: 0.9871 - val_loss: 0.1047 Epoch 7/10 375/375 ━━━━━━━━━━━━━━━━━━━━ 1s 4ms/step - accuracy: 1.0000 - loss: 2.9667e-07 - val_accuracy: 0.9870 - val_loss: 0.1054 Epoch 8/10 375/375 ━━━━━━━━━━━━━━━━━━━━ 1s 4ms/step - accuracy: 1.0000 - loss: 2.6079e-07 - val_accuracy: 0.9871 - val_loss: 0.1061 Epoch 9/10 375/375 ━━━━━━━━━━━━━━━━━━━━ 3s 4ms/step - accuracy: 1.0000 - loss: 2.3504e-07 - val_accuracy: 0.9871 - val_loss: 0.1067 Epoch 10/10 375/375 ━━━━━━━━━━━━━━━━━━━━ 2s 4ms/step - accuracy: 1.0000 - loss: 2.0702e-07 - val_accuracy: 0.9872 - val_loss: 0.1073
結果の可視化
各バッチサイズの検証精度と損失の推移をグラフ化します。
import matplotlib.pyplot as plt
for bs in [16, 32, 64, 128]:
print(f"{bs}: {results[bs]}")
for bs in [16, 32, 64, 128]:
plt.plot(histories[bs].history['val_accuracy'], label=f'{bs} val_accuracy')
plt.title('Validation Accuracy per Epoch')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend()
plt.grid(True)
plt.show()
for bs in [16, 32, 64, 128]:
plt.plot(histories[bs].history['val_loss'], label=f'{bs} val_loss')
plt.title('Validation Loss per Epoch')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.grid(True)
plt.show()
最終結果
16: {'val_acc': 0.9852499961853027, 'test_acc': 0.9847999811172485} 32: {'val_acc': 0.9868333339691162, 'test_acc': 0.9868000149726868} 64: {'val_acc': 0.9867500066757202, 'test_acc': 0.9868999719619751} 128: {'val_acc': 0.9872499704360962, 'test_acc': 0.9871000051498413}
精度グラフ
損失グラフ
結果まとめ
Batch Size | 最終 Val Accuracy | 最終 Val Loss | 特徴 |
---|---|---|---|
16 | 0.9852 | 0.1023 | ステップ多く学習安定だが、最終損失高め |
32 | 0.9868 | 0.1169 | 早く収束するが、損失のばらつき大 |
64 | 0.9868 | 0.1015 | 高速学習+安定感あり |
128 | 0.9872 | 0.1073 | 最も高精度だがメモリ効率が低い |
考察
- Batch Size 16:小バッチはパラメータ更新が細かく、安定的に学習する反面、ステップ数が増えて学習時間が長くなり、最終損失もやや高め。
- Batch Size 32:標準的な設定。学習が速く進むが、損失の振れ幅が大きいため微調整が必要。
- Batch Size 64:学習速度と性能のバランスが良い。Val Accuracy と Val Loss の両方で安定した結果。
- Batch Size 128:最も高い Val Accuracy を達成。ただし、大きなバッチはメモリ使用量が増加し、過学習リスクも若干高まる。
まとめ
バッチサイズは「学習時間」「メモリ使用量」「汎化性能」のトレードオフで最適値が変わります。
本実験では Batch Size 64 が最もバランスの良い結果となりましたが、データやモデル構造に応じて調整をおすすめします。
ぜひ本記事を参考に、プロジェクトに最適なバッチサイズを見つけてください!
0 件のコメント:
コメントを投稿