---
title: Hand Posture Recognition with CNN - 以CNN解決手勢辨識問題
tags: Fundamental Deep Learning Assignments 2019, NDHU, CSIE
lang: zh_tw
---
# Hand Posture Recognition with CNN - 以CNN解決手勢辨識問題
##### Table of Contents
[TOC]
[code]: https://github.com/how8570/Hand-Posture-Recognition-with-CNN
## 0x00. Before Start - 在開始之前
- 環境建置
參考自 [林鈺錦大大分享的環境配置](https://hackmd.io/@abc1236762/HJAozs9pB) 以及我自行需要的套件
```shell
conda create -n deeplearn --strict-channel-priority python=3.6
tensorflow-gpu=1.14 keras numpy=1.16 pydot opencv
jupyter pylint autopep8 matplotlab pillow scikit-learn
```
- [完整原始碼][code]
> 這次我們用上了熟悉的 keras 套件完成 CNN 分類辨識問題。在這次的實作中要求,是利用 CNN 分辨出三種不同的手勢。
>[name=how8570]
## 0x01. Problem Descriptions - 問題解釋
- 本次的作業來自 **東華大學2019年度的深度學習導論** 的課堂作業
- [這裡是原題 \[可能需要 東華e學院 帳號才能存取\] ](http://web.csie.ndhu.edu.tw/ccchiang/Data/fdl_assignment2.pdf)
- 問題描述: (來自原題)<br>
[資料集 \[可能需要 東華e學院 帳號才能存取\]](http://web.csie.ndhu.edu.tw/ccchiang/Data/All_gray_1_32_32.rar)
## 0x02. Solutions - 解決思路
- 由於這次我們很開心的可以使用套件了 ~~所以當然是先 import keras~~
所以這的最大問題當然是在資料前處理的部分了
- 因為資料要分成測試跟訓練的部分,然後我檢查了一下資料集的數量

摁...有點少阿...
- 於是為了增加資料量我在處理圖片時增加了 <U>**垂直鏡像**</U> 的處理
實作如下
```python=
def get_train_datas():
train_data = []
train_label = []
for gen_path in itertools.product(path_of_TrainSets, path_of_type, path_of_dataID):
path = 'All_gray_1_32_32/' + '/'.join(gen_path) + '/'
for img in os.listdir(path):
if img.endswith('jpg'):
path += img
train_data.append(mpimg.imread(path))
# 垂直鏡射增加資料集
train_data.append(mpimg.imread(path)[:,::-1])
if gen_path[1] in ('0000', '0001', '0002'):
train_label.append(0)
train_label.append(0) # 別忘了一次是生兩張圖 label 也要加兩次
elif gen_path[1] in ('0003', '0004', '0005'):
train_label.append(1)
train_label.append(1)
elif gen_path[1] in ('0006', '0007', '0008'):
train_label.append(2)
train_label.append(2)
return np.array(train_data), np.array(train_label)
```
- 模型設計部分

我以兩層捲積 (Conv2D) 連上三層的全連接層 (Dense) 的架構建置該模型,並在其中插入池化 (Maxpooling) 以期望更良好的抓取特徵,插入丟棄層 (Dropout) 以避免過度學習 (Overfitting)。
- 其他細節請參考 [完整原始碼](code)
## 0x03 Result - 實現成果
- 雖然在我寫作業之前,同寢室的同學一直跟我嚷嚷著他的 **訓練成果是 1** ,如此誇張之高。雖然第一時間覺得是 Overfitting,但讓我心裡備感壓力。
- 而在最初還沒有增加資料時時做辨識率大概只有 83%~85% ,讓我直懷疑我以前在修其他課程所學到的經驗是不是有些出入?
- 於是我就去向其他人請教他們的 code 怎麼樣的一回事,發現大部分的同學好像都誤會於老師的題目要求 (或是是我誤會?)
- 他們在使用 fit 函數時,將 validation_data 的參數置入 (test_data, vali_label)
範例:`model.fit(x, y, validation_data=(test_data, vali_label), ...)`
這也意味著這些測試資料並不是被用來測試的。
上方的意思如果用比喻來說的話,那就是:
- 1.我們訓練 小明 考數學 目標考到100分
2.給了小明考古題 (有題目/有答案)
3.考另一個題庫出的小考 (小考內容是類似的題目,但不曾出現在考古題中),並告訴小明,這題你寫對了還是寫錯了。
4.重複3.直到設定的次數
- 但是這過程中其實已經讓小明 **類似利用試錯法** 的方式 **得知這些題庫小考題目解法**,及意味著 **如果有辦法訓練到 1.0,通常是 Overfitting**。( [issue 連結](https://github.com/keras-team/keras/issues/1753) 有提到相關內容)
- 這樣可能導致我們在訓練模型時選出過度符合這些資料集(訓練+測試)的模型
- 關於我理解的 test_data 的使用方式
- 我們應該是把 train_data 分成 train_feature 與 vali_features 兩個部分。訓練完模型後再使用 test_data 這份全新的考題來校驗我們的 model 的準確率
- 而我使用這個方式來核對我的模型正確率如下:
左邊是 loss 右邊是 正確率

- 雖然數字看起來低了不少,但我認為這才是 **真正有意義的正確率** ,不是唬爛的數字
- 詳情疑問可以參考這邊
- [issue (多數支持放心在 validation_data 使用 test data)](https://github.com/keras-team/keras/issues/1753)
- [簡書上的內容 (支持不應該使用)](https://www.jianshu.com/p/0c7af5fbcf72)
- 圖片的部分

## 0x04 Summary - 後計與總結
- 在嘗試鏡像原始資料集時,原本預期可能效果沒有這麼好,畢竟右手拇指會在左邊,手整個方向會不一樣。沒想到卻還是提升了不少準確率,可見對於 model 的特徵抽取來說,拇指在哪似乎不是這麼重要 ~~,可以把它切了~~。
- 雖然這次的作業好像砲火猛烈 XD ,但我覺得好像真的是大家誤會了題目的意思。
## 0x05 Tools and Reference - 工具與參考項目
- Tools
- IDE: [Visual Studio Code](https://code.visualstudio.com/)
- Git Remote repository: [GitHub](https://github.com/)
- Reference
- lecture slide
- [Wikipedia](https://www.wikipedia.org/)
- [keras 中文 doc](https://keras.io/zh/)
- [簡書](https://www.jianshu.com/)
> [name=how8570]
> [time=Thu, Dec 19, 2019 3:37 AM]
<style>
span.hidden-xs:after {
content: ' × NDHU AI' !important;
}
</style>