犬、猫、ペンギンを判別する深層学習(ディープラーニング)を作ってみた!

犬・猫・ペンギンを判別する深層学習 プログラミング
困ったさん
困ったさん
深層学習って何ができるの??

こんな疑問を解決します。

この記事を書いてる人

FUMIPEN blogを運営
本記事の内容

  • 深層学習とはそもそも何なのか?
  • 深層学習を使ったサンプル画像解析を公開

本記事では「深層学習とは?から深層学習を用いた画像解析」について解説して紹介

この記事を読むことで、深層学習の概念がわかり、それを踏まえて画像解析を誰でも行うことができるようになります。

結論から話すと、

結論

  • この記事を読めば、画像判別をできるプログラムを作ることが可能
  • 深層学習(ディープラーニング)とはコンピュータを教育して学習能力を与えること
  • 学習能力を与えて実世界では、画像解析や音声認識を行うことが可能
  • 建設の世界なら様々な場所で役に立つ

深層学習(ディープラーニング)とは

深層学習

大まかな構造はこのようになっております。

ディープラーニングを話す上で避けては通れないのが、人工知能と機械学習との立ち位置です。

まずディープラーニング

データを反復学習して、学習結果を法則化する。さらにその反復学習から、特徴をコンピュータが掴みモデル化

続いて機械学習

特徴を私たちが探し出して、法則化します。そして法則化させたのちにそれ以降の再現性を作るのがディープラーニングから拡張させたもの

最後に人工知能です。

人工知能とは

知的とみなせる行動を機械で実現することを目標とする。「知的とみなせる行動」をMinskyは「多数の人が確かに知能的であると認める行動」とする。

引用元:人工知能 , 南雲仁一・甘利俊一・中野馨

深層学習(ディープラーニング)で可能になること

東京大学の松尾様「人工知能は人間を超えるか」から引用させていただきますと、

ディープラーニングで可能になること

  • 画像から特徴量を抽出する(画像認識の精度向上)
  • 映像、センサーなどの複数の入力情報から特徴量を抽出し、モデル化(行動予測、異常検知、動画の認識精度の向上)
  • 自分の行動と観測のデータをセットにして、特徴量を抽出する。記号を操作し、行動計画を作る(プランニング、フレーム問題の解決)
  • 外界と試行錯誤することで、外界の特徴量を引き出す(オントロジー、高度な状況認識)
  • 高次特徴量を、言語と紐付ける(言語理解、自動翻訳)
  • バインディングされた言語データの大量の入力による、さらなる抽象化を行う(知識獲得のボトルネックの解決)

とあります。

ふみペン
ふみペン
今の世界よりももっと安心安全に生きることができる社会ができる可能性があるってこと!

それでは犬猫、ペンギン判別プログラムを作成したいと思います。

あ!ただし、プログラムを動かしたいとなれば、anaconda等でpythonの環境構築を行っていただく必要がありますのでご了承ください。

実装方法はAnacondaのインストールをご覧いただけたらと思います。

他にもtensorflowの実装方法はAnacondaでTensorFlowをインストールする手順メモで解説してくださっています。

ディープラーニングによる画像認識プログラム

import numpy as np
import tensorflow as tf
import glob
#画像の準備######################
x_train = []
y_train = []
x_test = []
y_test = []

#globを用いることでここに当てはまる全ての情報をループさせることができる
for f in glob.glob("image/*/*/*.jpeg"):
    img_data = tf.io.read_file(f)
    print(f)
    img_data = tf.io.decode_jpeg(img_data)
    #バラバラの画像の縦横比を揃える
    img_data = tf.image.resize(img_data,[100,100])
    
    #fの一番目つまりimageの一つ下のフォルダがtrainの場合はtrainデータに持ってくる
    if f.split("/")[1] == "train":
        x_train.append(img_data)
        y_train.append(int(f.split("/")[2].split("_")[0]))
    elif f.split("/")[1] == "test":
        x_test.append(img_data)
        y_test.append(int(f.split("/")[2].split("_")[0]))
        
