トップページデータベース研究CNN による画像分類 (image classification)転移学習での特徴抽出器(ImageNet で学習済みの ResNet-50 による転移学習)(Windows あるいは Ubuntu 上)

転移学習での特徴抽出器(ImageNet で学習済みの ResNet-50 による転移学習)(Windows あるいは Ubuntu 上)

転移学習 (transfer learning): CNN の学習では,ImageNet などのデータを用いた前学習 (pretrain) ののち,別のデータを用いた学習に移るということがよく行われる.別のデータでの学習は,次のいずれかで行う.

  1. CNN を画像からの特徴抽出器として使う: CNN の最終層である全結合層を取り除く.残りは,画像からの特徴抽出器(最終層のユニットの数だけの数値を出力する.ImageNet で学習したときは 1000 個の数値である)と見ることができる.そして,CNN の最終層の代わりに,線形分類器 (linear classifier) を付け加える.線形分類器には,線形 SVM や,softmax 分類器がある.その後,データを用いて,学習を行う.画像からの特徴抽出器と言っている部分(最終層である全結合層を取り除いた残り)の結合の重みは変化させない
  2. CNN での Fine Tuning も行う: CNN を画像からの特徴抽出器として使うことに加えて, 画像からの特徴抽出器と言っている部分(最終層である全結合層を取り除いた残り)の結合の重みを,バックプロパゲーションにより,変化させる(このことを Fine Tuning という).Fine Tuning においては,すべての層の結合の重みを変化させることもあるし,後段の層の結合の重みのみを変化させる場合もある(過学習の防止のため). Fine Tuning でのエポック数(学習率)は,過学習の防止のため,小さな値にすることを意識する.

上の 1, 2 のどちらで行うかの目安

前学習でのデータと類似している別データで転移学習を行うとき:過学習が起きないだけの十分な量の別データがあるときは,Fine Tuning も行い,Fine Tuning においては,すべての層の結合の重みを変化させる.十分な量の別データがないときは,CNN を画像からの特徴抽出器として使うだけにとどめて,Fine Tuning を行わないことを検討する.

前学習でのデータと類似していない別データで転移学習を行うとき: 過学習が起きないだけの十分な量の別データがあるときは,Fine Tuning も行い,Fine Tuning においては,すべての層の結合の重みを変化させるのか,あるいは,転移学習を行わないのかを検討する(転移学習を行う方がよい場合があると期待できる).十分な量の別データがないときは,CNN を画像からの特徴抽出器として使うだけにとどめる(Fine Tuning を行わない),あるいは,線形分離器として線形 SVM を用いた上で,層を最終層から少しさかのぼってのFine Tuning を行うのがよい可能性がある.

