activation関数を変えると精度はどう変わる?(relu vs gelu vs elu)【Keras×CIFAR-10実験】

投稿日:2026年4月25日土曜日 最終更新日:

activation CIFAR-10 CNN ELU GELU Google Colab Keras ReLU

X f B! P L
activation関数を変えると精度はどう変わる?(relu vs gelu vs elu)【Keras×CIFAR-10実験】 アイキャッチ画像

KerasのDense層でactivation関数を選ぶとき、なんとなく relu にしていませんか?

MNISTでのrelu・leakyrelu・elu・geluの比較は → 活性化関数比較:ReLU / LeakyReLU / ELU / GELU の違いとは? で行いました。今回はより難しいCIFAR-10・GAP使用モデルで relu・gelu・elu の3種を比較します。MNISTと結果が変わるかどうかも見どころです。

📘 この記事でわかること

  • relu・gelu・eluでCIFAR-10の精度・収束速度がどう変わるか
  • MNISTでの結果とCIFAR-10での結果に違いはあるか
  • GAP使用CNNモデルでのactivation関数の選び方

relu・gelu・eluの特徴おさらい

関数 数式(概要) 特徴
ReLU max(0, x) 最もシンプルで高速。負の入力で勾配ゼロ(死んだReLU問題)
ELU x(x≥0)/ α(e^x - 1)(x<0) 負の領域でも出力を持ち平均を0に近づける。収束が速い傾向
GELU x・Φ(x) ガウス分布に基づくスムーズな応答。BERTやGPTで標準採用

今回はConv2D層のactivationは relu に固定し、Dense層のactivationだけを3パターンで切り替えます。これにより「特徴抽出部分は同じ・分類部分だけが異なる」という条件で比較できます。


実験コード

使用環境はGoogle Colab(GPU:T4)、データセットはCIFAR-10です。activation以外の条件は全て同一にします。

環境準備(最初に一度だけ実行)

# ── 環境準備(最初に一度だけ実行)──────────────────────
!apt-get -y install fonts-ipafont-gothic
!rm -rf /root/.cache/matplotlib
!pip install -q japanize_matplotlib
print("環境準備完了")
実行結果をクリックして内容を開く
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
  fonts-ipafont-mincho
The following NEW packages will be installed:
  fonts-ipafont-gothic fonts-ipafont-mincho
0 upgraded, 2 newly installed, 0 to remove and 42 not upgraded.
Need to get 8,237 kB of archives.
After this operation, 28.7 MB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu jammy/universe amd64 fonts-ipafont-gothic all 00303-21ubuntu1 [3,513 kB]
Get:2 http://archive.ubuntu.com/ubuntu jammy/universe amd64 fonts-ipafont-mincho all 00303-21ubuntu1 [4,724 kB]
Fetched 8,237 kB in 2s (4,773 kB/s)
Selecting previously unselected package fonts-ipafont-gothic.
(Reading database ... 122354 files and directories currently installed.)
Preparing to unpack .../fonts-ipafont-gothic_00303-21ubuntu1_all.deb ...
Unpacking fonts-ipafont-gothic (00303-21ubuntu1) ...
Selecting previously unselected package fonts-ipafont-mincho.
Preparing to unpack .../fonts-ipafont-mincho_00303-21ubuntu1_all.deb ...
Unpacking fonts-ipafont-mincho (00303-21ubuntu1) ...
Setting up fonts-ipafont-mincho (00303-21ubuntu1) ...
update-alternatives: using /usr/share/fonts/opentype/ipafont-mincho/ipam.ttf to provide /usr/share/fonts/truetype/fonts-japanese-mincho.ttf (fonts-japanese-mincho.ttf) in auto mode
Setting up fonts-ipafont-gothic (00303-21ubuntu1) ...
update-alternatives: using /usr/share/fonts/opentype/ipafont-gothic/ipag.ttf to provide /usr/share/fonts/truetype/fonts-japanese-gothic.ttf (fonts-japanese-gothic.ttf) in auto mode
Processing triggers for fontconfig (2.13.1-4.2ubuntu5) ...
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.1/4.1 MB 55.7 MB/s eta 0:00:00
  Preparing metadata (setup.py) ... done
  Building wheel for japanize_matplotlib (setup.py) ... done
環境準備完了

import・データ準備・モデル構築関数

import tensorflow as tf
from tensorflow import keras
import matplotlib.pyplot as plt
import japanize_matplotlib
import time

