1. sartan123

    コメントなし

    sartan123
本文の変更
Source | HTML | Preview
@@ -1,177 +1,177 @@
#はじめに
こちらの記事をかなり参考にしました
[続・深層学習でアニメ顔を分類する with Keras](http://qiita.com/hogefugabar/items/afb4f6c9a93a4bbda51a)
-学習モデルを作って、その正解率は確かめることはできたけど、僕がやりたかったことはネットで拾ってきたアニメキャラの画像を入力として、それを判別することだったのでこの記事ではその辺も含めて書いています。
+学習モデルを作ってその正解率は確かめることはできたけど、僕がやりたかったことはネットで拾ってきたアニメキャラの画像を入力としてそれを判別することだったのでこの記事ではその辺も含めて書いています。
#データセット
学習に使うデータセットは[animeface-character-dataset](http://www.nurs.or.jp/~nagadomi/animeface-character-dataset/)から入手しました。
圧縮ファイルのanimeface-character-datasetを解凍して、そのファルダの中はthumbだけにしておいてください。
#データセット前処理
画像はopencvを使って32×32にリサイズ(この辺も先ほどの記事を参考にしました)し、すべての画像(14490枚)の行列をnumpyのsave()を使って別のファイルに保存していきます。
これで毎回画像を扱わずに済み実行速度も少し速くなります。
画像の正解ラベルも別のファイルに格納しておきましょう。
```dataset_predisporsal.py
import os
import numpy as np
import cv2 as cv
data_dir_path = "./animeface-character-dataset/thumb/"
tmp = os.listdir(data_dir_path)
tmp=sorted([x for x in tmp if os.path.isdir(data_dir_path+x)])
dir_list = tmp
X_target=[]
for dir_name in dir_list:
file_list = os.listdir(data_dir_path+dir_name)
for file_name in file_list:
if file_name.endswith('.png'):
image_path=str(data_dir_path)+str(dir_name)+'/'+str(file_name)
image = cv.imread(image_path)
image = cv.resize(image, (32, 32))
image = image.transpose(2,0,1)
image = image/255.
X_target.append(image)
anime_class=[]
count=0
for dir_name in dir_list:
file_list = os.listdir(data_dir_path+dir_name)
for file_name in file_list:
if file_name.endswith('.png'):
anime_class.append(count)
count+=1
anime_arr2=np.array(anime_class)
np.save('anime_face_target.npy',anime_arr2)
anime_arr=np.array(X_target)
np.save('anime_face_data.npy',anime_arr)
```
anime_face_data.npyには画像の行列(14490,3,28,28)
anime_face_target.npyには正解ラベル(14490,)
が保存されます。
#Kerasによるモデル構築と学習
前処理で作成した2つのnpyファイルを読み込んで学習させます。
```anime_face.py
import numpy as np
np.random.seed(20160715) # シード値を固定
from keras.layers.convolutional import Convolution2D
from keras.layers.core import Activation
from keras.layers.core import Dense
from keras.models import Sequential
from keras.callbacks import EarlyStopping
from keras.callbacks import LearningRateScheduler
from keras.optimizers import Adam
from keras.optimizers import SGD
import sklearn.cross_validation
X_test=np.load('anime_face_data.npy')
Y_target=np.load('anime_face_target.npy')
a_train, a_test, b_train, b_test = sklearn.cross_validation.train_test_split(X_test,Y_target)
model = Sequential()
model.add(Convolution2D(96, 3, 3, border_mode='same', input_shape=(3, 32, 32)))
model.add(Activation('relu'))
model.add(Convolution2D(128, 3, 3))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Flatten())
model.add(Dense(1024))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(203))
model.add(Activation('softmax'))
init_learning_rate = 1e-2
opt = SGD(lr=init_learning_rate, decay=0.0, momentum=0.9, nesterov=False)
model.compile(loss='sparse_categorical_crossentropy', optimizer=opt, metrics=["acc"])
early_stopping = EarlyStopping(monitor='val_loss', patience=3, verbose=0, mode='auto')
lrs = LearningRateScheduler(0.01)
hist = model.fit(a_train,b_train,
batch_size=128,
nb_epoch=50,
validation_split=0.1,
verbose=1)
model_json_str = model.to_json()
open('anime_face_model.json', 'w').write(model_json_str)
model.save_weights('anime_face_model.h5')
score=model.evaluate(a_test, b_test, verbose=0)
print(score[1])
```
結果は約55%の正解率でした。
正解率を上げる方法については今回は触れません。
```
model_json_str = model.to_json()
open('anime_face_model.json', 'w').write(model_json_str)
model.save_weights('anime_face_model.h5')
```
この部分が重要で学習モデルと学習結果をanime_face_model.jsonとnime_face_model.h5にそれぞれ保存します。
これで学習モデルと学習結果を使い回すことができるようになりました。
実行する時も一瞬です。
さて次が本題です。
#学習結果を使ってオリジナル画像を判別する
今回使用するオリジナル画像は魔法少女リリカルなのはの「八神はやて」(yagami.png)です
![yagami.png](https://qiita-image-store.s3.amazonaws.com/0/125193/c6d5a5c1-c8f7-4a8f-5b90-5794bfa0c246.png)
```load_anime_face.py
import numpy as np
from keras.models import model_from_json
from keras.utils import np_utils
from keras.optimizers import SGD
import sklearn.cross_validation
import cv2 as cv
np.random.seed(20160717)
X_test=np.load('anime_face_data.npy')
Y_target=np.load('anime_face_target.npy')
model = model_from_json(open('anime_face_model.json').read())
model.load_weights('anime_face_model.h5')
init_learning_rate = 1e-2
opt = SGD(lr=init_learning_rate, decay=0.0, momentum=0.9, nesterov=False)
model.compile(loss='sparse_categorical_crossentropy', optimizer=opt, metrics=["acc"])
image = cv.imread('yagami.png')
image = cv.resize(image, (32, 32))
image = image.transpose(2,0,1)
image = image/255.
image=image.reshape(1,3,32,32)
for i in range(202):
sample_target=np.array([i])
score = model.evaluate(image, sample_target, verbose=0)
if score[1]==1.0:
break
print(i)
```
39と出力されました。
この数字はthumbの中にあるファイル名の先頭の数字になります。
![スクリーンショット 2016-10-18 13.51.55.png](https://qiita-image-store.s3.amazonaws.com/0/125193/6b1135b7-e813-4b27-4c40-47def28d352a.png)
したがって39番の八神はやてを正解することができたということになります。
しかし正解率は55%なので、不正解であることもかなり多いです。
#おわりに
特に解説もせず淡々とコードと処理内容を書いてきましたが、これでオリジナル画像を入力としてキャラを判別することができるようにました。
正解率だけを見てもあまり実感が湧かないので、このように1枚の画像を入力として結果が返ってくると僕みたいな機械学習の初心者からするとやったぜという気持ちになります。
何か疑問や突っ込みがあればコメントしてもらえると嬉しいです。
簡単ですが以上になります。