あっぱれ日和、 - What a "Appare" day -

あっぱれ日和、 - What a "Appare" day -

通りすがりのしがない映画好きが綴る、モノづくりの記録や備忘録。そして、影響を受けた映画の記録。

機械学習初心者がDeep Learningを試してみる ~CNN(Convolutional Neural Network, またの名を畳み込みニューラルネットワーク) 前編、学習させる前に下準備~

はじめに、

こんにちは。今回はDeep Leaningの中でもとても有名なCNN(Convolutional Neural Network)を実装しながらどんなものかを見てみようと思います。

そして、今回も機械学習初心者の人間がDeep Learningの実装にチャレンジする記録を残していこうと思いのもと書いている記事になります。間違えやミスがあればご指摘いただければ幸いです。


【目次】

前回の記事ではmnistを用いて画像認識を行いました。(前回の記事は以下になります。)
apao-m-appare99.hatenablog.com

これはDeep Neural Networkというものです。
モデルとしては以下のように
f:id:appare99:20200516160153p:plain

Input -> Affine+ReLU -> Affine+ReLU -> ・・・ -> Affine+ReLU -> Affine+softmax -> Output
のようなモデル構成となります。

さて、それではこの学習方法と比較してCNNについてみていきましょう。

CNNとは

CNNはニューラルネットワークに「畳み込み」という処理を取り入れたものであり、画像をそのまま2次元で入力として用いることができることが特徴です。

「畳み込み」の処理については以下の記事がとても分かりやすく説明しています。(というよりCNN自体についてもわかりやすく説明しています。)
www.atmarkit.co.jp
一応、畳み込みについて簡単に説明すると、カーネルというフィルタを用いることで画像から特徴を抽出する処理の事になります。つまり、画像の特徴を抽出し、ニューラルネットワークで重みを学習していったように、この特徴の値を学習していくことになります。

CNNは様々なモデルが考案されています。
そして、今回参考にするのが、1998年にヤン・ルカン氏によって考案されたLeNetと呼ばれる有名なCNNモデルになります。
以下がその概要図です。(https://nocotan.github.io/chainer/2017/08/04/chainercnn-copy.html より引用)
f:id:appare99:20200516164405p:plain


このモデルでは畳み込み層とプーリング層の2種類を交互に複数組み合わせるようなモデル構成となっています。

畳み込み層では上記で説明した畳み込み処理を行いその結果を出力します。
次のプーリング層ですが、
プーリングはダウンサンプリングが行われています。イメージとしてはピクセルの画像を減らして小さい画像を生成することです。そしてこの画像を生成する際に画像のピクセルの値をどのようにするかを決めていきます。決める方法として例えばmaxプーリングやavgプーリングがあります。

プーリングについては以下のサイトが分かりやすく説明しています。
products.sint.co.jp

以上からmnistを使用したときのDNNは
Input -> Affine+ReLU -> Affine+ReLU -> ・・・ -> Affine+ReLU -> Affine+softmax -> Output
と上記で記載しましたが、
CNNは次のようなモデル構成となります。ここでConvは畳み込み層(Convolution)、Poolはプーリング層(Pooling)を表します。
Input -> Conv+ReLU+Pool -> Conv+ReLU+Pool -> ・・・ -> Conv+ReLU+Pool -> Affine+softmax -> Outpu

今回はこのようなモデル構成のCNNでモデルを作成することになります。
●補足:以下の記事もCNNについてとても分かりやすく書かれています。
qiita.com

今回使用するデータ

今回使用する画像データはThe Oxford-IIIT Pet Datasetになります。以下のリンクから画像データは入手できます。
www.robots.ox.ac.uk


今回この画像データを使用しようと思った理由は、前回と同じmnistを用いて学習させてもよかったのですが、mnistは割かし整えられている画像ではあるので、今回は少し複雑な画像を使用してみたいと思ったからです。
また有名な画像データとしてCIFAR-10でもよかったのですが、CNNのサンプルコードが結構ネット上にあるので敢えてネット上にあまりない、The Oxford-IIIT Pet Datasetを使用することで勉強になるかと思ったからでもあります。

こちらのデータセットは37種の品種で分けられたカテゴリーと各カテゴリーに対して約200枚の画像で構成されています。
以下The Oxford-IIIT Pet Datasetのページに載っているデータの詳細になります。(https://www.robots.ox.ac.uk/~vgg/data/pets/ より参照)
f:id:appare99:20200516190415p:plain

データの前処理

お次は学習させるための画像の前処理を行っていきます。
まずはThe Oxford-IIIT Pet Datasetでとってきた画像を見ていきましょう。ダウンロードしてきたgz.tarを解凍してみましょう。
画像たちを見てみましょう。かわいい猫ちゃんやワンちゃんの画像が入っています。これが今回使う画像です。
あ、あれ?なんか枚数足りなくない?No.38, 39が無かったり、No41, No42が無かったり。。。
ま、まあ画像自体は悪くないし一つの品種に対し200枚ほどあるので学習させればうまくいくと願ってます。
f:id:appare99:20200516185739p:plain

さて、これらの画像をそれぞれのファイルに振り分けていきましょう。ラベル付けではなくフォルダに分けて区別していきます。(ザ・ごり押し(笑))
以下のような感じになりました。
f:id:appare99:20200516190552p:plain

学習前の前処理

さてそれでは早速画像を読み込んで本記事の本題でもある学習前の処理を実装しましょう。
参考にしたサイトは以下の2つになります。
qiita.com
newtechnologylifestyle.net

で、データの前処理までの全体像のコードが以下のようになりました。コメントアウトで各処理に関して書いてあるので参考にしてみてください。

from keras.utils import np_utils
from sklearn.model_selection import train_test_split
from PIL import Image
import numpy as np
import glob
import os

DATAPATH = "./data/src/" 

folder = os.listdir(DATAPATH) # ファイル、ディレクトリの一覧を取得

image_size = 50
dense_size  = len(folder)

X = []
Y = []

'''
Xには50×50のサイズでRBG形式のため[Red,Green,Blue]で格納されてます。
Yにはフォルダのナンバリング、
jpg形式のファイルを取り出し、RGB形式、50×50のサイズに変更し、
そのデータをX、Yの配列に格納しています。
'''

for index, name in enumerate(folder):    
    files = glob.glob(DATAPATH + name + "/*.jpg") #ディレクトリごとに画像をまとめて格納
    for i, file in enumerate(files): # 1つのディレクトリの画像に対し、一つ一つ画像を見ていく
        image = Image.open(file)
        image = image.convert("RGB")
        image = image.resize((image_size, image_size))
        data = np.asarray(image)
        X.append(data)
        Y.append(index)

X = np.array(X)
Y = np.array(Y)

X = X.astype('float32') # 学習用のモデルに渡すためにfloat32に変換する必要がある
X = X / 255.0 # 正規化処理:値を0~1の間に分布するようにさせる

Y = np_utils.to_categorical(Y, dense_size) # np_utils.to_categoricalを使用する事により、ラベルをベクトルに変換出来る
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.10)
# 訓練用の画像とラベル、テスト用の画像とラベルに分ける。今回の場合は画像データの10%をテスト用に使う

まとめ

はい、ということで今日はここまでにします。ざっくりとCNNを説明して学習用データの前処理まで終えることができました。
次回は実際に学習をさせてみて評価まで行いたいと思います。