(x_train, y_train), (x_test, y_test) = keras.datasets.cifar10.load_data()
x_train = x_train.astype('float32') / 255.0
x_test  = x_test.astype('float32')  / 255.0

def build_model(activation, name):
    return keras.Sequential([
        keras.layers.Input(shape=(32, 32, 3)),
        keras.layers.Conv2D(64, (3, 3), activation='relu', padding='same'),
        keras.layers.MaxPooling2D((2, 2)),
        keras.layers.Conv2D(128, (3, 3), activation='relu', padding='same'),
        keras.layers.MaxPooling2D((2, 2)),
        keras.layers.GlobalAveragePooling2D(),
        keras.layers.Dense(128, activation=activation),  # ← ここだけ変える
        keras.layers.Dropout(0.2),
        keras.layers.Dense(10, activation='softmax'),
    ], name=name)

def compile_and_fit(model):
    model.compile(optimizer='adam',
                  loss='sparse_categorical_crossentropy',
                  metrics=['accuracy'])
    start = time.time()
    history = model.fit(x_train, y_train, epochs=30, batch_size=64,
                        validation_split=0.2, verbose=1)
    return history, time.time() - start
実行結果をクリックして内容を開く
Downloading data from https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz
170498071/170498071 ━━━━━━━━━━━━━━━━━━━━ 13s 0us/step

3パターンの学習実行

configs = [('relu', 'A_relu'), ('gelu', 'B_gelu'), ('elu', 'C_elu')]
histories, times, scores = {}, {}, {}

for activation, name in configs:
    print(f"\n=== {name} ===")
    model = build_model(activation, name)
    h, t = compile_and_fit(model)
    s = model.evaluate(x_test, y_test, verbose=0)
    label = name.split('_')[1]
    histories[label] = h
    times[label] = t
    scores[label] = s
    print(f"学習時間:{t:.1f}秒 test_accuracy:{s[1]:.4f}")
実行結果をクリックして内容を開く
=== A_relu ===
Epoch 1/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 16s 12ms/step - accuracy: 0.2722 - loss: 1.9084 - val_accuracy: 0.3719 - val_loss: 1.6928
Epoch 2/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 7ms/step - accuracy: 0.3794 - loss: 1.6540 - val_accuracy: 0.3997 - val_loss: 1.6036
Epoch 3/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 6ms/step - accuracy: 0.4336 - loss: 1.5358 - val_accuracy: 0.4720 - val_loss: 1.4436
Epoch 4/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4688 - loss: 1.4478 - val_accuracy: 0.4871 - val_loss: 1.4039
Epoch 5/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4953 - loss: 1.3913 - val_accuracy: 0.5151 - val_loss: 1.3191
Epoch 6/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5110 - loss: 1.3372 - val_accuracy: 0.5327 - val_loss: 1.2725
Epoch 7/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5300 - loss: 1.2978 - val_accuracy: 0.5406 - val_loss: 1.2535
Epoch 8/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5440 - loss: 1.2621 - val_accuracy: 0.5545 - val_loss: 1.2176
Epoch 9/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5541 - loss: 1.2261 - val_accuracy: 0.5633 - val_loss: 1.1954
Epoch 10/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5636 - loss: 1.1982 - val_accuracy: 0.5553 - val_loss: 1.2262
Epoch 11/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5722 - loss: 1.1817 - val_accuracy: 0.5836 - val_loss: 1.1535
Epoch 12/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5850 - loss: 1.1514 - val_accuracy: 0.5883 - val_loss: 1.1322
Epoch 13/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5907 - loss: 1.1296 - val_accuracy: 0.5952 - val_loss: 1.1062
Epoch 14/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5998 - loss: 1.1080 - val_accuracy: 0.5982 - val_loss: 1.0906
Epoch 15/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6076 - loss: 1.0895 - val_accuracy: 0.6095 - val_loss: 1.0801
Epoch 16/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6168 - loss: 1.0685 - val_accuracy: 0.5809 - val_loss: 1.1370
Epoch 17/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6187 - loss: 1.0541 - val_accuracy: 0.6290 - val_loss: 1.0346
Epoch 18/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6277 - loss: 1.0405 - val_accuracy: 0.6177 - val_loss: 1.0647
Epoch 19/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6339 - loss: 1.0214 - val_accuracy: 0.6221 - val_loss: 1.0532
Epoch 20/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6368 - loss: 1.0083 - val_accuracy: 0.6437 - val_loss: 0.9920
Epoch 21/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6411 - loss: 0.9953 - val_accuracy: 0.6428 - val_loss: 0.9997
Epoch 22/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6502 - loss: 0.9703 - val_accuracy: 0.6530 - val_loss: 0.9689
Epoch 23/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 10ms/step - accuracy: 0.6520 - loss: 0.9655 - val_accuracy: 0.6555 - val_loss: 0.9590
Epoch 24/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6558 - loss: 0.9508 - val_accuracy: 0.6577 - val_loss: 0.9534
Epoch 25/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6637 - loss: 0.9369 - val_accuracy: 0.6499 - val_loss: 0.9697
Epoch 26/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6685 - loss: 0.9259 - val_accuracy: 0.6525 - val_loss: 0.9743
Epoch 27/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6708 - loss: 0.9150 - val_accuracy: 0.6666 - val_loss: 0.9183
Epoch 28/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6788 - loss: 0.9016 - val_accuracy: 0.6645 - val_loss: 0.9270
Epoch 29/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6821 - loss: 0.8894 - val_accuracy: 0.6719 - val_loss: 0.9307
Epoch 30/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6841 - loss: 0.8787 - val_accuracy: 0.6779 - val_loss: 0.8999
学習時間:133.1秒 test_accuracy:0.6752

