トップページデータベース研究CNN による画像分類 (image classification)画像の増強,CNN による画像分類,モデルの作成と学習と評価(tf.image を用いて増強,MobileNetV2,TensorFlow データセットのCIFAR 10 データセットを使用)(Google Colab 上もしくはパソコン上)

画像の増強,CNN による画像分類,モデルの作成と学習と評価(tf.image を用いて増強,MobileNetV2,TensorFlow データセットのCIFAR 10 データセットを使用)(Google Colab 上もしくはパソコン上)

CIFAR 10 データセット下図)の画像分類を行う. 所定の 10種類に画像分類を行うものである. その 10種類は,airplane, automobile, bird, cat, deer, dog, frog, horse, ship, truck である.

[image]

学習データとして用いる画像データの増強を行う.増量では,TensorFlow の機能を使い,画像を縦横にずらす,コントラストを変化させることを行う. 前提として,このページの手順では,増量後の画像データがメモリに入り切る分量であるとしている. TensorFlow データセットCIFAR 10 データセットを使用する. CNN としては,次のものを使用する.

この資料の URL: https://www.kkaneko.jp/dblab/imclassify/augment.html

サイト内の関連ページ

参考Webページ:

1. Google Colab へのリンク

このページの内容は,Google Colab でも実行できる.

そのために,次の URL で,Google Colab のノートブックを準備している.

次のリンクをクリックすると,Google Colab のノートブックが開く. そして,Google アカウントでログインすると,Google Colab のノートブック内のコードを実行することができる.Google Colab のノートブックは書き換えて使うこともできる.このとき,書き換え後のものを,各自の Google ドライブ内に保存することもできる.

https://colab.research.google.com/drive/1osVlD5wpv-pFMrIt2WgXWbTB8t5fKu9f?usp=sharing

2. 前準備

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 など)の利用も便利である.

3. CIFAR 10 データセットの準備

  1. パッケージのインポートと TensorFlow のバージョン確認
    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()
    
    print(tf.__version__)
    

    [image]
  2. CIFAR 10 データセットのロード
    tensorflow_datasets の loadで, 「batch_size = -1」を指定して,一括読み込みを行っている.
    cifar10, cifar10_info = tfds.load('cifar10', with_info = True, shuffle_files=True, as_supervised=True, batch_size = -1)
    

    [image]
  3. データセットの中の画像を表示

    MatplotLib を用いて,0 番目の画像を表示する

    import matplotlib.pyplot as plt
    %matplotlib inline
    import warnings
    warnings.filterwarnings('ignore')   # Suppress Matplotlib warnings
    NUM = 0
    # NUM 番目の画像を表示
    plt.imshow(cifar10['train'][0][NUM])
    

    [image]

    MatplotLib を用いて,複数の画像を並べて表示する.

    def plot25(ds, start):
        plt.figure(figsize=(10,10))
        for i in range(25):
            plt.subplot(5,5,i+1)
            plt.xticks([])
            plt.yticks([])
            plt.grid(False)
            image, label = ds[0][i + start], ds[1][i + start]
            plt.imshow(image)
            plt.xlabel(label.numpy())
        plt.show()
    
    plot25(cifar10['train'], 0)
    

    [image]
  4. データセットの情報を表示
    print(cifar10_info)
    print(cifar10_info.features["label"].num_classes)
    print(cifar10_info.features["label"].names)
    

    [image]
  5. cifar10['train'] と cifar10['test'] の形と次元を確認

    cifar10['train']: サイズ 32 かける 32 の 50000枚のカラー画像,50000枚のカラー画像それぞれのラベル(0 から 9 のどれか)

    cifar10['test']: サイズ 32 かける 32 の 10000枚のカラー画像,10000枚のカラー画像それぞれのラベル(0 から 9 のどれか)

    print(cifar10['train'][0].shape)
    print(cifar10['train'][1].shape)
    print(cifar10['test'][0].shape)
    print(cifar10['test'][1].shape)
    

    [image]
  6. データセットの生成
    ds_train, ds_test = cifar10['train'], cifar10['test']
    

    [image]
  7. ニューラルネットワークを使うために,データの前処理

    値は,もともと int で 0 から 255 の範囲であるのを, float32 で 0 から 1 の範囲になるように前処理を行う.

    ds_train = (ds_train[0].numpy().astype("float32") / 255., ds_train[1])
    ds_test = (ds_test[0].numpy().astype("float32") / 255., ds_test[1])
    

    [image]