#numpy形式に変換
x_train = np.array(x_train)/255.0
y_train = np.array(y_train)
x_test = np.array(x_test)/255.0
y_test = np.array(y_test)

#ニューラルネットワークの構築##########
model = tf.keras.models.Sequential([
    #入力層(正方形にするが、横長の画像は潰れてしまう)
    tf.keras.layers.Flatten(input_shape=(100,100,3)),
    #隠れ層,reluは活性化関数
    tf.keras.layers.Dense(64,activation="relu"),
    #隠れ層,dropoutはディープラーニングの精度を上げるためのもので試行錯誤する場所
    tf.keras.layers.Dropout(0.2),
    #出力層,犬、猫、ペンギンの3種類,分類するときはsoftmaxにしておけばまず動く
    tf.keras.layers.Dense(3,activation="softmax")
])

#モデルの学習########################
#どれくらい間違えたのか計算する方法(学習に関する設定)
model.compile(optimizer="adam",loss="sparse_categorical_crossentropy",metrics=["accuracy"])

#epochは学習を何回回すのか?やりすぎたら過学習になる。最低でも100くらいなる
model.fit(x_train,y_train,epochs=30)

#モデルの評価########################
model.evaluate(x_test,y_test)

それ早速全コードを添付しておきます。ディープラーニングを構築する上で必要となる手順は三つです。

ディープラーニングを行う上で必要となる手順

  • 学習に用いる画像の準備
  • ニューラルネットワークの構築
  • モデルの学習
  • モデルの評価

この四つです。一つづつ解説します。

学習に用いる画像とフォルダ構成の準備

今回学習させるのは。。。そうですね、画像を見せたときにパッと「これは犬!」「これは猫!」「これはペンギン!」と判断してもらいたい。

それでは用意する画像は何が良いでしょうか?

え??いろんな動物の画像??
困ったさん
困ったさん
ふみペン
ふみペン
確かに動物の画像なんだけど、ここでは3種類の画像の識別がわかればいいから、犬と猫とペンギンの画像だね!

一番上のフォルダ

python ディープラーニング

まずは

  • imageフォルダ
  • ディープラーニングと書かれたプログラムファイル

を用意してください。

imageフォルダの中

python ディープラーニング

続いて

  • test
  • train

を用意してください。これはtestはそのままテスト問題を格納するフォルダで、trainはtrainingフォルダとなっています。

trainフォルダとtestフォルダの中身

python ディープラーニング

testフォルダとtrainフォルダの両方に

  • 0_cat
  • 1_dog
  • 2_penguin

のファイルを作成してください。

画像を格納

python ディープラーニング

最後にテストフォルダにそれぞれ「犬」「猫」「ペンギン」の画像をダウンロードしてから格納してください。

trainフォルダには10枚ダウンロードお願いします。(正直ここが一番面倒)

ふみペン
ふみペン
画像の大きさとかは気にせずダウンロードしてくれて構わないよ!
import numpy as np
import tensorflow as tf
import glob
#画像の準備######################
x_train = []
y_train = []
x_test = []
y_test = []

#globを用いることでここに当てはまる全ての情報をループさせることができる
for f in glob.glob("image/*/*/*.jpeg"):
    img_data = tf.io.read_file(f)
    print(f)
    img_data = tf.io.decode_jpeg(img_data)
    #バラバラの画像の縦横比を揃える
    img_data = tf.image.resize(img_data,[100,100])
    
    #fの一番目つまりimageの一つ下のフォルダがtrainの場合はtrainデータに持ってくる
    if f.split("/")[1] == "train":
        x_train.append(img_data)
        y_train.append(int(f.split("/")[2].split("_")[0]))
    elif f.split("/")[1] == "test":
        x_test.append(img_data)
        y_test.append(int(f.split("/")[2].split("_")[0]))
        