Keras の機能として, ImageNet で学習済みのモデルResNet-50,Inception-ResNet, DenseNet, MobileNetV2 など)がある. (Keras で利用可能なモデルは,https://keras.io/api/applications/ で説明されている.)

モデルからの最終層の除去,線形分類器 (linear classifier) の追加と別データでの学習,学習曲線の確認,Fine Tuning の実行を行う.

目次:

  1. Google Colab へのリンク
  2. 前準備
  3. 特徴抽出を行う画像データの準備
  4. ImageNet で学習済みの ResNet-50 をベースモデルとして,特徴抽出器を作成

参考 Web ページ:

前準備

Google Colab を使うか,パソコンを使う.それぞれの場合の前準備を説明する.

(1) Google Colab を使う場合

  1. Google Colab のWebページを開く

    https://colab.research.google.com

    Google Colab はオンラインの Python 開発環境. 使用するには Google アカウントが必要

  2. ファイル」で、「ノートブックを新規作成」を選ぶ

    [image]
  3. Google アカウントでのログインが求められたときはログインする

    [image]

    [image]

(2) パソコンを使う場合

(NVIDIA GPU を使うとき)TensorFlow のバージョンを確認の上,NIDIA CUDA ツールキットとNIDIA cuDNN のバージョンを確認

TensorFlow を使う場合は,必要となる NVIDIA CUDA ツールキット,NVIDIA cuDNN のバージョン確認

TensorFlow は,そのバージョンによって,必要となるNVIDIA CUDA ツールキット,NVIDIA cuDNN のバージョンが違う(最新の NVIDIA CUDA ツールキット,NVIDIA cuDNN で動くというわけでない). そのことは,https://www.tensorflow.org/install/gpu で確認できる.

そこで, まずは,使用したい TensorFlow のバージョンを確認し,それにより, NVIDIA CUDA ツールキット,NVIDIA cuDNN を確認する.

NVIDIA CUDA ツールキットのバージョン:

指定されているバージョンより高いものは使わない. その根拠は次のページ. URL: https://www.tensorflow.org/install/source#common_installation_problems

NVIDIA cuDNN のバージョン:

その根拠は次のページ. URL: https://www.tensorflow.org/install/source#common_installation_problems

(NVIDIA GPU を使うとき)NVIDIA グラフィックスドライバ,NVIDIA CUDA ツールキット 11.0 ,NVIDIA cuDNN 8.0.5 のインストール

GPU とは,グラフィックス・プロセッシング・ユニットの略で、コンピュータグラフィックス関連の機能,乗算や加算の並列処理の機能などがある.

NVIDIA CUDA は,NVIDIA社が提供している GPU 用のプラットフォームである.

インストール手順の説明

関連 Web ページ

Python のインストール,pip と setuptools の更新,Python 開発環境(JupyterLab, spyder, nteract)のインストール,TensorFlow などのインストール

インストール手順の説明

Python プログラムを動かすために, pythonpython3などのコマンドを使う. あるいは, 開発環境や Python コンソール(Jupyter Qt ConsolespyderPyCharmPyScripter など)の利用も便利である.

GraphViz のインストール

特徴抽出を行う画像データの準備

TensorFlow チュートリアルのページ: https://www.tensorflow.org/tutorials/images/transfer_learning?hl=jaに掲載の犬,猫のデータを使用.

train_dataset, validation_dataset, test_dataset を準備する.

import os
from tensorflow.keras.preprocessing import image_dataset_from_directory

# 追加データである画像の画像サイズを IMG_SIZE に設定すること
IMG_SIZE = (160, 160)
IMG_SHAPE = IMG_SIZE + (3,)
# TensorFlow の API で処理するときのバッチサイズの設定
BATCH_SIZE = 32
# URL によりダウンロード
_URL = 'https://storage.googleapis.com/mledu-datasets/cats_and_dogs_filtered.zip'
path_to_zip = tf.keras.utils.get_file('cats_and_dogs.zip', origin=_URL, extract=True)
PATH = os.path.join(os.path.dirname(path_to_zip), 'cats_and_dogs_filtered')

train_dir = os.path.join(PATH, 'train')
validation_dir = os.path.join(PATH, 'validation')
train_dataset = image_dataset_from_directory(train_dir, shuffle=True, batch_size=BATCH_SIZE, image_size=IMG_SIZE)
validation_dataset = image_dataset_from_directory(validation_dir, shuffle=True, batch_size=BATCH_SIZE, image_size=IMG_SIZE)
val_batches = tf.data.experimental.cardinality(validation_dataset)
# validation_dataset を test_dataset とvalidation_dataset に振り分け
test_dataset = validation_dataset.take(val_batches // 5)
validation_dataset = validation_dataset.skip(val_batches // 5)
# プリフェッチの設定(読み込み高速化のため)
AUTOTUNE = tf.data.AUTOTUNE
train_dataset = train_dataset.prefetch(buffer_size=AUTOTUNE)
validation_dataset = validation_dataset.prefetch(buffer_size=AUTOTUNE)
test_dataset = test_dataset.prefetch(buffer_size=AUTOTUNE)

[image]

ImageNet で学習済みの ResNet-50 をベースモデルとして,特徴抽出器を作成

参考 Web ページ: https://keras.io/ja/applications/

謝辞:ここでは、https://keras.io/ja/applications に記載のプログラムを変更して使用している

  1. ベースモデルの作成

    次の Python プログラムを実行

    Python プログラムを動かすために, pythonpython3などのコマンドを使う. あるいは, 開発環境や Python コンソール(Jupyter Qt ConsolespyderPyCharmPyScripter など)も便利である.

    from __future__ import absolute_import, division, print_function, unicode_literals
    import tensorflow.compat.v2 as tf
    import tensorflow_datasets as tfds
    from tensorflow.keras.preprocessing import image
    import numpy as np
    import matplotlib.pyplot as plt
    %matplotlib inline
    import warnings
    warnings.filterwarnings('ignore')   # Suppress Matplotlib warnings
    tf.enable_v2_behavior()
    from tensorflow.keras import backend as K 
    K.clear_session()
    
    from tensorflow.keras.applications.resnet50 import ResNet50
    from tensorflow.keras.applications.resnet50 import preprocess_input, decode_predictions
    from tensorflow.keras.models import Model
    from tensorflow.keras.layers import Dense, Dropout, GlobalAveragePooling2D
    
    # include_top=False により分類層を含まないようにする
    base_model = ResNet50(weights='imagenet', input_shape=IMG_SHAPE, include_top=False)
    # 学習中に結合の重みが更新されないようにする
    base_model.trainable = False
    base_model.summary()
    

    [image]
  2. ベースモデルと画像データの事前確認のため,ベースモデルを用いて画像データを処理してみる

    エラーメッセージが出ないことを確認.ここの結果をあとで使うことはない.

    image_batch, label_batch = iter(train_dataset).get_next()
    feature_batch = base_model(image_batch)
    print(feature_batch.shape)
    

    [image]
  3. ベースモデルを用いて,特徴抽出器のモデルの作成
    inputs = tf.keras.Input(IMG_SHAPE)
    x = base_model(inputs, training=False)
    x = GlobalAveragePooling2D()(x)
    m = Model(inputs=inputs, outputs=x)
    m.summary()
    

    [image]
  4. 別データを,特徴抽出器により処理し結果を得る

    特徴抽出器による処理結果は,feature_batch_all に格納する. それは,長さ 2048 の数値ベクトル,2000個になる.

    feature_batch_all = None
    label_batch_all = None
    it = iter(train_dataset)
    while True:
        try:
            image_batch, label_batch = it.get_next()
        except tf.errors.OutOfRangeError:
            break
        if feature_batch_all is None:
            feature_batch_all = m(image_batch).numpy()
            label_batch_all = label_batch.numpy()
        else:
            feature_batch_all = np.vstack((feature_batch_all, m(image_batch).numpy()))
            label_batch_all = np.append(label_batch_all, label_batch.numpy())
    
    print(feature_batch_all.shape)
    print(label_batch_all.shape)
    

    [image]
  5. データのプロット

    主成分分析(PCA)による

    import pandas as pd
    features = [str(i) for i in range(feature_batch_all.shape[1])]
    df = pd.DataFrame(feature_batch_all, columns=features)
    df['label'] = label_batch_all
    df.shape
    # 主成分分析
    import sklearn
    pca = sklearn.decomposition.PCA(n_components=2)
    pca_result = pca.fit_transform(df[features].to_numpy())
    df['pca1'] = pca_result[:,0]
    df['pca2'] = pca_result[:,1] 
    # プロット
    import matplotlib.pyplot as plt
    %matplotlib inline
    import warnings
    warnings.filterwarnings('ignore')   # Suppress Matplotlib warnings
    import seaborn as sns
    plt.figure(figsize=(10,10))
    # 2クラスなので,パレット数は2
    sns.scatterplot(
        x="pca1", y="pca2",
        hue="label",
        palette=sns.color_palette("hls", 2),
        data=df,
        legend="full",
        alpha=0.4
    )
    

    [image]
  6. データのプロット

    6次元に次元削減ののち,SOM を作り,SOM をプロット.前準備として「pip install minisom」を実行しておくこと.

    import pandas as pd
    features = [str(i) for i in range(feature_batch_all.shape[1])]
    df = pd.DataFrame(feature_batch_all, columns=features)
    df['label'] = label_batch_all
    df.shape
    # まず,主成分分析により,次元削減する.結果は X へ.
    import sklearn
    DIM = 6
    pca = sklearn.decomposition.PCA(n_components=DIM)
    pca_result = pca.fit_transform(df[features].values)
    df['pca1'] = pca_result[:,0]
    df['pca2'] = pca_result[:,1] 
    df['pca3'] = pca_result[:,2] 
    df['pca4'] = pca_result[:,3] 
    df['pca5'] = pca_result[:,4] 
    df['pca6'] = pca_result[:,5] 
    X = df[['pca1', 'pca2', 'pca3', 'pca4', 'pca5', 'pca6']].to_numpy()
     
    # see https://github.com/JustGlowing/minisom/blob/master/examples/BasicUsage.ipynb
    # マーカーと色は2種類を設定(2クラスなので),label_batch_all に入っっている 0, 1 の値に応じて選択.
    markers = ['o', 's']
    colors = ['C0', 'C1']
    
    from minisom import MiniSom    
    som = MiniSom(20, 20, DIM, sigma=0.3, learning_rate=0.5) # initialization of 20x20 SOM
    som.train(X, 100000) # trains the SOM with 50000 iterations
    
    plt.figure(figsize=(10, 10))
    plt.pcolor(som.distance_map().T, cmap='bone_r')
    plt.colorbar()
    for cnt, xx in enumerate(X):
        w = som.winner(xx)
        print(w, cnt, xx)
        plt.plot(w[0]+.5, w[1]+.5, markers[label_batch_all[cnt]], markersize=12, markeredgewidth=2, markerfacecolor='None', markeredgecolor=colors[label_batch_all[cnt]])
    
    plt.show()
    

    [image]