各クラス10枚の画像で機械学習モデルは学習できるのか?Keras×MNISTで検証

2025年5月21日水曜日

Google Colab Keras データ拡張 画像分類 機械学習

X f B! P L
アイキャッチ画像 各クラス10枚の画像で機械学習モデルは学習できるのか?Keras×MNISTで検証

はじめに

こんにちは、SHOUです!
今回は「各クラス10枚の画像だけで機械学習モデルを訓練した場合、どこまで分類精度が出せるのか?」というテーマで実験を行いました。

画像分類モデルを作る際に最も課題となるのが、「学習データの少なさ」です。
ラベル付き画像を大量に用意するのは難しく、現実のプロジェクトでは「数十枚しかない」という場面も珍しくありません。

今回はあえて、1クラスあたり10枚、全体で100枚の手書き数字画像を使い、Kerasの多層パーセプトロン(MLP)でどこまで分類可能かを検証しました。

実験の条件

今回の実験の条件は以下の通りです。

  • クラス数:10(0〜9の手書き数字)
  • 1クラスあたりの画像数:10枚(合計100枚)
  • モデル:Kerasによる多層パーセプトロン
  • 学習環境:Google Colab + GPU
  • データ拡張:あり(回転・ズーム・シフトなど)

画像はすべて28×28ピクセルのグレースケール画像に統一しました。

学習の様子

100枚の画像だけでは学習に必要な多様性が足りないため、ImageDataGeneratorを使って様々なバリエーションを自動生成しました。
この技術を「データ拡張」と呼び、少ないデータで学習を成立させるためにとても有効な手段です。

Google DriveをColabにマウント

まず、Google Drive を Colab に接続します👇
from google.colab import drive
drive.mount('/content/drive')
すると、認証リンクが出るので、指示に従って認証してください。
マウントが完了すると、Drive のファイルが /content/drive/MyDrive/ 以下に見えるようになります。

データ拡張

1枚の画像から10通り以上のパターンが生成されます。
これにより、実際には100枚でも「1000枚分」の情報を学習させることが可能になります。


from tensorflow.keras.preprocessing.image import ImageDataGenerator

# データ拡張の設定
datagen = ImageDataGenerator(
    rescale=1./255,         # 正規化
    preprocessing_function=lambda x: 1.0 - x,  # 白黒反転
    rotation_range=30,      # 回転
    width_shift_range=10,   # 横移動
    height_shift_range=10,  # 縦移動
    zoom_range=0.1,         # ズーム
    shear_range=0.1,        # 傾き
    validation_split=0.2    # 検証データ分割
)

train_generator = datagen.flow_from_directory(
    '/content/drive/MyDrive/Colab/digits',
    target_size=(28, 28),
    color_mode='grayscale',
    batch_size=32,
    class_mode='sparse',
    subset='training',
    shuffle=True
)

val_generator = datagen.flow_from_directory(
    '/content/drive/MyDrive/Colab/digits',
    target_size=(28, 28),
    color_mode='grayscale',
    batch_size=32,
    class_mode='sparse',
    subset='validation'
)

学習

モデルはKerasのSequential APIでシンプルに構築しました。
入力画像を1次元に変換(Flatten)し、128ユニットの全結合層とDropout層を通じて過学習を防止、最後に10クラスのsoftmaxで分類する構成です。

import tensorflow as tf
from tensorflow import keras

model = keras.models.Sequential([
    keras.layers.Input(shape=(28, 28, 1)),
    keras.layers.Flatten(),
    keras.layers.Dense(128, activation='relu'),
    keras.layers.Dropout(0.3),
    keras.layers.Dense(10, activation='softmax')
])

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

# 学習
history = model.fit(train_generator,epochs=30,validation_data=val_generator)

簡素な構成ですが、過学習対策や損失関数の工夫も取り入れています。
それでも、データが少なすぎると限界があります。

学習結果と限界

30エポックにわたって学習を行ったものの、精度の向上はほとんど見られませんでした。
以下はログの一部です。

