中間層の特徴マップを可視化してみた|Keras × CNN × MNIST

2025年6月24日火曜日

CNN Google Colab Keras MNIST

アイキャッチ画像 中間層の特徴マップを可視化してみた

はじめに

畳み込みニューラルネットワーク(CNN)は画像認識に強力な性能を持つモデルです。しかし、その「中身」はブラックボックスになりがちです。この記事では、中間層の出力(特徴マップ)を可視化し、CNNが画像からどんな特徴を抽出しているのかを探ってみます。

使用環境

  • TensorFlow / Keras
  • MNIST手書き数字データセット
  • Matplotlibによる描画

データ準備とモデル構築

import tensorflow as tf
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.astype("float32") / 255.0
x_test = x_test.astype("float32") / 255.0
x_train = np.expand_dims(x_train, -1)
x_test = np.expand_dims(x_test, -1)

# CNNモデル構築
inputs = keras.Input(shape=(28, 28, 1))
x = layers.Conv2D(16, 3, activation='relu', name='conv1')(inputs)
x = layers.MaxPooling2D()(x)
x = layers.Conv2D(32, 3, activation='relu', name='conv2')(x)
x = layers.MaxPooling2D()(x)
x = layers.Flatten()(x)
outputs = layers.Dense(10, activation='softmax')(x)
model = keras.Model(inputs, outputs)

model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(x_train, y_train, epochs=3, validation_split=0.1)

中間層の出力を取得する

ここでは1枚の画像を使い、Conv層の出力を取得します。

# 可視化対象の画像(例:3)
idx = 0
img = x_test[idx:idx+1]

# 中間層出力モデルを作成
layer_outputs = [layer.output for layer in model.layers if 'conv' in layer.name]
activation_model = keras.Model(inputs=model.input, outputs=layer_outputs)

# 特徴マップを取得
activations = activation_model.predict(img)

特徴マップの描画

import matplotlib.pyplot as plt

# 特徴マップを表示する関数
def display_feature_maps(activations, layer_names, cols=8):
    for layer_name, feature_map in zip(layer_names, activations):
        num_filters = feature_map.shape[-1]
        rows = (num_filters + cols - 1) // cols  # 必要な行数を自動計算

        plt.figure(figsize=(cols * 1.5, rows * 1.5))  # サイズ調整
        for i in range(num_filters):
            plt.subplot(rows, cols, i + 1)
            plt.imshow(feature_map[0, :, :, i], cmap='viridis')
            plt.axis('off')
        plt.suptitle(f"Layer: {layer_name}", fontsize=14)
        plt.tight_layout()
        plt.subplots_adjust(top=0.9)  # タイトルのための余白
        plt.show()

# レイヤー名を取得
layer_names = [layer.name for layer in model.layers if 'conv' in layer.name]

# 実行
display_feature_maps(activations, layer_names)

特徴マップの描画結果

Conv1層目の特徴マップ

Conv1層目の特徴マップ

Conv2層目の特徴マップ

Conv2層目の特徴マップ

結果と考察

Conv1層では輪郭や直線の抽出が、Conv2層ではより複雑なパターンの抽出が行われていることがわかります。CNNは階層的に情報を抽象化していく構造になっていることが、視覚的に理解できました。

まとめ

中間層の可視化により、CNNがどのように画像を解釈しているかを視覚的に捉えることができます。ブラックボックスとされがちな深層学習モデルの理解に役立つアプローチとして、今後も様々な応用が期待できます。

参考リンク

自己紹介

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

プライバシーポリシー

QooQ