=== B_gelu ===
Epoch 1/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 8s 9ms/step - accuracy: 0.2797 - loss: 1.9041 - val_accuracy: 0.3607 - val_loss: 1.7094
Epoch 2/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.3866 - loss: 1.6501 - val_accuracy: 0.4250 - val_loss: 1.5633
Epoch 3/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4404 - loss: 1.5220 - val_accuracy: 0.4505 - val_loss: 1.4684
Epoch 4/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.4776 - loss: 1.4359 - val_accuracy: 0.5030 - val_loss: 1.3776
Epoch 5/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5017 - loss: 1.3696 - val_accuracy: 0.4926 - val_loss: 1.3655
Epoch 6/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5181 - loss: 1.3269 - val_accuracy: 0.5335 - val_loss: 1.2827
Epoch 7/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5344 - loss: 1.2820 - val_accuracy: 0.5412 - val_loss: 1.2576
Epoch 8/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5457 - loss: 1.2492 - val_accuracy: 0.5494 - val_loss: 1.2260
Epoch 9/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5568 - loss: 1.2174 - val_accuracy: 0.5680 - val_loss: 1.1953
Epoch 10/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5688 - loss: 1.1857 - val_accuracy: 0.5622 - val_loss: 1.1888
Epoch 11/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5793 - loss: 1.1626 - val_accuracy: 0.5933 - val_loss: 1.1327
Epoch 12/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5881 - loss: 1.1378 - val_accuracy: 0.6010 - val_loss: 1.1017
Epoch 13/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5997 - loss: 1.1084 - val_accuracy: 0.5955 - val_loss: 1.1175
Epoch 14/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6077 - loss: 1.0837 - val_accuracy: 0.6074 - val_loss: 1.0941
Epoch 15/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6154 - loss: 1.0711 - val_accuracy: 0.6049 - val_loss: 1.0747
Epoch 16/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6197 - loss: 1.0509 - val_accuracy: 0.6279 - val_loss: 1.0395
Epoch 17/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6280 - loss: 1.0323 - val_accuracy: 0.6257 - val_loss: 1.0302
Epoch 18/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6350 - loss: 1.0155 - val_accuracy: 0.6231 - val_loss: 1.0362
Epoch 19/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 7ms/step - accuracy: 0.6417 - loss: 0.9967 - val_accuracy: 0.6436 - val_loss: 0.9941
Epoch 20/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6476 - loss: 0.9809 - val_accuracy: 0.6326 - val_loss: 1.0162
Epoch 21/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6548 - loss: 0.9621 - val_accuracy: 0.6459 - val_loss: 0.9818
Epoch 22/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6581 - loss: 0.9555 - val_accuracy: 0.6616 - val_loss: 0.9476
Epoch 23/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6647 - loss: 0.9371 - val_accuracy: 0.6552 - val_loss: 0.9581
Epoch 24/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6710 - loss: 0.9183 - val_accuracy: 0.6593 - val_loss: 0.9463
Epoch 25/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6752 - loss: 0.9111 - val_accuracy: 0.6630 - val_loss: 0.9338
Epoch 26/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6817 - loss: 0.8958 - val_accuracy: 0.6702 - val_loss: 0.9311
Epoch 27/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6817 - loss: 0.8867 - val_accuracy: 0.6717 - val_loss: 0.9335
Epoch 28/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6873 - loss: 0.8742 - val_accuracy: 0.6707 - val_loss: 0.9223
Epoch 29/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6942 - loss: 0.8593 - val_accuracy: 0.6820 - val_loss: 0.8910
Epoch 30/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6944 - loss: 0.8528 - val_accuracy: 0.6800 - val_loss: 0.8945
学習時間:123.4秒 test_accuracy:0.6818

