こんにちは、のっくんです。
今日はKaggleにあったジェスチャー画像の分類を、ニューラルネットを使ってやっていきたいと思います。
Hand Gesture Recognition Databaseという、リープモーションで撮影した赤外線画像のデータベースを使います。
https://www.kaggle.com/gti-upm/leapgestrecog/version/1
データセットをダウンロードするには、Kaggleにログインする必要があります。

10種類のジェスチャー画像
[toc]
画像データの読み込み
まず最初に画像とラベルの読み込みをやっていきます。
画像データをX、ラベルをyとします。
画像枚数は2万枚ありますが、1枚ずつopencvで読み込んでリストに追加(append)していきます。
ラベルはファイル名についている、01~10の10種類のラベルを使用することにします。
こちらも1枚ずつ、ファイル名からリストに追加(append)していきます。
import os from os import walk import cv2 mypath = "./leapGestRecog" f = [] for (dirpath, dirnames, filenames) in walk(mypath): f.extend(os.path.join(dirpath, filename) for filename in filenames) X = [] y = [] for i in f: img = cv2.imread(i) img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) img = cv2.resize(img,(120,320)) X.append(img) file_name = i.split("/")[4] y.append(file_name.split("_")[2])
これで、Xとyが作成できました。
リストからnumpy配列に変換
Xとyが作成できましたが、今のままだとリストです。
ディープラーニングをする際には扱うデータはnumpyの配列が定石なので、numpy配列に変換しましょう。
# リストをNumPy配列ndarrayに変換 import numpy as np X = np.array(X) y = np.array(y)
さてここでyのラベルの数を数えてみます。
# yのラベルと数を数え上げる u, c = np.unique(y, return_counts=True) print(dict(zip(u, c)))
{'01': 2000, '02': 2000, '03': 2000, '04': 2000, '05': 2000, '06': 2000, '07': 2000, '08': 2000, '09': 2000, '10': 2000}
01~10のラベルがありますが、ワンホットベクトル(1次元ベクター)に変換する際に、10があるとエラーが発生しました。
`np.where`を使って、10を00に変換します。
y = np.where(y=="10", "00", y)
データの分割
学習用とテスト用にデータを分割します。
from sklearn.model_selection import train_test_split X_train, X_test,y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0) print(X_train.shape) print(X_test.shape) print(y_train.shape) print(y_test.shape)
(16000, 320, 120) (4000, 320, 120) (16000,) (4000,)
16000枚を学習用、4000枚をテスト用に分割しました。
学習の前処理
画像データの場合、ディープラーニングにかける前に1次元にしたり浮動小数点数にする必要があります。
ラベルデータはワンホットベクトルにするのが定石です。
このあたりの処理は、numpyとkerasを使うとすぐに変換できます。
import keras height= 120 witdh = 320 im_size = height*witdh num_classes = 10 # データを一次元配列に変換 X_train = X_train.reshape(-1, im_size).astype('float32') / 255 X_test = X_test.reshape(-1, im_size).astype('float32') / 255 # ラベルデータをOne-Hot形式に変換 y_train = keras.utils.to_categorical(y_train, num_classes) y_test = keras.utils.to_categorical(y_test, num_classes)
学習
入力層(120*320)〜中間層(512)〜出力層(10)の3層から構成される多層パーセプトロン(ニューラルネット)を作ります。
from keras.models import Sequential from keras.layers import Dense, Dropout from keras.callbacks import EarlyStopping # モデルを定義 model = Sequential() model.add(Dense(512, activation='relu', input_shape=(im_size,))) model.add(Dense(num_classes, activation='softmax')) es = EarlyStopping(monitor="val_loss", patience=2) # モデルをコンパイル model.compile( loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) # 学習を実行 hist = model.fit(X_train, y_train, batch_size=32, epochs=50, verbose=1, validation_data=(X_test, y_test), callbacks=[es]) # モデルを評価 score = model.evaluate(X_test, y_test, verbose=1) print('正解率=', score[1], 'loss=', score[0])
実行結果は以下の通り。
Train on 16000 samples, validate on 4000 samples Epoch 1/50 16000/16000 [==============================] - 15s 961us/step - loss: 5.1985 - acc: 0.6251 - val_loss: 4.9323 - val_acc: 0.6760 Epoch 2/50 16000/16000 [==============================] - 14s 877us/step - loss: 3.3693 - acc: 0.7701 - val_loss: 3.2928 - val_acc: 0.7900 Epoch 3/50 16000/16000 [==============================] - 14s 886us/step - loss: 3.2374 - acc: 0.7946 - val_loss: 3.2884 - val_acc: 0.7887 Epoch 4/50 16000/16000 [==============================] - 14s 879us/step - loss: 0.9810 - acc: 0.9134 - val_loss: 0.0268 - val_acc: 0.9952 Epoch 5/50 16000/16000 [==============================] - 14s 882us/step - loss: 0.0089 - acc: 0.9985 - val_loss: 0.0065 - val_acc: 0.9982 Epoch 6/50 16000/16000 [==============================] - 14s 879us/step - loss: 0.0059 - acc: 0.9989 - val_loss: 0.0039 - val_acc: 0.9992 Epoch 7/50 16000/16000 [==============================] - 14s 881us/step - loss: 0.0271 - acc: 0.9921 - val_loss: 0.4057 - val_acc: 0.9018 Epoch 8/50 16000/16000 [==============================] - 14s 885us/step - loss: 0.0613 - acc: 0.9854 - val_loss: 0.0079 - val_acc: 0.9978 4000/4000 [==============================] - 1s 165us/step 正解率= 0.99775 loss= 0.007857956944731995
EarlyStoppingを使っているので8エポックで終了し、精度は約99.7%でした。
実行速度はGeforce GTX1060を使って2分程度でした。
シンプルなネットワークでしたが、かなりの精度が出て驚きました。
というのも、前にcifar10データセットに多層パーセプトロン(MLP)を適用してあまり精度が出なかったからです。
精度が低かった場合には畳み込みニューラルネット(CNN)を試そうと思っていましたが、試さなくても良いかな。
おわり。