[Deep Learning] Kerasで分類器を作成する

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 件のコメント :

コメントを投稿