This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

More than 5 years have passed since last update.

ディープラーニングで作る犬・猫・乗り物を分類する画像認識AI

Last updated at Posted at 2017-05-11

画像認識問題

簡単な画像認識モデルを作ってみましょう。
DeepLearingライブラリであるkerasを使い、単純な猫,犬,乗り物の3クラス画像分類を行います。

これから作るもの / DEMO

 ターミナル/コマンドプロンプトver

kerasとは

keras-logo-small.jpg

KerasはPythonで書かれたTensorFlowまたはTheano上で実行可能なディープラーニング用のライブラリです。

・Keras公式ドキュメント
https://keras.io/ja/
https://keras.io/

Keras特徴3つ

次のような特徴を持ちます。

1 Kerasの特徴として、TensorFlowに比べると、かなり短いコード量でプロトタイプ作成が可能。
2 CNNとRNNの両方が使える。
3 CPUとGPUで実行可能。

Kerasを使うことで、TensorFlowに比べて、面倒な処理を記述しないで実装が出来るため、
より簡単にモデルを作ることが可能です。

Kerasで作る画像認識AI

●目的と手順の確認
これかなり重要です.
取り組んでいる間に何をやっているかわからなくなる場合が多々あるため,必ず最初に整理しておきます。

・目的の確認

何を入力して何を出力したいのか確認しましょう.
今回の場合は画像を入力した時,その画像が猫,犬,車のどれであるか判定することです。

・手順の確認

今回の手順は大きく分けて3つになると考えられます

1,データセットの作成

2,学習し,学習したモデルを保存するためのtraining.pyの作成

3,保存したモデルを試すためのuse_model.pyの作成

1,データセットの作成

・データの読み込み
・説明変数(X)の作成
・目的変数(y)の作成

今回はcifar10から猫、犬、乗り物を読み込みます。

cifar10は、CIFAR-10画像データセットは32×32サイズのカラー画像のデータセットです。
20151014211729.png

まずは、

sample.py
from keras.datasets import cifar10
(X_train, y_train), (X_test, y_test) = cifar10.load_data()
    print(X_train.shape, y_train.shape)
    print(X_test.shape, y_test.shape)

Cifar10には、猫や犬以外にも、他の写真があり、この中から猫と犬と乗り物だけをとってきます。
そこで、次の関数で猫と犬と乗り物だけを取り出しています。

sample.py
def change3class(exp_val, obj_val):
    new_exp = []
    new_obj = []
    for (x, y) in zip(exp_val, obj_val):
        if y == 3:
            new_exp.append(x)
            new_obj.append(0)
        elif y == 5:
            new_exp.append(x)
            new_obj.append(1)
        elif y == 1:
            new_exp.append(x)
            new_obj.append(2)
        else:
            pass

    new_exp = np.array(new_exp)
    return new_exp, new_obj

change3classの中で、

new_exp = np.array(new_exp)
return new_exp, new_obj

の2行をfor文と同じ行に合わせないと、

ValueError: zero-size array to reduction operation maximum which has no identity

のエラーが出てしまうので注意です。

2,学習し,学習したモデルを保存するためのtraining.pyの作成

training.pyは以下で構成されます.

・kerasでモデルの定義
・kerasで学習とモデルの保存

・kerasでモデルの定義

モデルを定義します.

training.py
def build_model():
    model = Sequential()

    """
    16 → 使用する畳み込みカーネルの数
    3  → 畳み込みカーネルの行数と列数
    border_modeはパディングを変更することが可能。デフォルトは’valid’になっておりパディングはなし。
    input_shapeは整数のタプルを指定  例) 128x128 RGB画像の場合は、input_shape=(3, 128, 128)
    層に関してより詳しい詳細→ https://keras.io/ja/layers/convolutional/
    """
    model.add(Convolution2D(16, 3, 3, border_mode="same", input_shape=in_shape))
    model.add(Activation("relu"))
    model.add(Convolution2D(16, 3, 3, border_mode="same"))
    model.add(Activation("relu"))
    model.add(MaxPooling2D())
    model.add(Dropout(0.5))

    model.add(Convolution2D(32, 3, 3, border_mode="same"))
    model.add(Activation("relu"))
    model.add(Convolution2D(32, 3, 3, border_mode="same"))
    model.add(Activation("relu"))
    model.add(MaxPooling2D())
    model.add(Dropout(0.5))

    model.add(Convolution2D(64, 3, 3, border_mode="same"))
    model.add(Activation("relu"))
    model.add(Convolution2D(64, 3, 3, border_mode="same"))
    model.add(Activation("relu"))
    model.add(MaxPooling2D())
    model.add(Dropout(0.5))

    model.add(Convolution2D(64, 3, 3, border_mode="same"))
    model.add(Activation("relu"))
    model.add(Convolution2D(64, 3, 3, border_mode="same"))
    model.add(Activation("relu"))
    model.add(MaxPooling2D())
    model.add(Dropout(0.5))

    model.add(Convolution2D(128, 3, 3, border_mode="same"))
    model.add(Activation("relu"))
    model.add(Dropout(0.5))

    model.add(Flatten())
    model.add(Dense(100))
    model.add(Activation("relu"))

    model.add(Dropout(0.5))
    model.add(Dense(cls_num))
    model.add(Activation('softmax'))

    model.compile(loss="categorical_crossentropy", 
        metrics   = ["accuracy"], 
        optimizer = "adam"
    )
    return model