4. 画像データセットの増強

  1. 画像データの増強を行ってみる

    画像データの増強を行う. 画像データは,ds_train[0] にある. TensorFlow の機能を使い,画像を縦横にずらす,コントラストを変化させることを行う. ds_train[1] にはラベルのデータが入っているとする.

    結果の入る augmented_ds_train はタップル.うち1つ目は,numpy の配列.2つ目は,要素が tf.Tensor の配列.

    INPUT_SHAPE = [32, 32, 3]
    CROP_SIZE = 3
    
    # 画像を縦横にずらす.コントラストを変化させる.
    def augment(image, seed):
        image = tf.image.resize_with_crop_or_pad(image, INPUT_SHAPE[0] + (2 * CROP_SIZE), INPUT_SHAPE[1] + (2 * CROP_SIZE))
        # Random crop back to the original size
        image = tf.image.stateless_random_crop(image, size=INPUT_SHAPE, seed=seed)
        # Make a new seed
        new_seed = tf.random.experimental.stateless_split(seed, num=1)[0, :]
        image = tf.image.stateless_random_contrast(
            image, lower=0.8, upper=0.99, seed=new_seed)
        image = tf.clip_by_value(image, 0, 1)
        return image
    
    def augment_images(images, seed):
        new_images = np.zeros(images.shape)
        for i, image in enumerate(images):
            new_images[i] = augment(image, (i + seed * 100, 0))
        return new_images
    
    augmented_ds_train = (augment_images(ds_train[0], 123), ds_train[1])
    plot25(augmented_ds_train, 0)
    

    [image]
  2. 増量できたことの確認
    print(augmented_ds_train[0].shape)
    
  3. 今度は,画像データの増強を行いながら,画像データを 5倍に増やす.

    ここで増やした画像データは,あとで使用する

    def increase_image_data(ds_train, t):
    # t 倍に増やす
        x1 = augment_images(ds_train[0], 1)
        y1 = ds_train[1]
        if t > 1:
            for i in range(t - 1):
                x2 = augment_images(ds_train[0], i + 1)
                # 画像は nparray, ラベルは tf.Tensorを要素とする配列にする
                x1 = np.concatenate([x1, x2])
                y1 = tf.concat([y1, ds_train[1]], axis = 0)
    
        result = (x1, y1)
        return result
    
    augmented_ds_train = increase_image_data(ds_train, 5)
    plot25(augmented_ds_train, 0)
    

    [image]

5. MobileNetV2 による cifar10 の画像分類

  1. 使用するデータの確認
    print(augmented_ds_train[0].shape)
    print(augmented_ds_train[1].shape)
    print(ds_test[0].shape)
    print(ds_test[1].shape)
    

    [image]
  2. モデルの作成と確認とコンパイル
    Keras の MobileNet を使う. 「weights=None」を指定することにより,最初,重みはランダムに設定する.

    最適化器(オプティマイザ) と損失関数メトリクスを設定する.

    NUM_CLASSES = 10
    INPUT_SHAPE = [32, 32, 3]
    m1 = tf.keras.applications.mobilenet.MobileNet(input_shape=INPUT_SHAPE, weights=None, classes=NUM_CLASSES)
    m1.summary()
    m1.compile(
        optimizer=tf.keras.optimizers.Adam(learning_rate=0.001),
        loss='sparse_categorical_crossentropy',
        metrics=['sparse_categorical_crossentropy', 'accuracy']
    )
    

    [image]
  3. モデルのビジュアライズ

    Keras のモデルのビジュアライズについては: https://keras.io/ja/visualization/

    ここでの表示で,エラーメッセージが出る場合でも,モデル自体は問題なくできていると考えられる.続行する

    from tensorflow.keras.utils import plot_model
    import pydot
    plot_model(m1)
    
  4. 学習(訓練)

    学習(訓練)は fit メソッドにより行う. 学習データを投入する.

    EPOCHS = 20
    history = m1.fit(augmented_ds_train[0], augmented_ds_train[1],
                        epochs=EPOCHS,
                        validation_data=(ds_test[0], ds_test[1]), 
                        verbose=1)
    

    [image]
  5. CNN による画像分類

    ds_test を分類してみる.

    print(m1.predict(ds_test[0]))
    

    [image]

    それぞれの数値の中で、一番大きいものはどれか?

    m1.predict(ds_test[0]).argmax(axis=1)
    

    [image]

    ds_test 内にある正解のラベル(クラス名)を表示する(上の結果と比べるため)

    print(ds_test[1])
    

    [image]
  6. 学習曲線の確認

    過学習や学習不足について確認.

    import pandas as pd
    hist = pd.DataFrame(history.history)
    hist['epoch'] = history.epoch
    print(hist)
    

    [image]
  7. 学習曲線のプロット

    過学習や学習不足について確認.

    https://www.tensorflow.org/tutorials/keras/overfit_and_underfit?hl=ja で公開されているプログラムを使用

    import matplotlib.pyplot as plt
    %matplotlib inline
    import warnings
    warnings.filterwarnings('ignore')   # Suppress Matplotlib warnings
    def plot_history(histories, key='binary_crossentropy'):
      plt.figure(figsize=(16,10))
    
      for name, history in histories:
        val = plt.plot(history.epoch, history.history['val_'+key],
                       '--', label=name.title()+' Val')
        plt.plot(history.epoch, history.history[key], color=val[0].get_color(),
                 label=name.title()+' Train')
    
      plt.xlabel('Epochs')
      plt.ylabel(key.replace('_',' ').title())
      plt.legend()
    
      plt.xlim([0,max(history.epoch)])
    
    
    plot_history([('history', history)], key='sparse_categorical_crossentropy')
    

    [image]
    plot_history([('history', history)], key='accuracy')
    

    [image]

データの増強を行わない場合の結果(学習曲線など)は, 別ページで説明している.