はじめに | バッチサイズの違いで精度や学習効率にどんな差が出るのか?
深層学習の訓練において、バッチサイズ(Batch Size)は重要なハイパーパラメータです。
バッチサイズがモデルの収束速度や精度、損失にどう影響を与えるのかを知ることは、より効果的な学習のために不可欠です。
本記事では、KerasとMNISTを使い、バッチサイズ 16・32・64・128でモデルを学習させ、その違いを比較・考察しました。
精度や損失の推移、学習時間、グラフ付きの結果を交えて解説します。
実験設定:使用データとモデルの構成
- データセット:MNIST(手書き数字画像)
- モデル:簡易CNN(Conv2D → MaxPool → Flatten → Dense)
- オプティマイザ:Adam(初期学習率デフォルト)
- エポック数:10
- バッチサイズ:16, 32, 64, 128
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
}
学習ログ:各バッチサイズの訓練過程
各バッチサイズにおける10エポックの学習ログを記録しました。精度・損失の変化や学習スピードの違いも比較対象です。
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
結果の可視化:精度・損失グラフで比較
各バッチサイズの検証精度(val_accuracy)および損失(val_loss)の推移をグラフで比較します。
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:安定性と速度のバランスが最も良い。
- Batch Size 128:高精度を出せるが、メモリ負荷と過学習リスクもある。
まとめ:最適なバッチサイズを見つけよう
本記事ではバッチサイズの違いによる精度・損失の比較を行いました。
結果、64が最もバランス良好でしたが、使用するデータやモデルによって最適値は変動します。
実運用においては、リソースや精度の要件に応じて適切なバッチサイズを選定しましょう。
0 件のコメント:
コメントを投稿