=== C_elu ===
Epoch 1/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 8s 8ms/step - accuracy: 0.2779 - loss: 1.9000 - val_accuracy: 0.3720 - val_loss: 1.6753
Epoch 2/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4058 - loss: 1.6075 - val_accuracy: 0.4480 - val_loss: 1.5074
Epoch 3/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4652 - loss: 1.4617 - val_accuracy: 0.4761 - val_loss: 1.4024
Epoch 4/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4975 - loss: 1.3821 - val_accuracy: 0.5053 - val_loss: 1.3533
Epoch 5/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5227 - loss: 1.3216 - val_accuracy: 0.5304 - val_loss: 1.2849
Epoch 6/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5406 - loss: 1.2758 - val_accuracy: 0.5467 - val_loss: 1.2475
Epoch 7/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5545 - loss: 1.2357 - val_accuracy: 0.5355 - val_loss: 1.2685
Epoch 8/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5643 - loss: 1.2113 - val_accuracy: 0.5656 - val_loss: 1.2024
Epoch 9/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5809 - loss: 1.1692 - val_accuracy: 0.5830 - val_loss: 1.1534
Epoch 10/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5875 - loss: 1.1468 - val_accuracy: 0.5817 - val_loss: 1.1435
Epoch 11/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5949 - loss: 1.1249 - val_accuracy: 0.5915 - val_loss: 1.1293
Epoch 12/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6090 - loss: 1.0967 - val_accuracy: 0.6082 - val_loss: 1.0967
Epoch 13/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6144 - loss: 1.0745 - val_accuracy: 0.6124 - val_loss: 1.0689
Epoch 14/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 10ms/step - accuracy: 0.6205 - loss: 1.0611 - val_accuracy: 0.6077 - val_loss: 1.0882
Epoch 15/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6313 - loss: 1.0309 - val_accuracy: 0.6317 - val_loss: 1.0222
Epoch 16/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6403 - loss: 1.0108 - val_accuracy: 0.6284 - val_loss: 1.0302
Epoch 17/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6465 - loss: 0.9954 - val_accuracy: 0.6245 - val_loss: 1.0340
Epoch 18/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6517 - loss: 0.9814 - val_accuracy: 0.6408 - val_loss: 1.0025
Epoch 19/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6579 - loss: 0.9663 - val_accuracy: 0.6362 - val_loss: 1.0239
Epoch 20/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6625 - loss: 0.9476 - val_accuracy: 0.6570 - val_loss: 0.9538
Epoch 21/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6691 - loss: 0.9335 - val_accuracy: 0.6307 - val_loss: 1.0308
Epoch 22/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6735 - loss: 0.9200 - val_accuracy: 0.6537 - val_loss: 0.9773
Epoch 23/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6768 - loss: 0.9066 - val_accuracy: 0.6662 - val_loss: 0.9341
Epoch 24/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6827 - loss: 0.8946 - val_accuracy: 0.6704 - val_loss: 0.9290
Epoch 25/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6866 - loss: 0.8781 - val_accuracy: 0.6715 - val_loss: 0.9258
Epoch 26/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6908 - loss: 0.8713 - val_accuracy: 0.6726 - val_loss: 0.9244
Epoch 27/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6939 - loss: 0.8569 - val_accuracy: 0.6697 - val_loss: 0.9234
Epoch 28/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7003 - loss: 0.8456 - val_accuracy: 0.6763 - val_loss: 0.9097
Epoch 29/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7026 - loss: 0.8349 - val_accuracy: 0.6726 - val_loss: 0.9294
Epoch 30/30
625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.7093 - loss: 0.8212 - val_accuracy: 0.6805 - val_loss: 0.8976
学習時間:123.6秒 test_accuracy:0.6872

グラフ+サマリー

fig, axes = plt.subplots(1, 2, figsize=(14, 5))
for label, h in histories.items():
    axes[0].plot(h.history['val_accuracy'], label=label)
    axes[1].plot(h.history['val_loss'],     label=label)
