Augmentationシリーズ3回目です。
第1回では「flip + rotation + zoom + cropを重ねるほど精度が下がる」、
第2回では「rotationはどの角度でもCIFAR-10では逆効果」という結果になりました。
今回は RandomZoom の強度だけを5段階に変えて比較します。
rotationと異なりzoomは余白が生まれない変換のため、低解像度でも効果が出る可能性があります。
📘 この記事でわかること
RandomZoomの数値が実際にどの程度の拡大・縮小を意味するか- rotationと異なりzoomが低解像度でも有効になりうる理由
- CIFAR-10(32×32)に最適なzoom強度
- Augmentationシリーズ3回の実験を通じた最終推奨設定
RandomZoom の仕組み──rotationとの決定的な違い
Kerasの RandomZoom(height_factor) は、画像をランダムに拡大・縮小する変換です。
0.2 を指定すると ±20%の範囲でランダムにズーム します。
| zoom値 | 拡大・縮小範囲 | イメージ |
|---|---|---|
0.1 | ±10% | わずかに大きく・小さくなる |
0.2 | ±20% | やや拡大・縮小 |
0.3 | ±30% | 明確に被写体サイズが変わる |
0.5 | ±50% | 被写体が半分になるケースも |
rotationとの最大の違いは黒い余白が生まれない点です。
縮小時は画像端をコピーして埋め(fill_mode)、拡大時は中央部分をクロップして32×32に戻します。
32×32という小さな画像でもエッジ情報が失われにくく、
rotationより低解像度への影響が緩やかになることが期待できます。
📌 シリーズ前回記事:CIFAR-10にRandomRotationは逆効果?角度を変えて5段階で比較実験した結果【Keras】
実験で比較する5段階
全パターンに RandomFlip('horizontal') を統一適用し、
RandomZoom の値だけを変えます。
モデル構造・エポック数・バッチサイズ・オプティマイザは前回・前々回と同一です。
| パターン | zoom値 | 拡大・縮小範囲 | 狙い |
|---|---|---|---|
| A:0.0 | zoomなし | なし | flipのみのベースライン |
| B:0.1 | 0.1 | ±10% | 最小限のズーム |
| C:0.2 | 0.2 | ±20% | よく使われる標準値 |
| D:0.3 | 0.3 | ±30% | やや強めのズーム |
| E:0.5 | 0.5 | ±50% | 強めのズーム(上限確認) |
実験コード
環境準備(最初に一度だけ実行)
# ── 環境準備(最初に一度だけ実行)──────────────────────
!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 0s (64.3 MB/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 59.1 MB/s eta 0:00:00
Preparing metadata (setup.py) ... done
Building wheel for japanize_matplotlib (setup.py) ... done
環境準備完了
import・データ準備・Augmentationレイヤーの定義
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
# ── zoom値ごとのAugmentation定義 ────────────────────────
def get_augmentation(zoom_factor):
layers = [keras.layers.RandomFlip('horizontal')]
if zoom_factor > 0:
layers.append(keras.layers.RandomZoom(zoom_factor))
return keras.Sequential(layers, name=f'aug_zoom{zoom_factor}')
実行結果をクリックして内容を開く
Downloading data from https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz 170498071/170498071 ━━━━━━━━━━━━━━━━━━━━ 238s 1us/step
モデル構築関数
# ── モデル構築関数 ─────────────────────────────────────
def build_model(zoom_factor, name):
augmentation = get_augmentation(zoom_factor)
model = keras.Sequential([
keras.layers.Input(shape=(32, 32, 3)),
augmentation,
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(256, activation='relu'),
keras.layers.Dropout(0.2),
keras.layers.Dense(10, activation='softmax'),
], name=name)
model.compile(
optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
return model
5パターンの学習実行
EPOCHS = 30
BATCH = 64
configs = [
(0.0, 'A_zoom0.0'),
(0.1, 'B_zoom0.1'),
(0.2, 'C_zoom0.2'),
(0.3, 'D_zoom0.3'),
(0.5, 'E_zoom0.5'),
]
histories, scores, times = {}, {}, {}
for zoom, name in configs:
print(f"\n=== {name} ===")
model = build_model(zoom, name)
start = time.time()
h = model.fit(
x_train, y_train,
epochs=EPOCHS,
batch_size=BATCH,
validation_split=0.2,
verbose=1
)
elapsed = time.time() - start
score = model.evaluate(x_test, y_test, verbose=0)
label = name.split('_')[1] # 'zoom0.0' / 'zoom0.1' / ...
histories[label] = h
scores[label] = score
times[label] = elapsed
print(f"学習時間:{elapsed:.1f}秒 test_accuracy:{score[1]:.4f}")
実行結果をクリックして内容を開く
=== A_zoom0.0 === Epoch 1/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 16s 11ms/step - accuracy: 0.2887 - loss: 1.8719 - val_accuracy: 0.3702 - val_loss: 1.7261 Epoch 2/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 7ms/step - accuracy: 0.4026 - loss: 1.6086 - val_accuracy: 0.4296 - val_loss: 1.5420 Epoch 3/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4531 - loss: 1.4815 - val_accuracy: 0.4851 - val_loss: 1.4071 Epoch 4/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.4883 - loss: 1.3986 - val_accuracy: 0.5138 - val_loss: 1.3421 Epoch 5/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5074 - loss: 1.3419 - val_accuracy: 0.5333 - val_loss: 1.2914 Epoch 6/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 6ms/step - accuracy: 0.5267 - loss: 1.2961 - val_accuracy: 0.5434 - val_loss: 1.2512 Epoch 7/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5385 - loss: 1.2636 - val_accuracy: 0.5572 - val_loss: 1.2196 Epoch 8/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5526 - loss: 1.2269 - val_accuracy: 0.5600 - val_loss: 1.2073 Epoch 9/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5651 - loss: 1.1938 - val_accuracy: 0.5738 - val_loss: 1.1677 Epoch 10/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5782 - loss: 1.1593 - val_accuracy: 0.5870 - val_loss: 1.1387 Epoch 11/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.5894 - loss: 1.1357 - val_accuracy: 0.5925 - val_loss: 1.1275 Epoch 12/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.5983 - loss: 1.1147 - val_accuracy: 0.5969 - val_loss: 1.1115 Epoch 13/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6062 - loss: 1.0915 - val_accuracy: 0.6001 - val_loss: 1.0892 Epoch 14/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6174 - loss: 1.0659 - val_accuracy: 0.6210 - val_loss: 1.0474 Epoch 15/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6238 - loss: 1.0475 - val_accuracy: 0.6095 - val_loss: 1.1099 Epoch 16/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6287 - loss: 1.0319 - val_accuracy: 0.6326 - val_loss: 1.0193 Epoch 17/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6374 - loss: 1.0126 - val_accuracy: 0.6387 - val_loss: 0.9998 Epoch 18/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6434 - loss: 0.9934 - val_accuracy: 0.6467 - val_loss: 0.9910 Epoch 19/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6513 - loss: 0.9763 - val_accuracy: 0.6618 - val_loss: 0.9571 Epoch 20/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6525 - loss: 0.9666 - val_accuracy: 0.6573 - val_loss: 0.9542 Epoch 21/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6596 - loss: 0.9462 - val_accuracy: 0.6529 - val_loss: 0.9674 Epoch 22/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6650 - loss: 0.9351 - val_accuracy: 0.6638 - val_loss: 0.9323 Epoch 23/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6704 - loss: 0.9176 - val_accuracy: 0.6617 - val_loss: 0.9423 Epoch 24/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6732 - loss: 0.9101 - val_accuracy: 0.6671 - val_loss: 0.9264 Epoch 25/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6804 - loss: 0.8964 - val_accuracy: 0.6763 - val_loss: 0.9017 Epoch 26/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6846 - loss: 0.8828 - val_accuracy: 0.6762 - val_loss: 0.9034 Epoch 27/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6880 - loss: 0.8688 - val_accuracy: 0.6776 - val_loss: 0.9010 Epoch 28/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6909 - loss: 0.8589 - val_accuracy: 0.6712 - val_loss: 0.9184 Epoch 29/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 6ms/step - accuracy: 0.6952 - loss: 0.8480 - val_accuracy: 0.6901 - val_loss: 0.8706 Epoch 30/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 4s 7ms/step - accuracy: 0.6974 - loss: 0.8421 - val_accuracy: 0.6831 - val_loss: 0.8887 学習時間:133.8秒 test_accuracy:0.6810 === B_zoom0.1 === Epoch 1/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 10s 10ms/step - accuracy: 0.2621 - loss: 1.9290 - val_accuracy: 0.3570 - val_loss: 1.7243 Epoch 2/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.3715 - loss: 1.6740 - val_accuracy: 0.4169 - val_loss: 1.5716 Epoch 3/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.4317 - loss: 1.5489 - val_accuracy: 0.4411 - val_loss: 1.5032 Epoch 4/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.4707 - loss: 1.4550 - val_accuracy: 0.4861 - val_loss: 1.4018 Epoch 5/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.4914 - loss: 1.3965 - val_accuracy: 0.5130 - val_loss: 1.3227 Epoch 6/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5081 - loss: 1.3474 - val_accuracy: 0.5248 - val_loss: 1.3173 Epoch 7/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5225 - loss: 1.3119 - val_accuracy: 0.5459 - val_loss: 1.2563 Epoch 8/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5393 - loss: 1.2717 - val_accuracy: 0.5502 - val_loss: 1.2330 Epoch 9/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 9ms/step - accuracy: 0.5508 - loss: 1.2489 - val_accuracy: 0.5495 - val_loss: 1.2418 Epoch 10/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5616 - loss: 1.2115 - val_accuracy: 0.5693 - val_loss: 1.1681 Epoch 11/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5705 - loss: 1.1897 - val_accuracy: 0.5783 - val_loss: 1.1719 Epoch 12/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 11s 17ms/step - accuracy: 0.5749 - loss: 1.1740 - val_accuracy: 0.5815 - val_loss: 1.1594 Epoch 13/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 14s 22ms/step - accuracy: 0.5843 - loss: 1.1493 - val_accuracy: 0.5972 - val_loss: 1.1259 Epoch 14/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 14s 23ms/step - accuracy: 0.5916 - loss: 1.1297 - val_accuracy: 0.5817 - val_loss: 1.1649 Epoch 15/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 15s 24ms/step - accuracy: 0.5998 - loss: 1.1127 - val_accuracy: 0.6186 - val_loss: 1.0697 Epoch 16/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 12s 18ms/step - accuracy: 0.6079 - loss: 1.0880 - val_accuracy: 0.6028 - val_loss: 1.0937 Epoch 17/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 17s 13ms/step - accuracy: 0.6120 - loss: 1.0777 - val_accuracy: 0.5546 - val_loss: 1.2294 Epoch 18/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 8s 13ms/step - accuracy: 0.6229 - loss: 1.0587 - val_accuracy: 0.6302 - val_loss: 1.0256 Epoch 19/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 7s 8ms/step - accuracy: 0.6208 - loss: 1.0500 - val_accuracy: 0.6296 - val_loss: 1.0463 Epoch 20/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6316 - loss: 1.0319 - val_accuracy: 0.6352 - val_loss: 1.0143 Epoch 21/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6362 - loss: 1.0112 - val_accuracy: 0.6249 - val_loss: 1.0500 Epoch 22/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6378 - loss: 1.0057 - val_accuracy: 0.6361 - val_loss: 1.0178 Epoch 23/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 10s 8ms/step - accuracy: 0.6463 - loss: 0.9921 - val_accuracy: 0.6406 - val_loss: 0.9997 Epoch 24/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6490 - loss: 0.9786 - val_accuracy: 0.6281 - val_loss: 1.0434 Epoch 25/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6554 - loss: 0.9683 - val_accuracy: 0.6569 - val_loss: 0.9597 Epoch 26/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6578 - loss: 0.9569 - val_accuracy: 0.6631 - val_loss: 0.9493 Epoch 27/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6599 - loss: 0.9467 - val_accuracy: 0.6680 - val_loss: 0.9424 Epoch 28/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 9ms/step - accuracy: 0.6603 - loss: 0.9493 - val_accuracy: 0.6620 - val_loss: 0.9484 Epoch 29/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6665 - loss: 0.9306 - val_accuracy: 0.6330 - val_loss: 1.0167 Epoch 30/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 12s 19ms/step - accuracy: 0.6695 - loss: 0.9194 - val_accuracy: 0.6659 - val_loss: 0.9331 学習時間:228.8秒 test_accuracy:0.6671 === C_zoom0.2 === Epoch 1/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 7s 10ms/step - accuracy: 0.2655 - loss: 1.9275 - val_accuracy: 0.3778 - val_loss: 1.6807 Epoch 2/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.3821 - loss: 1.6585 - val_accuracy: 0.4117 - val_loss: 1.5975 Epoch 3/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.4382 - loss: 1.5361 - val_accuracy: 0.4430 - val_loss: 1.5510 Epoch 4/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.4719 - loss: 1.4505 - val_accuracy: 0.4882 - val_loss: 1.3885 Epoch 5/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.4961 - loss: 1.3876 - val_accuracy: 0.5262 - val_loss: 1.3197 Epoch 6/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5129 - loss: 1.3431 - val_accuracy: 0.5151 - val_loss: 1.3107 Epoch 7/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5236 - loss: 1.3134 - val_accuracy: 0.5167 - val_loss: 1.3101 Epoch 8/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5401 - loss: 1.2771 - val_accuracy: 0.5555 - val_loss: 1.2310 Epoch 9/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5497 - loss: 1.2524 - val_accuracy: 0.5404 - val_loss: 1.2634 Epoch 10/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5597 - loss: 1.2218 - val_accuracy: 0.5585 - val_loss: 1.2321 Epoch 11/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5714 - loss: 1.1975 - val_accuracy: 0.5775 - val_loss: 1.1478 Epoch 12/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5793 - loss: 1.1739 - val_accuracy: 0.5898 - val_loss: 1.1372 Epoch 13/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5852 - loss: 1.1544 - val_accuracy: 0.5939 - val_loss: 1.1237 Epoch 14/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5912 - loss: 1.1355 - val_accuracy: 0.5956 - val_loss: 1.1214 Epoch 15/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6007 - loss: 1.1197 - val_accuracy: 0.6099 - val_loss: 1.0918 Epoch 16/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6069 - loss: 1.1031 - val_accuracy: 0.6048 - val_loss: 1.1137 Epoch 17/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6120 - loss: 1.0826 - val_accuracy: 0.6323 - val_loss: 1.0461 Epoch 18/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6163 - loss: 1.0656 - val_accuracy: 0.6365 - val_loss: 1.0261 Epoch 19/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6255 - loss: 1.0475 - val_accuracy: 0.6394 - val_loss: 1.0141 Epoch 20/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6307 - loss: 1.0383 - val_accuracy: 0.6333 - val_loss: 1.0285 Epoch 21/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6358 - loss: 1.0213 - val_accuracy: 0.6480 - val_loss: 1.0041 Epoch 22/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6369 - loss: 1.0093 - val_accuracy: 0.6171 - val_loss: 1.0765 Epoch 23/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6402 - loss: 1.0048 - val_accuracy: 0.6644 - val_loss: 0.9465 Epoch 24/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6488 - loss: 0.9860 - val_accuracy: 0.6639 - val_loss: 0.9407 Epoch 25/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6510 - loss: 0.9833 - val_accuracy: 0.6737 - val_loss: 0.9238 Epoch 26/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6549 - loss: 0.9670 - val_accuracy: 0.6624 - val_loss: 0.9619 Epoch 27/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6612 - loss: 0.9532 - val_accuracy: 0.6713 - val_loss: 0.9323 Epoch 28/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 9ms/step - accuracy: 0.6608 - loss: 0.9573 - val_accuracy: 0.6768 - val_loss: 0.9191 Epoch 29/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6664 - loss: 0.9366 - val_accuracy: 0.6735 - val_loss: 0.9314 Epoch 30/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6684 - loss: 0.9303 - val_accuracy: 0.6795 - val_loss: 0.9074 学習時間:164.3秒 test_accuracy:0.6759 === D_zoom0.3 === Epoch 1/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 7s 9ms/step - accuracy: 0.2564 - loss: 1.9481 - val_accuracy: 0.3420 - val_loss: 1.7478 Epoch 2/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.3586 - loss: 1.7144 - val_accuracy: 0.3913 - val_loss: 1.6480 Epoch 3/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.4055 - loss: 1.6109 - val_accuracy: 0.4349 - val_loss: 1.5120 Epoch 4/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.4401 - loss: 1.5267 - val_accuracy: 0.4769 - val_loss: 1.4239 Epoch 5/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.4673 - loss: 1.4621 - val_accuracy: 0.4967 - val_loss: 1.3760 Epoch 6/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.4809 - loss: 1.4182 - val_accuracy: 0.5086 - val_loss: 1.3278 Epoch 7/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.4981 - loss: 1.3763 - val_accuracy: 0.5194 - val_loss: 1.3058 Epoch 8/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5137 - loss: 1.3468 - val_accuracy: 0.5284 - val_loss: 1.2809 Epoch 9/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5245 - loss: 1.3143 - val_accuracy: 0.5417 - val_loss: 1.2579 Epoch 10/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5313 - loss: 1.2954 - val_accuracy: 0.5368 - val_loss: 1.2848 Epoch 11/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5437 - loss: 1.2651 - val_accuracy: 0.5646 - val_loss: 1.1878 Epoch 12/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 9ms/step - accuracy: 0.5509 - loss: 1.2450 - val_accuracy: 0.5701 - val_loss: 1.1766 Epoch 13/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5617 - loss: 1.2173 - val_accuracy: 0.5863 - val_loss: 1.1495 Epoch 14/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5638 - loss: 1.2073 - val_accuracy: 0.5895 - val_loss: 1.1266 Epoch 15/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5782 - loss: 1.1734 - val_accuracy: 0.5945 - val_loss: 1.1157 Epoch 16/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5819 - loss: 1.1608 - val_accuracy: 0.5916 - val_loss: 1.1322 Epoch 17/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5869 - loss: 1.1471 - val_accuracy: 0.6107 - val_loss: 1.0742 Epoch 18/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5957 - loss: 1.1297 - val_accuracy: 0.6148 - val_loss: 1.0582 Epoch 19/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6037 - loss: 1.1074 - val_accuracy: 0.6196 - val_loss: 1.0487 Epoch 20/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 9ms/step - accuracy: 0.6068 - loss: 1.0887 - val_accuracy: 0.6104 - val_loss: 1.0813 Epoch 21/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6108 - loss: 1.0878 - val_accuracy: 0.6261 - val_loss: 1.0433 Epoch 22/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6172 - loss: 1.0692 - val_accuracy: 0.6324 - val_loss: 1.0224 Epoch 23/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 10s 9ms/step - accuracy: 0.6222 - loss: 1.0558 - val_accuracy: 0.6274 - val_loss: 1.0285 Epoch 24/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6264 - loss: 1.0468 - val_accuracy: 0.6164 - val_loss: 1.0609 Epoch 25/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6304 - loss: 1.0387 - val_accuracy: 0.6451 - val_loss: 0.9854 Epoch 26/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6310 - loss: 1.0351 - val_accuracy: 0.6265 - val_loss: 1.0527 Epoch 27/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6343 - loss: 1.0203 - val_accuracy: 0.6553 - val_loss: 0.9653 Epoch 28/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6398 - loss: 1.0114 - val_accuracy: 0.6510 - val_loss: 0.9706 Epoch 29/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6444 - loss: 1.0001 - val_accuracy: 0.6550 - val_loss: 0.9734 Epoch 30/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6463 - loss: 0.9969 - val_accuracy: 0.6392 - val_loss: 1.0068 学習時間:167.2秒 test_accuracy:0.6394 === E_zoom0.5 === Epoch 1/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 7s 9ms/step - accuracy: 0.2549 - loss: 1.9579 - val_accuracy: 0.3366 - val_loss: 1.7445 Epoch 2/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.3503 - loss: 1.7416 - val_accuracy: 0.4073 - val_loss: 1.6336 Epoch 3/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.3997 - loss: 1.6325 - val_accuracy: 0.4445 - val_loss: 1.5129 Epoch 4/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.4283 - loss: 1.5610 - val_accuracy: 0.4564 - val_loss: 1.4715 Epoch 5/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.4538 - loss: 1.5022 - val_accuracy: 0.4936 - val_loss: 1.3912 Epoch 6/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.4708 - loss: 1.4526 - val_accuracy: 0.5098 - val_loss: 1.3494 Epoch 7/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 9ms/step - accuracy: 0.4868 - loss: 1.4195 - val_accuracy: 0.5328 - val_loss: 1.2903 Epoch 8/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.4997 - loss: 1.3801 - val_accuracy: 0.5352 - val_loss: 1.2697 Epoch 9/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5092 - loss: 1.3566 - val_accuracy: 0.5529 - val_loss: 1.2342 Epoch 10/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5217 - loss: 1.3314 - val_accuracy: 0.5333 - val_loss: 1.2654 Epoch 11/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5278 - loss: 1.3070 - val_accuracy: 0.5699 - val_loss: 1.1893 Epoch 12/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5346 - loss: 1.2840 - val_accuracy: 0.5722 - val_loss: 1.1899 Epoch 13/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5481 - loss: 1.2604 - val_accuracy: 0.5860 - val_loss: 1.1424 Epoch 14/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5530 - loss: 1.2444 - val_accuracy: 0.5903 - val_loss: 1.1302 Epoch 15/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5594 - loss: 1.2212 - val_accuracy: 0.5871 - val_loss: 1.1408 Epoch 16/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5677 - loss: 1.2068 - val_accuracy: 0.5770 - val_loss: 1.1768 Epoch 17/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5689 - loss: 1.2025 - val_accuracy: 0.6053 - val_loss: 1.0983 Epoch 18/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5783 - loss: 1.1822 - val_accuracy: 0.6222 - val_loss: 1.0595 Epoch 19/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5841 - loss: 1.1660 - val_accuracy: 0.6208 - val_loss: 1.0621 Epoch 20/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5871 - loss: 1.1513 - val_accuracy: 0.6208 - val_loss: 1.0639 Epoch 21/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.5903 - loss: 1.1446 - val_accuracy: 0.6120 - val_loss: 1.0826 Epoch 22/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.5965 - loss: 1.1319 - val_accuracy: 0.6378 - val_loss: 1.0154 Epoch 23/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6012 - loss: 1.1205 - val_accuracy: 0.6162 - val_loss: 1.0740 Epoch 24/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6028 - loss: 1.1091 - val_accuracy: 0.6346 - val_loss: 1.0260 Epoch 25/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6082 - loss: 1.0979 - val_accuracy: 0.6342 - val_loss: 1.0226 Epoch 26/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6106 - loss: 1.0903 - val_accuracy: 0.6350 - val_loss: 1.0214 Epoch 27/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6139 - loss: 1.0841 - val_accuracy: 0.6480 - val_loss: 0.9889 Epoch 28/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6212 - loss: 1.0695 - val_accuracy: 0.6521 - val_loss: 0.9642 Epoch 29/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step - accuracy: 0.6248 - loss: 1.0590 - val_accuracy: 0.6527 - val_loss: 0.9891 Epoch 30/30 625/625 ━━━━━━━━━━━━━━━━━━━━ 6s 9ms/step - accuracy: 0.6264 - loss: 1.0548 - val_accuracy: 0.6537 - val_loss: 0.9681 学習時間:162.6秒 test_accuracy:0.6535
グラフ描画・サマリー
# ── val_accuracy / val_loss 比較グラフ ───────────────────
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('zoom_val.png', dpi=150)
plt.show()
# ── train vs val(過学習の乖離)────────────────────────
fig2, axes2 = plt.subplots(1, 2, figsize=(14, 5))
for ax, label in zip(axes2, ['zoom0.0', 'zoom0.2']):
h = histories[label]
ax.plot(h.history['loss'], label='train_loss')
ax.plot(h.history['val_loss'], label='val_loss')
ax.set_title(f'{label}:train vs val loss')
ax.set_xlabel('Epoch'); ax.legend(); ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('zoom_overfit.png', dpi=150)
plt.show()
# ── サマリー ─────────────────────────────────────────────
print("\n===== 最終結果サマリー =====")
print(f"{'Pattern':>10} | {'Zoom Range':>12} | {'Val Acc':>8} | {'Test Acc':>9} | {'Time(s)':>8}")
print("-" * 60)
range_map = {'zoom0.0': 'なし', 'zoom0.1': '±10%',
'zoom0.2': '±20%', 'zoom0.3': '±30%', 'zoom0.5': '±50%'}
for label, h in histories.items():
val_acc = h.history['val_accuracy'][-1]
test_acc = scores[label][1]
t = times[label]
rng = range_map[label]
print(f"{label:>10} | {rng:>12} | {val_acc:>8.4f} | {test_acc:>9.4f} | {t:>8.1f}")
print("-" * 60)
最終結果サマリー
===== 最終結果サマリー ===== Pattern | Zoom Range | Val Acc | Test Acc | Time(s) ------------------------------------------------------------ zoom0.0 | なし | 0.6831 | 0.6810 | 133.8 zoom0.1 | ±10% | 0.6659 | 0.6671 | 228.8 zoom0.2 | ±20% | 0.6795 | 0.6759 | 164.3 zoom0.3 | ±30% | 0.6392 | 0.6394 | 167.2 zoom0.5 | ±50% | 0.6537 | 0.6535 | 162.6 ------------------------------------------------------------
実験結果
精度グラフ
損失グラフ
zoom0.0
zoom0.2
| パターン | 拡大・縮小範囲 | 最終 val_accuracy | 最終 test_accuracy | 学習時間 |
|---|---|---|---|---|
| A:zoom0.0 | なし(flipのみ) | 68.31% | 68.10% | 133.8秒 |
| B:zoom0.1 | ±10% | 66.59% | 66.71% | 228.8秒 |
| C:zoom0.2 | ±20% | 67.95% | 67.59% | 164.3秒 |
| D:zoom0.3 | ±30% | 63.92% | 63.94% | 167.2秒 |
| E:zoom0.5 | ±50% | 65.37% | 65.35% | 162.6秒 |
最も良かったのはrotation実験と同様にzoomなし(flipのみ)のパターンAでした。
ただしrotationと異なり、zoom0.2はベースラインとの差がわずか0.5ポイントに留まっており、
zoomはrotationより低解像度への影響が緩やかであることが確認できます。
また、zoom0.1よりzoom0.2の方が精度が高いという逆転現象も見られました。
考察
① zoomはrotationより低解像度への影響が緩やかだった
rotationでは最小の0.03(±10.8度)でさえ精度が約3.1ポイント低下しましたが、 zoom0.2では低下幅が約0.5ポイントに留まりました。 この差は余白の有無によるものです。 rotationはコーナーに黒い余白が生まれ被写体が歪みますが、 zoomは拡大・縮小後に32×32にリサイズするため余白が生まれません。 被写体の形そのものは維持されやすいという特性が、 低解像度での影響を小さくしています。
② zoom0.1よりzoom0.2の方が精度が高かった理由
zoom0.1(±10%)よりzoom0.2(±20%)の方が精度が高いという逆転は、 zoom0.1の変化が小さすぎてAugmentationとして機能しきれていない可能性を示しています。 わずかな拡大・縮小はモデルにとって「ほぼ同じ画像」に見えるため、 過学習抑制の効果が薄くなります。 一方zoom0.2は変化量が適度で、モデルが「スケールの違う被写体」として認識できる ちょうどよい強さだったと考えられます。
③ zoom0.3・0.5で精度が落ちた理由
zoom0.3(±30%)以上では縮小方向に振れた場合、 32×32という小さなCIFAR-10の画像がさらに小さくなり、 被写体が数ピクセルに収まってしまうケースが増えます。 モデルが学ぶべき特徴量が失われ、精度が低下します。 また拡大方向では中央部のみがクロップされるため、 被写体が画像の端にある場合に特徴が欠落します。
④ zoom0.5でzoom0.3より精度が高い逆転について
zoom0.3(63.94%)よりzoom0.5(65.35%)の方が若干精度が高い点は一見不思議ですが、 これはランダム性による実行ごとのばらつきの範囲内と考えられます。 30エポック・単一実験での比較であるため、複数回実行した平均で比較すると 差が逆転する可能性もあります。
⑤ 学習時間の異常値:zoom0.1で228秒
zoom0.1の学習時間(228.8秒)はzoom0.2〜0.5(約163〜167秒)と比較して 約65秒も長くなっています。これはColabのGPU割り当て状況や セッション初期化のタイミングによる実行環境のばらつきと考えられます。 zoom強度と学習時間には本来相関がなく、zoomレイヤーの有無による 追加コストはどのzoom値でもほぼ同等のはずです。
Augmentationシリーズ3回の総まとめ
3回の実験(flip・rotation・zoom)を通じた結果を集約します。
| 実験 | 最良パターン | test_accuracy | 結論 |
|---|---|---|---|
| 第1回:flip〜crop比較 | flip のみ | 69.35% | 重ねるほど逆効果 |
| 第2回:rotation角度比較 | rotation なし(flip のみ) | 68.42% | どの角度でも逆効果 |
| 第3回:zoom強度比較 | zoom なし(flip のみ) | 68.10% | rotationより影響は緩やか。zoom0.2はベースラインに迫る |
CIFAR-10(32×32)向けの最終推奨設定
| Augmentation | 推奨 | 理由 |
|---|---|---|
| RandomFlip | ✅ 使う | 余白なし・コスト小・効果あり(最良) |
| RandomZoom | ⚠️ 0.2以下なら検討余地あり | rotationより影響が緩やか。ただしflipのみより精度は下がる |
| RandomRotation | ❌ 使わない | どの角度でも精度が下がる |
| RandomCrop | ❌ 単独では使わない | 他の変換との重ね掛けで最悪化 |
3回の実験を通じた最終結論は「CIFAR-10ではRandomFlipのみが最善」です。
zoomはrotationと異なり影響が緩やかで、zoom0.2ならベースラインとの差が0.5ポイント程度に留まります。
ただし精度を最優先するなら、flipのみのシンプルな構成が最も安定しています。
Augmentationはデータセットの解像度と特性に合った手法を選ぶことが、実験を通じた一貫した教訓です。
関連記事もあわせてどうぞ:
- シリーズ第1回 → Data Augmentationを重ねすぎると精度が下がる?flip〜cropの5パターンをCIFAR-10で比較【Keras実験】
- シリーズ第2回 → CIFAR-10にRandomRotationは逆効果?角度を変えて5段階で比較実験した結果【Keras】
- Dropoutとの組み合わせ → Dropoutの割合(0.0 vs 0.2 vs 0.5)を変えると過学習はどう変わる?【Keras×CIFAR-10実験】
- 過学習の判定方法 → CIFAR-10で学ぶ:過学習(オーバーフィッティング)の判定方法と実践的対策
- 学習曲線の見方 → Kerasで学習曲線を可視化する方法【過学習の発見と対策まで】





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