#numpy形式に変換
x_train = np.array(x_train)/255.0
y_train = np.array(y_train)
x_test = np.array(x_test)/255.0
y_test = np.array(y_test)

ここまでで上記のコードが読めるようになっております。

画像の縦横比はimage.resize関数で100ピクセルの正方形に直して統一させています。

あれ??それだと元の画像の縮尺変わるよね??
困ったさん
困ったさん
ふみペン
ふみペン
その通りで、縦横比が変わることで学習精度が低下しますが、今回は動けばいいと思って進めていきます!

ニューラルネットワークの構築

#ニューラルネットワークの構築##########
model = tf.keras.models.Sequential([
    #入力層(正方形にするが、横長の画像は潰れてしまう)
    tf.keras.layers.Flatten(input_shape=(100,100,3)),
    #隠れ層,reluは活性化関数
    tf.keras.layers.Dense(64,activation="relu"),
    #隠れ層,dropoutはディープラーニングの精度を上げるためのもので試行錯誤する場所
    tf.keras.layers.Dropout(0.2),
    #出力層,犬、猫、ペンギンの3種類,分類するときはsoftmaxにしておけばまず動く
    tf.keras.layers.Dense(3,activation="softmax")
])

ニューラルネットワークは

  • 入力層(データが入力される層)
  • 隠れ層
  • 出力層

の3つに分けられます。