axes[0].set_title('val_accuracy の比較(全30エポック)')
axes[1].set_title('val_loss の比較(全30エポック)')
for ax in axes:
    ax.set_xlabel('Epoch'); ax.legend(); ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('activation_comparison.png', dpi=150)
plt.show()

print("\n===== 最終結果サマリー =====")
print(f"{'Pattern':>8} | {'Val Acc':>8} | {'Test Acc':>9} | {'Time(s)':>8}")
print("-" * 42)
for label in ['relu', 'gelu', 'elu']:
    val_acc  = histories[label].history['val_accuracy'][-1]
    test_acc = scores[label][1]
    t        = times[label]
    print(f"{label:>8} | {val_acc:>8.4f} | {test_acc:>9.4f} | {t:>8.1f}")
print("-" * 42)

最終結果サマリー

===== 最終結果サマリー =====
 Pattern |  Val Acc |  Test Acc |  Time(s)
------------------------------------------
    relu |   0.6779 |    0.6752 |    133.1
    gelu |   0.6800 |    0.6818 |    123.4
     elu |   0.6805 |    0.6872 |    123.6
------------------------------------------

実験結果

精度グラフ

精度グラフ

損失グラフ

損失グラフ
パターン 最終 val_accuracy 最終 test_accuracy 学習時間 収束の傾向
A:relu 67.79% 67.52% 133.1秒 3パターン中最も低精度・最も遅い
B:gelu 68.00% 68.18% 123.4秒 relu比で速く・精度も上
C:elu 68.05% 68.72% 123.6秒 最高精度・geluとほぼ同速

考察

① reluが最下位になった理由

今回の実験では relu が精度・学習時間ともに最下位という結果になりました。test_accuracyはeluと比べて約1.2%低く、学習時間も約10秒長くなっています。

reluは負の入力で勾配がゼロになります(死んだReLU問題)。CIFAR-10のような複雑なタスクでは、負の値を持つ入力に対してニューロンが学習できなくなるケースが蓄積し、geluやeluと比べて表現力が制限された可能性があります。また、GAPの後のDense層でreluを使う場合、GAPによって平均化された特徴の一部が負値になったとき、それらの情報がそのまま捨てられてしまいます。

② gelu と elu の差が小さかった理由

geluとeluのtest_accuracyの差は0.54%と非常に小さく、学習時間もほぼ同じ(0.2秒差)です。どちらも負の入力に対して非ゼロの出力を持つという点が共通しており、死んだニューロン問題を回避できるため、CIFAR-10レベルでは同程度の効果があったと考えられます。

GELUはTransformerベースのモデル(BERT・GPT)で標準採用されており、大規模なモデルや自然言語処理タスクでの優位性が知られています。一方ELUは計算がやや単純で、今回のようなCNNモデルでは同等以上の性能が出やすい傾向があります。

③ Dense層のactivationだけを変えた影響はどれくらいか

今回はConv2D層のactivationはrelu固定で、Dense層のactivationだけを変える設計でした。最大の精度差は1.2%(relu vs elu)と小さい結果になりました。

これは「Dense層のactivationはそれほど重要でない」という意味ではありません。Conv2Dのrelu固定という条件の影響が大きく、仮にConv2D層もgeluやeluに変えた場合はより大きな差が出る可能性があります。activation関数の効果を完全に評価するには全層を統一して比較する実験が必要です。

④ MNISTとCIFAR-10で結果は変わったか

既存のMNIST版実験では4種類とも0.984〜0.988に収まり精度差はほぼありませんでした。CIFAR-10では最大1.2%の差が出ており、タスクが難しくなるほどactivation関数の選択が精度に影響しやすくなることが確認できました。


まとめ

  • elu が最高精度(68.72%)で、relu比で約1.2%上回った
  • gelu と elu はほぼ同精度・同速度(test_acc差0.54%・時間差0.2秒)で、どちらも relu より優位
  • relu は精度・学習時間ともに最下位。CIFAR-10レベルの難しいタスクでは死んだReLU問題の影響が出やすい可能性がある
  • Dense層のactivationだけを変えた場合の精度差は最大1.2%。Conv2D層まで含めて変えるとさらに差が出る可能性がある
  • MNISTでは差がほぼなかったが、CIFAR-10では傾向が明確に出た。タスクが難しいほどactivation関数の選択が重要になる

関連記事もあわせてどうぞ: