PythonとKerasで作る画像分類モデル:CNNによる実装手順を完全解説
画像分類とは
画像分類(Image Classification)とは、コンピュータビジョンにおける基本的なタスクの一つで、入力された画像をあらかじめ定義されたカテゴリへ自動的に振り分ける技術です。ディープラーニングを活用することで、高精度な画像分類モデルを比較的簡単に構築できます。
画像分類モデルを構築する主なアプローチとして、以下の2つの方法が挙げられます。
- 小規模なネットワークをスクラッチから学習させる — シンプルなタスクやデータセットが限られている場合に有効です。
- VGG16など事前学習済みモデルの上位層をファインチューニングする — 転移学習によって、少ないデータでも高い精度を実現できます。
本記事では、前者の「スクラッチからCNN(畳み込みニューラルネットワーク)を構築して学習させる」方法を、Kerasを使った具体的なコード例とともに解説します。
全体のコード例
# 必要なライブラリをインポート
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras import backend as K
# train_data_dir:訓練データセットのディレクトリ
# validation_data_dir:検証データ用のディレクトリ
# nb_train_samples:訓練サンプルの総数
# nb_validation_samples:検証サンプルの総数
img_width, img_height = 224, 224
train_data_dir = 'v_data/train'
validation_data_dir = 'v_data/test'
nb_train_samples = 400
nb_validation_samples = 100
epochs = 10
batch_size = 16
# 画像データの形式(チャンネルの並び)を確認
if K.image_data_format() == 'channels_first':
input_shape = (3, img_width, img_height)
else:
input_shape = (img_width, img_height, 3)
model = Sequential()
# Conv2D:画像を畳み込むための層
model.add(Conv2D(32, (2, 2), input_shape=input_shape))
# Activation:活性化関数
model.add(Activation('relu'))
# MaxPooling2D:指定サイズの行列から最大値をプーリング
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(32, (2, 2)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(64, (2, 2)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
# Flatten:多次元の出力を1次元ベクトルに変換
model.add(Flatten())
# Dense:全結合Dense:全結合層(隠れ層)
model.add(Dense(64))
model.add(Activation('relu'))
# Dropout:過学習(オーバーフィッティング)を防止
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))
# compile:損失関数・オプティマイザ・評価指標を指定
# 損失関数にbinary_crossentropy、オプティマイザにrmspropを使用
model.compile(loss='binary_crossentropy', optimizer='rmsprop', metrics=['accuracy'])
# ImageDataGenerator:リスケール・せん断・ズーム・水平反転によるデータ拡張
train_datagen = ImageDataGenerator(rescale=1. / 255, shear_range=0.2, zoom_range=0.2, horizontal_flip=True)
test_datagen = ImageDataGenerator(rescale=1. / 255)
# flow_from_directory:ディレクトリからデータを読み込む
# target_sizeで画像のサイズを統一
train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode='binary')
validation_generator = test_datagen.flow_from_directory(
validation_data_dir,
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode='binary')
# fit_generator:モデルにデータを適合させる
# steps_per_epoch:1エポックあたりのステップ数
# epochs:学習の繰り返し回数(順伝播と逆伝播の実行回数)
# validation_data:検証データ
# validation_steps:検証ステップ数
model.fit_generator(
train_generator,
steps_per_epoch=nb_train_samples // batch_size,
epochs=epochs,
validation_data=validation_generator,
validation_steps=nb_validation_samples // batch_size)
# 学習済みモデルの重みを保存
model.save_weights('ImgmodelKeras_saved.h5')
コードのポイント解説
1. CNNモデルの構造
このモデルは、Conv2D(畳み込み層)、Activation(ReLU活性化関数)、MaxPooling2D(最大プーリング層)の組み合わせを3ブロック重ねた典型的なCNN構成です。フィルタ数は32→32→64と段階的に増やしており、浅い層では線や模様といった単純な特徴を、深い層ではより複雑な特徴を抽出します。
その後、Flattenで特徴マップを1次元化し、Dense層(全結合層)につなぐことで分類を行います。出力層は2クラス分類を想定しているため、ユニット数1のDense層にシグモイド活性化関数を適用し、0〜1の確率値を出力します。
2. 過学習対策としてのDropout
Dropout(0.5)は、学習時に各ユニットを50%の確率で無効化する手法です。これによりモデルが特定の特徴に依存しすぎることを防ぎ、汎化性能の向上が期待できます。データセットが小さい場合(本例では訓練サンプル400枚)には特に重要なテクニックです。
3. ImageDataGeneratorによるデータ拡張
ImageDataGeneratorを使うと、画像のリスケール(0〜1への正規化)、せん断(shear)、ズーム、水平反転などをリアルタイムに適用したデータ拡張が可能です。これにより、実質的な訓練データのバリエーションが増え、少ないデータでも頑健なモデルを学習できます。
4. モデルのコンパイルと学習
compile()では、2クラス分類向けの損失関数「binary_crossentropy」、オプティマイザ「rmsprop」、評価指標「accuracy」を指定しています。fit_generator()にジェネレータを渡すことで、メモリに収まらない大量の画像データもバッチ単位で効率的に学習できます。
注意点:新しいKerasでの書き方
TensorFlow 2.x以降のKerasでは、fit_generator()およびflow_from_directory()は非推奨となり、ジェネレータをそのままmodel.fit()に渡せるようになりました。最新環境では以下のように書き換えることをおすすめします。
model.fit(
train_generator,
steps_per_epoch=nb_train_samples // batch_size,
epochs=epochs,
validation_data=validation_generator,
validation_steps=nb_validation_samples // batch_size)
まとめ
Kerasを使えば、畳み込み層とプーリング層を積み重ねるだけで直感的にCNNモデルを構築でき、ImageDataGeneratorによるデータ拡張と組み合わせることで、数百枚程度の画像データからでも実用的な2クラス分類モデルを作成できます。まずは本記事のコードを実際に動かしてみて、画像分類の基礎を体感してみてください。
-
Pythonで理解する畳み込みニューラルネットワーク(CNN)の基礎とSobelフィルタによるエッジ検出
画像認識はかつて、線形回帰や類似度の比較といった、より単純な手法によって行われていました。その結果は決して良いものではなく、手書き文字のアルファベットを認識するという単純なタスクさえ困難でした。畳み込みニューラルネットワーク(CNN)は、人間が画像を知覚する際の脳の神経活動を緩やかに模倣する、計算コストの低い手法を提供することで、従来のアプローチから一歩進んだ存在となっています。畳み込みニューラルネットワーク(CNN)の概要人間がさまざまな物体を認識できるようになる過程と非常に似ていて、コンピュータのアルゴリズムも、入力を汎化し、初めて見る画像に対して判断を下せるようになるまでに、何百万もの画
-
Pythonで画像を読み込む方法:OpenCVとPILを使った基本操作を解説
OpenCVによる画像処理OpenCV(Open Source Computer Vision)は、機械学習とコンピュータビジョンのために開発されたオープンソースのプログラミングライブラリです。コンピュータビジョンアプリケーション開発のための共通基盤を提供し、商用製品への機械学習の導入を迅速化します。OpenCVには、2,500以上の最適化されたアルゴリズムが含まれており、古典的な手法から最先端の手法まで、コンピュータビジョンと機械学習の両分野をカバーしています。これらの豊富なアルゴリズムにより、顔検出・認識、物体识别、動画内の人間の動作の分類、カメラの動きの追跡、複数画像の結合による高解像度