Deep Learningをしてみたいと思っていましたが、何から手をつけて良いか分からずにいましたが[この記事](http://taka-say.hateblo.jp/entry/2016/12/19/235554)をみて同じ事をやってみました。
記事の書かれた時とKerasのバージョンが違ったりして、なかなかハマりました。
現在のバージョンで試すための勘所をまとめます。
これが理解できれば、自分の求める分類器を作成する事ができると思います。
### 環境
なんかpythonのバージョンが微妙みたいですが、以下のバージョンで確認しています。
```bash
$ python -c 'import keras; print(keras.__version__)'
Using TensorFlow backend.
/Users/xxxxx/.pyenv/versions/anaconda3-4.2.0/lib/python3.5/importlib/_bootstrap.py:222: RuntimeWarning: compiletime version 3.6 of module 'tensorflow.python.framework.fast_tensor_util' does not match runtime version 3.5
return f(*args, **kwds)
2.1.4
```
### 事前準備
ガッキーの顔写真などをDLして加工しておきます。
今回は、写真を与えるとなんの写真か分類する分類器を作成します。
フォルダ構成は以下の通り
```
`gutter:false;
└── FaceImages
├── Gakkey # ガッキーの顔イメージ
└── Other # その他のイメージ
```
### 学習データの準備
Kerasで学習を行うには、学習データと回答データを用意する必要があります。
分類する画像は以下のようにします。
* サイズを64 x 64にする
* 0.0〜1.0の間にする
* 回答は[0, 1, 0...] のようにする (0,1がそれぞれの画像の回答)
```python
import os
import glob
import numpy as np
import cv2
data_dir_path = './FaceImages/'
tmp = os.listdir(data_dir_path)
dir_list = sorted([x for x in tmp if os.path.isdir(data_dir_path + x)])
X_data = []
Y_data = []
for i, dir_name in enumerate(dir_list):
images = glob.glob(data_dir_path + dir_name + '/*.jpg')
for path in images:
# [64, 64, 3] に変更する
# 画像は255で割って0 - 1の範囲にする
image = cv2.imread(path)
image = cv2.resize(image, (64, 64))
image = image / 255.
X_data.append(image)
Y_data.append(i)
X_ary = np.array(X_data)
np.save('X_data_npy', X_ary)
Y_ary = np.array(Y_data)
np.save('Y_data_npy', Y_ary)
```
僕の環境では、image.transpose(2, 0, 1)を行う必要はありませんでした。
### Kerasで学習を行う
Kerasで学習を行うのですが、バージョンが上がっていたので他のページを参考にしつつ学習するコードを作成します。
Conv2Dを使うようにします。
```python
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras.optimizers import SGD
from keras.callbacks import ModelCheckpoint
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
# 学習データの準備
X_data = np.load('X_data_npy.npy')
Y_data = np.load('Y_data_npy.npy')
X_train, X_test, Y_train, Y_test = train_test_split(X_data, Y_data, test_size=0.15, random_state=42)
# オプション指定
batch_size = 32
nb_classes = 2
nb_epoch = 21
# モデル定義
model = Sequential()
#model.add(Conv2D(32, (3, 3), activation='relu', input_shape=X_train.shape[1:]))
print(X_train.shape[1:])
model.add(Conv2D(32, (3, 3), activation='relu', input_shape=X_train.shape[1:], data_format="channels_last"))
model.add(Conv2D(32, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(256, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(nb_classes, activation='softmax'))
sgd = SGD(lr=2e-2, momentum=0.9, decay=0.0, nesterov=True)
model.compile(loss='sparse_categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
checkpointer = ModelCheckpoint(filepath="./Models/gakkey_face_model.hdf5", verbose=1, save_best_only=True)
# モデル学習
hist = model.fit(X_train, Y_train,
batch_size=batch_size,
nb_epoch=nb_epoch,
validation_data=(X_test, Y_test),
shuffle=True,
verbose=1,
callbacks=[checkpointer])
# 学習経過のプロット
plt.style.use("ggplot")
df = pd.DataFrame(hist.history)
df.index += 1
df.index.name = "epoch"
df[["acc", "val_acc"]].plot(linewidth=2)
plt.savefig("acc_history.pdf")
df[["loss", "val_loss"]].plot(linewidth=2)
plt.savefig("loss_history.pdf")
```
Modelsフォルダを作成しておきましょう。
学習が成功すると、gakkey_face_model.hdf5が作成されます。
### 作成したモデルを使用する
作成したモデルを使うには以下のようにします。
modelに入れて学習させるためには、[1, 64, 64, 3]にする必要があります。
(そこに気づくのに時間がかかりました)
```python
from keras.models import load_model
import numpy as np
import cv2
model = load_model('./models/gakkey_face_model.hdf5')
def predict(path):
image = cv2.imread(path)
image = cv2.resize(image, (64, 64))
image = image / 255.
# 画像データをnumpy.arrayに変換
image = np.expand_dims(image, axis=0)
print(model.predict(np.array(image)))
predict('checkimage.png')
```
0 件のコメント :
コメントを投稿