Edited at

keras(tensorflow)で花の画像から名前を特定

More than 1 year has passed since last update.

Convolutional Neural Network (CNN)畳み込みニューラルネットで、

花の画像から名前を特定する実験をしてみる!


はじめに

今回はdocker環境上にプログラムをおいて実施します。

 1.環境準備

 2.プログラム

 3.実験

 

プログラムはGitに置いておきます。


環境準備


開発環境

Macbook pro 13 2016


dockerのインストール

dockerは以下のサイトからバイナリで簡単にインストールできます。

https://docs.docker.com/docker-for-mac/


Minicondaイメージから機械学習環境を構築

機械学習系のパッケージを詰め込んだ、コンパイル済みバイナリをインストールできる

conda(Miniconda)での環境構築をします。


① テンプレートのダウンロード

$ docker pull continuumio/miniconda3


② Dockerfileの作成

$ vi Dockerfile

  :
$ cat Dockerfile
FROM continuumio/miniconda3
RUN apt-get update
RUN pip install --upgrade pip
RUN pip install tensorflow \
pandas \
scipy \
Pillow \
keras
RUN pip install -U scikit-learn
RUN mkdir /home/src/


③ dockerのbuild(イメージの作成)

$ docker build -t conda:init .


④ 確認

$ docker images

REPOSITORY TAG IMAGE ID CREATED SIZE
conda init daf923e29da8 2 hours ago 1.55 GB


⑤ dockerの起動

今回はdockerに開発するフォルダをマウントします。

# [mount dir]を書き換えて使ってください。

$ docker run -i -t -v [mount dir]:/home/src conda:init /bin/bash

「Cntl + p」、「Cntl + q」で抜けれます。

再度、コンテナにアクセスする場合

$ docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
745860b72c67 conda:init "/usr/bin/tini -- ..." 11 hours ago Up 11 hours friendly_galileo

# CONTAINER ID を指定
$ docker attach 745860b72c67

これで環境準備は完了


ここから花画像分類のプログラム


① トレーニングデータの準備

インターネットから適当に花の画像を集めます!

以下のキャプチャの様にディレクトリ名に花の名前をつけ、その中に花の画像を配置。

キャプチャ

※ この辺は画像の権利等あるかと思いますのでご自身にて集めてください。


② 学習モデルの作成

画像データとカテゴリの配列を保存プログラムを準備します。


data_create.py

from PIL import Image

import sys
from sklearn import cross_validation
import os, glob
import numpy as np
import random, math

#
# トレーニングデータを生成
#
class DataCreate :
def __init__(self, script_name):
Image.LOAD_TRUNCATED_IMAGES = True

def create(self) :
input_dir = "images"
categorys = []

dir_list = os.listdir(input_dir)
for index, dir_name in enumerate(dir_list):
if dir_name == '.DS_Store' :
continue
categorys.append(dir_name)
image_size = 50
train_data = [] # 画像データ, ラベルデータ
for idx, category in enumerate(categorys):
try :
print("---", category)
image_dir = input_dir + "/" + category
files = glob.glob(image_dir + "/*.jpg")
for i, f in enumerate(files):
img = Image.open(f)
img = img.convert("RGB")
img = img.resize((image_size, image_size))
data = np.asarray(img)
train_data.append([data, idx])

except:
print("SKIP : " + category)

# データをshuffle
random.shuffle(train_data)
X, Y = [],[]
for data in train_data:
X.append(data[0])
Y.append(data[1])

test_idx = math.floor(len(X) * 0.8)
xy = (np.array(X[0:test_idx]), np.array(X[test_idx:]),
np.array(Y[0:test_idx]), np.array(Y[test_idx:]))
np.save("./npy/flower", xy)

if __name__ == "__main__":
args = sys.argv
datacreate = DataCreate(args[0])
datacreate.create()


次に学習モデルを作るプログラムを準備します。


train.py

import sys

import os
import numpy as np
import pandas as pd
import gc
from keras.models import Sequential
from keras.layers import Convolution2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras.utils import np_utils

#
# モデルを生成
#
class TrainModel :
def __init__(self):
input_dir = 'images'
self.nb_classes = len([name for name in os.listdir(input_dir) if name != ".DS_Store"])
x_train, x_test, y_train, y_test = np.load("./npy/flower.npy")
# データを正規化する
self.x_train = x_train.astype("float") / 256
self.x_test = x_test.astype("float") / 256
self.y_train = np_utils.to_categorical(y_train, self.nb_classes)
self.y_test = np_utils.to_categorical(y_test, self.nb_classes)

def train(self, input=None) :
model = Sequential()
# K=32, M=3, H=3
if input == None :
model.add(Convolution2D(32, 3, 3, border_mode='same', input_shape=self.x_train.shape[1:]))
else :
model.add(Convolution2D(32, 3, 3, border_mode='same', input_shape=input))

# K=64, M=3, H=3(調整)
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Convolution2D(64, 3, 3, border_mode='same'))
model.add(Activation('relu'))
# K=64, M=3, H=3(調整)
model.add(Convolution2D(64, 3, 3))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(512))
# biases nb_classes
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(self.nb_classes))
model.add(Activation('softmax'))

model.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy'])
if input == None :
# 学習してモデルを保存
model.fit(self.x_train, self.y_train, batch_size=32, nb_epoch=10)
hdf5_file = "./model/flower-model.hdf5"
model.save_weights(hdf5_file)

# modelのテスト
score = model.evaluate(self.x_test, self.y_test)
print('loss=', score[0])
print('accuracy=', score[1])
return model

if __name__ == "__main__":
args = sys.argv
train = TrainModel()
train.train()
gc.collect()


これで学習は完了。

続いて実行してみます。

※ スペックにもよりますが、少し時間がかかります。

# 画像を配列化

$ python data_create.py
--- アイ(タデアイ)
--- アオギリ
--- アオモリアザミ(オキノアザミ)
--- アガパンサス(ムラサキクンシラン)
--- アカザ
--- アカショウマ
--- アカバナソバ
--- アカバナミツマタ
--- アカヤジオウ
--- アカンサス(ハアザミ)
--- アギナシ
--- アキザキスノーフレーク
--- アキノウナギツカミ
--- アキノタムラソウ(サルビア・ヤポニカ)
--- アキノノゲシ
--- アキノワスレグサ

# 学習
$ python train.py
:
loss= 0.0410282239616
accuracy= 0.992773946126

的中率 99%はバグってる(笑)


③ とりあえずモデルのテスト

モデルテスト用に簡単なプログラムを用意します。


check.py

import train as train

import sys, os
from PIL import Image
import numpy as np
import pandas as pd

if len(sys.argv) <= 1:
quit()

image_size = 50
input_dir = 'images'
categories = [name for name in os.listdir(input_dir) if name != ".DS_Store"]

X = []
for file_name in sys.argv[1:]:
img = Image.open(file_name)
img = img.convert("RGB")
img = img.resize((image_size, image_size))
in_data = np.asarray(img)
X.append(in_data)

X = np.array(X)

model = train.TrainModel().train(X.shape[1:])
model.load_weights("./model/flower-model.hdf5")

predict = model.predict(X)

for pre in predict:
y = pre.argmax()
print("花の名前 : ", categories[y])



テスト実行

きゅうりの花でテスト。

flower.jpg

$ python check.py test/flower.jpg

Using TensorFlow backend.
花の名前 : キュウリ

きゅうりは成功!でも他の写真だとうまくいかないときもあった。

もう少し勉強して、またあげます。


最後に

時間あるときに学習付きのチャットボットの作り方もあげます。