(引用:ニューラルネットワークとは|仕組み・学習手法・活用事例・ディープラーニングとの違い

何これ??ビリヤード??
困ったさん
困ったさん

よく言われる入力層、隠れ層、出力層のイメージ図ですが、確かにこれでは初心者にはわかりづらいかもですね。

深層学習 流れ

こんなイメージです!一つづつ解説します。

最初のkera.models.Sequentialは入力と出力がそれぞれ一つの場合に成り立つモデルです。

(引用:SequentialモデルAPI

さらにkeras.layersはモデルに加えたリストを表示しています。

(引用:SequentialモデルAPI

入力層

深層学習 流れ

tf.keras.layers.Flatten(input_shape=(100,100,3))

100✖︎100のRGBと三色で構成された100✖︎100✖︎3のデータを一次元データに平滑化します。

今は写真の画像はリスト形式で三次元配列でした。これを一次元に直すことができます。

ふみペン
ふみペン
RとGとBで分けてさらに縦と横を一次元で!
要点

入力層は「これを読んでください!」と写真をコンピュータにわかりやすく与える層

隠れ層パート①

深層学習 流れ

tf.keras.layers.Dense(64,activation=”relu”)

このactivation=”relu”というのは活性化関数を呼び出しています。

か、か、活性化関数??
困ったさん
困ったさん
ふみペン
ふみペン
学習した成果の精度をより高めるために使用する関数のことだね!

タウリンみたいなもの!!です!

深く掘り下げれば掘り下げるだけ解説が長くなりそうなので、これで勘弁してください!

隠れ層パート②

tf.keras.layers.Dropout(0.2)

過学習を抑えるための数値を指定しています。

か、か、過学習??
困ったさん
困ったさん
ふみペン
ふみペン
バッティングセンターで何回も打つ練習をしたから本番で打てるわけではないよね?
もしかしたら、バッティングセンターの弾に慣れすぎて全く対応できないなんてことも!練習したことない初心者の方がいろんな弾に対応できるかもしれないのとおんなじだね!
要点

タウリンを飲ませて、「コンピュータさん!ほどほどに学習お願いします!」と励ます層

出力層

深層学習 流れ

tf.keras.layers.Dense(3,activation=”softmax”)

まずは3と書かれてあるのは、今回は「犬」「猫」「ペンギン」の三つをコンピュータさんに「判別してください!!」とお願いしていたので、3になります。

続いてのactivation=”softmax”ですが、

複数の出力値の合計が1.0(100%)になるように変換して出力する関数

(引用:[活性化関数]ソフトマックス関数(Softmax function)とは?

ふみペン
ふみペン
出力結果を見やすくする関数だね!詳しくはRelu関数よりも勾配が緩やかで、計算時間を短縮できる関数だね!

計算時間の短縮は、0より小さい値も学習に含めるためです。

image.png

(引用:TensorFlowのチュートリアルがディープラーニングの勉強のスタートに良かったのでオススメしたい

青がRelu(ランプ関数)で緑がソフトプラス関数となっています。

モデルの学習

#モデルの学習########################
#どれくらい間違えたのか計算する方法(学習に関する設定)
model.compile(optimizer="adam",loss="sparse_categorical_crossentropy",metrics=["accuracy"])

#epochは学習を何回回すのか?やりすぎたら過学習になる。最低でも100くらいなる
model.fit(x_train,y_train,epochs=30)

#モデルの評価########################
model.evaluate(x_test,y_test)

model.compile(optimizer=”adam”,loss=”sparse_categorical_crossentropy”,metrics=[“accuracy”])

この文を分けて説明すると、

optimizer=”adam”

optimizerは最適化手法を決定するパラメータで、adamが一番オーソドックスなものです。

loss=”sparse_categorical_crossentropy”

lossは損失関数を決定するパラメータで、crossentropyは学習効率がその中でも良い手法なのです。

損失??何それ?嫌なもの??
困ったさん
困ったさん

今回は犬と猫とペンギンのデータをコンピュータさんに学習させるものでした。

例えばこの画像は犬です。とコンピュータに教えた後に、「猫」の画像をコンピュータに読み込ませます。

そうすると、コンピュータは「これは猫ではない!!!!」ってはっきり理解を示してくれる。これが効率の良い学習で、その方法としてのcrossentropyです。

まだ勉強不足のため詳しく解説できないですが、今後記事にまとめていこうと思います。

metrics=[“accuracy”]

はモデルのパフォーマンスを判断するための関数です。

モデルの評価

正解率は33.3%!!

ふみペン
ふみペン
ひ、ひ、低い。。。

確かに画像の縦横比や読むこませる画像が少なかったことも挙げられます。

皆さん大好き画像で精度を表すことも可能です。

 def compare_TV(history):
        import matplotlib.pyplot as plt

        # Setting Parameters
        acc = history.history['accuracy']
        val_acc = history.history['val_accuracy']
        loss = history.history['loss']
        val_loss = history.history['val_loss']

        epochs = range(len(acc))

        # 1) Accracy Plt
        plt.plot(epochs, acc, 'bo' ,label = 'training acc')
        plt.plot(epochs, val_acc, 'b' , label= 'validation acc')
        plt.title('Training and Validation acc')
        plt.legend()

        plt.figure()

        # 2) Loss Plt
        plt.plot(epochs, loss, 'bo' ,label = 'training loss')
        plt.plot(epochs, val_loss, 'b' , label= 'validation loss')
        plt.title('Training and Validation loss')
        plt.legend()

        plt.show()
history = model.fit(x_train, y_train,
                    epochs=5,
                    batch_size=20,
                    validation_data=(x_test, y_test)
                   )
#show Accuracy and Loss History
compare_TV(history)

このような感じでaccuracyとlossを算出することができます。

まとめ

こんな感じで簡単にディープラーニングを実装することができました。

ただし、問題はここから精度を上げるために何を使ってモデルを最適化していくかだと思います。

以外に簡単に実装することができるんだ!って理解していただけたと思います。

もっと身近にプログラミングの存在を感じていただき、皆さんの選択肢を広げるお役にも立てたらと思っています。

最後まで見ていただきありがとうございました!

ちなみに解説今からしていきますが、私が参考にしたyoutubeのデータサイエンス塾の方の動画も貼っておきますので、よろしければご覧ください!