Epoch 1/30
3/3 ━━━━━━━━━━━━━━━━━━━━ 2s 273ms/step - accuracy: 0.0432 - loss: 2.9863 - val_accuracy: 0.1500 - val_loss: 2.4238
Epoch 2/30
3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 190ms/step - accuracy: 0.0625 - loss: 2.7927 - val_accuracy: 0.0500 - val_loss: 2.3816
Epoch 3/30
3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 149ms/step - accuracy: 0.0688 - loss: 2.5960 - val_accuracy: 0.1500 - val_loss: 2.3417
Epoch 4/30
3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 156ms/step - accuracy: 0.1023 - loss: 2.4672 - val_accuracy: 0.1000 - val_loss: 2.3062
Epoch 5/30
・・・
Epoch 26/30
3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 175ms/step - accuracy: 0.0646 - loss: 2.3042 - val_accuracy: 0.1000 - val_loss: 2.3020
Epoch 27/30
3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 194ms/step - accuracy: 0.1177 - loss: 2.3022 - val_accuracy: 0.0500 - val_loss: 2.3025
Epoch 28/30
3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 146ms/step - accuracy: 0.1203 - loss: 2.3023 - val_accuracy: 0.1000 - val_loss: 2.3026
Epoch 29/30
3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 160ms/step - accuracy: 0.0932 - loss: 2.3028 - val_accuracy: 0.1000 - val_loss: 2.3026
Epoch 30/30
3/3 ━━━━━━━━━━━━━━━━━━━━ 0s 153ms/step - accuracy: 0.0818 - loss: 2.3028 - val_accuracy: 0.1000 - val_loss: 2.3026

学習ログを見ると、「学習しているように見えて、実はほぼ何も学習していない」という状態となっています。

  • accuracy: ~0.08 〜 0.15
  • val_accuracy: 0.05 〜 0.15
  • loss: ≈ 2.30

まとめ:極端に少ない画像では、機械学習はほとんど学習できない

今回の実験では、1クラス10枚、合計100枚の画像データでKerasモデルを訓練しましたが、精度は向上せず、「ほぼ学習していない状態」と なりました。

このように、画像分類においてはある程度のデータ量が必要であることがわかりました。次回は、「事前学習済みCNNモデル」や「転移学習」を用いた手法で、 少量データでも精度を高める方法を検証していきます。

原因の本質

  • 学習画像が極端に少ない(各クラス8枚)
  • 検証データも各クラス2枚では評価できない

有効な対策

  1. 事前学習モデルを活用する
    例えば、MNISTで学習済みのCNNをベースに、自作データでファインチューニングを行う。

  2. Conv2Dを使ったCNNモデルに変更する
    空間構造を活かす畳み込み層は、画像の特徴抽出に特に効果的です。
    model = keras.models.Sequential([
        keras.layers.Input(shape=(28, 28, 1)),
        keras.layers.Conv2D(32, (3, 3), activation='relu'),
        keras.layers.MaxPooling2D((2, 2)),
        keras.layers.Conv2D(64, (3, 3), activation='relu'),
        keras.layers.MaxPooling2D((2, 2)),
        keras.layers.Flatten(),
        keras.layers.Dense(64, activation='relu'),
        keras.layers.Dense(10, activation='softmax')
    ])

  3. データ拡張をさらに強化する
    より強いノイズや変形を加えて、モデルの汎化能力を高める。
    datagen = ImageDataGenerator(
        rescale=1./255,
        preprocessing_function=lambda x: 1.0 - x,
        rotation_range=40,
        width_shift_range=0.3,
        height_shift_range=0.3,
        zoom_range=0.2,
        shear_range=0.2,
        validation_split=0.2
    )

関連記事

このブログを検索

自己紹介

はじめまして、機械学習を独学中のSHOU TAKEと申します。本ブログでは、Python・Keras・Google Colabを活用した画像分類やニューラルネットワークの実験記事を中心に発信しています。初学者の方にも分かりやすく、学んだことをそのまま実験形式でまとめるスタイルです。これまで取り組んだテーマには、学習率やOptimizerの比較、Batch Sizeの検証、事前学習の活用などがあります。ご質問やご感想は、お問い合わせフォームからお気軽にどうぞ。

お問い合わせフォーム

名前

メール *

メッセージ *

プライバシーポリシー

QooQ