model.add(Dropout(0.5))
ここでは、ランダムに半分くらいノードを選択して、過学習を起きにくくしています。

・kerasで学習とモデルの保存

training.py
model.fit(X_train, y_train, nb_epoch=150, batch_size=16,validation_data=(X_test, y_test))

学習はこの1行で始まります.
トレーニングセットを指定し,エポックとバッチサイズを決めます.テストセットを指定する場合は,validation_data=(X_test, y_test)とします.

training.py
json_string = model.to_json()
open('model.json', 'w').write(json_string)
model.save_weights('weight.hdf5')

モデルと学習した重みを保存します。
この時model.jsonとweight.hdf5が生成され,use_model.pyで実際に試す時にはこれをloadすることになります。

以下モデルの全体像になります。

training.py
# coding:utf-8
import numpy as np
import scipy.misc
import tensorflow as tf
import pickle as p # python2系はcPickle
from keras.utils import np_utils
from keras.models import Sequential, Model, model_from_json
from keras.layers.core import Dense, Activation, Flatten, Dropout
from keras.layers.convolutional import Convolution2D
from keras.layers.convolutional import MaxPooling2D
from keras.optimizers import SGD
from keras.layers.normalization import BatchNormalization
from keras.callbacks import EarlyStopping, TensorBoard, ModelCheckpoint
from keras.datasets import cifar10

import keras.backend.tensorflow_backend as KTF
import matplotlib.pyplot as plt


in_shape = (32, 32, 3)
cls_num = 3

def build_model():
    model = Sequential()

    model.add(Convolution2D(16, 3, 3, border_mode="same", input_shape=in_shape)) 
    model.add(Activation("relu"))
    model.add(Convolution2D(16, 3, 3, border_mode="same"))
    model.add(Activation("relu"))
    model.add(MaxPooling2D())
    model.add(Dropout(0.5))
    # model.add(Dropout(1))

    model.add(Convolution2D(32, 3, 3, border_mode="same"))
    model.add(Activation("relu"))
    model.add(Convolution2D(32, 3, 3, border_mode="same"))
    model.add(Activation("relu"))
    model.add(MaxPooling2D())
    model.add(Dropout(0.5))
    # model.add(Dropout(1))

    model.add(Convolution2D(64, 3, 3, border_mode="same"))
    model.add(Activation("relu"))
    model.add(Convolution2D(64, 3, 3, border_mode="same"))
    model.add(Activation("relu"))
    model.add(MaxPooling2D())
    model.add(Dropout(0.5))
    # model.add(Dropout(1))

    model.add(Convolution2D(64, 3, 3, border_mode="same"))
    model.add(Activation("relu"))
    model.add(Convolution2D(64, 3, 3, border_mode="same"))
    model.add(Activation("relu"))
    model.add(MaxPooling2D())
    model.add(Dropout(0.5))
    # model.add(Dropout(1))

    model.add(Convolution2D(128, 3, 3, border_mode="same"))
    model.add(Activation("relu"))
    # model.add(BatchNormalization())
    model.add(Dropout(0.5))
    # model.add(Dropout(1))

    model.add(Flatten())
    model.add(Dense(100))
    model.add(Activation("relu"))

    model.add(Dropout(0.5))
    model.add(Dense(cls_num))
    model.add(Activation('softmax'))

    model.compile(loss="categorical_crossentropy", 
        metrics   = ["accuracy"], 
        optimizer = "adam"
    )
    return model

