#3 無念 学習モデルの構築 (ハンドジェスチャーでドローンを操作する )

今回は失敗してしまったので書く必要性はないと思いますが記録として書いていこうと思います。

## 1 学習用のデータセットの読み込み

#2で作成したデータセットのに合わせてデータセットの読み込みを以下のコードで行います。
データセットの中身は、6クラスで1クラス250枚の画像があります。今回は訓練:テストで8:2で分割します。

```python
import os
import cv2
import numpy as np

#train,testに指定した比率で分割する

train = 8
test = 10 - train

dir = './ds'

#クラス数の取得
num_class = len(os.listdir(dir))
print(num_class)

x_train = []
y_train = []

x_test = []
y_test = []

cnt = 0
class_label = 0

for folders in os.listdir(dir):
    file_list = os.listdir(dir + '/' +  folders)
    for file in file_list:
        
        img = cv2.imread(dir + '/' + folders + '/' + file)
        size = (64,48)
        img = cv2.resize(img,size)
        
        if cnt < len(file_list)/10*8:
            #print(dir + '/' + folders + '/' + file)
            x_train.append(img)
            y_train.append(class_label)
            cnt = cnt + 1
        else:
            #print(dir + '/' + folders + '/' + file)
            x_test.append(img)
            y_test.append(class_label)
    cnt = 0
    class_label = class_label + 1

x_train = np.array(x_train)
y_train = np.array(y_train)

x_test = np.array(x_test)
y_test = np.array(y_test)

#保存は最初以降の読込以外はしなくても良い
dataset_dir = "dataset.npy"
dataset = (x_train,x_test,y_train,y_test)
np.save(dataset_dir,dataset)

x_train,x_test,y_train,y_test = np.load(dataset_dir, allow_pickle=True)

x_train = x_train.astype("float") / x_train.max()
x_test  = x_test.astype("float") /  x_train.max()

y_train = np_utils.to_categorical(y_train,(num_class))
y_test  = np_utils.to_categorical(y_test ,(num_class))
```

## 2 モデルの構築・学習

様々なモデル構造を試して最も精度が良かった構造を載せています。
（他にもあると思いますが...）

```Python
import os
import cv2
import numpy as np
from __future__ import absolute_import, division, print_function, unicode_literals
import tensorflow as tf
from tensorflow import keras, config
from tensorflow.keras.layers import Dense, Flatten, Conv2D
from tensorflow.keras import Model
from keras.utils import np_utils

input_shape = (48, 64, 3)

model = tf.keras.Sequential()

model.add(tf.keras.layers.Conv2D(8,(3,3),padding='same',input_shape=input_shape,activation='relu'))
model.add(tf.keras.layers.MaxPooling2D(2,2))

model.add(tf.keras.layers.Conv2D(16,(3,3),padding='same',input_shape=input_shape,activation='relu'))
model.add(tf.keras.layers.MaxPooling2D(2,2))

model.add(tf.keras.layers.Conv2D(32,(3,3),padding='same',input_shape=input_shape,activation='relu'))
model.add(tf.keras.layers.MaxPooling2D(2,2))

model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(128, activation='relu'))
model.add(tf.keras.layers.Dense(64, activation='relu'))
model.add(tf.keras.layers.Dense(32, activation='relu'))
model.add(tf.keras.layers.Dropout(0.5))
model.add(tf.keras.layers.Dense(num_class,activation="softmax"))

model.compile(loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy"])

model.summary()

model.fit(x_train, y_train, batch_size=1, epochs=10)
model.save('test.h5')
```

## 3 結果

回した際の精度はいいのですが...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336392/1e26bf2b-b719-989e-5730-0e686aa4ae92.png)

評価から雲行きが怪しく...
```python
score = model.evaluate(x_test, y_test, verbose=0)
print("Test loss:", score[0])
print("Test accuracy:", score[1])
```

## 4 モデルの読み込み

```python
import os
import cv2
import numpy as np
from __future__ import absolute_import, division, print_function, unicode_literals
import tensorflow as tf
from tensorflow import keras, config
from tensorflow.keras.layers import Dense, Flatten, Conv2D
from tensorflow.keras import Model
from keras.utils import np_utils

input_shape = (48, 64, 3)

model = tf.keras.Sequential()

model.add(tf.keras.layers.Conv2D(8,(3,3),padding='same',input_shape=input_shape,activation='relu'))
model.add(tf.keras.layers.MaxPooling2D(2,2))

model.add(tf.keras.layers.Conv2D(16,(3,3),padding='same',input_shape=input_shape,activation='relu'))
model.add(tf.keras.layers.MaxPooling2D(2,2))

model.add(tf.keras.layers.Conv2D(32,(3,3),padding='same',input_shape=input_shape,activation='relu'))
model.add(tf.keras.layers.MaxPooling2D(2,2))

model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(128, activation='relu'))
model.add(tf.keras.layers.Dense(64, activation='relu'))
model.add(tf.keras.layers.Dense(32, activation='relu'))
model.add(tf.keras.layers.Dropout(0.5))
model.add(tf.keras.layers.Dense(num_class,activation="softmax"))

model.compile(loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy"])

model.summary()

model.load_weights('./test.h5')

```

評価用のデータセットの読込み

```python
import os
import cv2
import numpy as np

#評価用のデータセットの読み込み

dir = './eva'

#クラス数の取得
num_class = len(os.listdir(dir))
print(num_class)

x_eva = []
y_eva = []

cnt = 0
class_label = 0

for folders in os.listdir(dir):
    file_list = os.listdir(dir + '/' +  folders)
    for file in file_list:
        
        img = cv2.imread(dir + '/' + folders + '/' + file)
        size = (64,48)
        img = cv2.resize(img,size)
        
        #print(dir + '/' + folders + '/' + file)
        x_eva.append(img)
        y_eva.append(class_label)

    class_label = class_label + 1

x_eva = np.array(x_eva)
y_eva = np.array(y_eva)

x_eva = x_eva.astype("float") / x_eva.max()
y_eva  = np_utils.to_categorical(y_eva ,(num_class))

```

## 5 結果
この精度は、ちょっとね...

```python
score = model.evaluate(x_eva, y_eva)
print('Test loss:', score[0])
print('Test accuracy:', score[1])
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336392/a76a105d-d6e5-eead-cdc9-094175321ce3.png)

## 6　今後の展望
今回は6クラスの分類を行いましたがクラス数を減らせば変わってくるかもしれません。

mediapipeでハンドトラッキングして座標を取得して学習させた方が精度が良いことが分かったのでデータ収集からやり直ししていこうと思います。