def change3class(exp_val, obj_val):
    new_exp = []
    new_obj = []
    for (x, y) in zip(exp_val, obj_val):
        if y == 3:
            new_exp.append(x)
            new_obj.append(0)
        elif y == 5:
            new_exp.append(x)
            new_obj.append(1)
        elif y == 1:
            new_exp.append(x)
            new_obj.append(2)
        else:
            pass

    new_exp = np.array(new_exp)
    return new_exp, new_obj


if __name__ == "__main__":
    (X_train, y_train), (X_test, y_test) = cifar10.load_data()
    print(X_train.shape, y_train.shape)
    print(X_test.shape, y_test.shape)

    X_train, y_train = change3class(X_train, y_train)
    X_test, y_test = change3class(X_test, y_test)

    y_train = np_utils.to_categorical(y_train)
    y_test  = np_utils.to_categorical(y_test)

    X_train = X_train.astype('float32')
    X_test  = X_test.astype('float32')
    X_train /= 255.0
    X_test /= 255.0

    print("X_train", X_train.shape)
    print("y_train", y_train.shape)
    print("X_test", X_test.shape)
    print("y_test", y_test.shape)

    model = build_model()
    model.fit(X_train, y_train, 
        nb_epoch=250, 
        batch_size=128, 
        validation_data=(X_test, y_test)
    )

    json_string = model.to_json()
    open('test.json', 'w').write(json_string)
    model.save_weights('test.hdf5')

    # evaluate
    score = model.evaluate(X_train, y_train)
    print("test loss", score[0])
    print("test acc",  score[1])

3,保存したモデルを試すためのuse_model.pyの作成

use_model.pyは以下で構成されます。

・画像の読み込み
・training.pyで作成したモデルの読み込み
・読み込んだ画像をモデルに通す
・モデルが返した結果をユーザにわかりやすいように提示

use_model.py
# coding:utf-8
import keras
import sys, os
import scipy
import scipy.misc
import numpy as np
from keras.models import model_from_json

import json

imsize = (32, 32)
testpic = "./testpic/"
keras_model = "./test.json"
keras_param = "./test.hdf5"


def load_image(path):
    img = scipy.misc.imread(path, mode="RGB")
    img = scipy.misc.imresize(img, imsize)
    img = img / 255.0
    return img

def get_file(dir_path):
    """
    testpicディレクトリの配下の画像を1つのリストにして返す
    ['244573113_thumb.jpg', 'car1.jpg', 'car2.jpg', 'car3.jpg', 'cat1.jpg', 'cat2.jpg', 'cat3.jpg', 'dog1.jpg', 'dog2.jpg', 'dog3.jpg', 'dog4.jpg', 'dog5.jpg', 'dog6.jpg', 'dog7.jpg']
    """
    filenames = os.listdir(dir_path)
    return filenames

if __name__ == "__main__":

    pic = get_file(testpic)

    model = model_from_json(open(keras_model).read())
    model.load_weights(keras_param)
    model.summary()

    for i in pic:
        print(i) # ファイル名の出力
        img = load_image(testpic + i)
        #vec = model.predict(np.array([img]), batch_size=1)
        prd = model.predict(np.array([img]))
        print(prd)
        prelabel = np.argmax(prd, axis=1)

        # 各画像ファイルに猫ならファイル名+0が、犬ならファイル名+1、乗り物ならファイル名+2のラベルが付いている
        if prelabel == 0:
            print(">>> 猫")
        elif prelabel == 1:
            print(">>> 犬")
        elif prelabel == 2:
            print(">>> 乗り物")

        print("#"*55)

アンケートフォーム

AI Academy(エーアイ アカデミー)

オンラインによるマンツーマンレッスンでAIプログラミングが学べるスクール。
AI Academy 「AI(人工知能)技術をかつてないほどに多くの人々にとって身近にし、AI時代にAIを活用できる人材を創出する」 ことを掲げ、AIエンジニア育成をしている。

■ Python&AIプログラミングベーシックーコース
・月7,980円
・メールやチャットでの無制限の質問し放題

■ Python&AIプログラミングマスターコース
・月59,800円
・月4回のオンラインマンツーマンレッスン
・メールやチャットでの無制限の質問し放題
・オーダーメイドカリキュラム

無料体験レッスン申し込みはこちら

AI Academy 1day BootCamp

Python文法速習以外にも、色々なイベントを開催しています。
是非他のイベントも見てみてください!
https://connpass.com/user/AI_Academy/open/

AI Academy Community

AI Academy CommunityはオープンなFacebookグループです。 AIに関する情報をお届けします。 定期的にAIに関する情報を知りたい方は、是非参加してください! お待ちしております! https://www.facebook.com/groups/1892746874314837/

※参加するには、Facebookアカウントが必要です。

0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up