2020年12月1日 星期二

[DL]Static Gestures Recognition(6): Training Model & Next Step

從構想、規劃、試錯到完成深度學習的手勢辨識模型。


reference from Mark Robins



6 Training Model & Next Step

 

當前期充分準備後,後續訓練模型的過程反而沒花那麼多時間。

在建立訓練模型的過程中,反覆測試的過程是難以避免的。

比較值得一提的是測試中發現,模型層數增減影響結果甚為重要,

如果參數太少,在訓練的過程中很快就會發現 loss & accuracy 數值很不理想,

也就沒有必要再繼續跑下去。



但究竟該怎麼設定多寡?  坦白說目前也只有累積經驗值才知 (還請高手賜教)

關於細節請參考GitHub

Static Gesture Recognition @ GitHub


DEMO






What’s next?

儘管完成了初階段目標,但仍有很多方向值得觀察、改善、繼續深究:

 

誤判情形:

當在ROI範圍內迅速切換時,無可避免的是轉換手勢的過程中難免會出現誤判情形,

這是因為webcam不停地擷取影像資訊交給模型預測,在切換的過程中一定會出現非既定圖像的情況,

不過變換的時間只有一下子所以也不會造成太大影響。

實際應用時,應考慮接收手勢持續的時間後(如2秒內)再進行決定採用何種行為,應可有效降低誤判機率。

 


效能表現:

實際在PC上測試,以CPU Intel i5-3470 3.2G, RAM 8G, OS: Win10 硬體為例

執行時CPU使用率高達85+%


若要實際應用,必須要找出有效降低消耗資源的方法(Embedded system or other platform ?)

假設在真正進行判斷之前,先進行 Hand Detection,之後再行gesture recognition

是否有降低消耗資源的可能性(前提是Hand Detection 比起 Gesture Recognition有更好的性能消耗比)

或是降低模型的隱藏層數是否也是可能的方向?  都還有待繼續探索驗證。

 

 

更貼近真實的使用情境:

由於使用的是1 channel灰階圖案,且實際場景與訓練圖片也是刻意去除背景,

未必能完全適用在真實的複雜情境上。若要更廣泛的情境判斷,就必須有更大量的真實圖片提供訓練。抑或是有其他方式?

simple & complex background



擴充的可能:

是否在預訓練的模型上繼續擴充使用這套模型呢 但本專題使用的是單通道灰階圖像,必須要重新設定蒐集訓練圖片才行。



 動態手勢追蹤:

這個模型現階段僅能辨識靜態手勢,如果能進一步識別動態手勢,應用層面想必能更加擴大活躍!



更輕量的檔案大小與裝置:

由於單一模型就有591MB,為了提高效率,採用權重+結構是不可或缺的做法,但即使權重也高達197MB

若減少隱藏層數是否能達到有效降低檔案大小的目標?

到移動性高但可能資源有限的輕量硬體使用,如行動裝置、或樹莓派的可能性?


 

 


後記:

這篇心得記錄是不斷反覆試錯 + 參考網友無私分享的教學文所摸索出來的心得。

 

 

當學習越多,越發覺得不足之處越多。

對於深度學習用的數學公式與理論,自慚資質駑鈍無法參透,只知如何使用。

因此這系列文僅記錄自己的開發/檢討/除錯的過程與思路邏輯,

並不打算描述太多程式的做法,畢竟只是野人獻曝罷了。

有需要的朋友們可自行至 Static Gesture Recognition @ Github 參考。

並希望這系列記錄也能提供給初心者的同好們,

作為一篇打造屬於你自己的影像辨識模型之基礎入門說明書,

若能在學習的路上對你有所幫助,我也感到非常榮幸。






Series link:

[DL]Static Gestures Recognition(1): Conception

[DL]Static Gestures Recognition(2): Solution finding

[DL]Static Gestures Recognition(3): Define workflow

[DL]Static Gestures Recognition(4): Preparing appropriate dataset

[DL]Static Gestures Recognition(5): Time is worth more than money

[DL]Static Gestures Recognition(6): Training Model & Next Step






[DL]Static Gestures Recognition(5): Time is worth more than money

從構想、規劃、試錯到完成深度學習的手勢辨識模型。




5關  進入訓練模型前的準備

資料準備好了,剩下是如何訓練一個真正可用的模型,訓練環境與某些必備條件很重要。

剛接觸入門的朋友們,沒有必要再多踩地雷,請參考以下建議。


<1> GPU

如果沒有GPU可用,請使用Google Colab+GPU訓練模型,或是其他有GPU的線上環境也可以 (just like AWS?)。 

關於Google Drive + Google Colab 可參考這裡

因為訓練模型是一個非常消耗硬體資源的行為,

光在本機靠CPU訓練所耗費測試的時間,就足夠好好睡上一覺+追劇+吃飯還綽綽有餘了,

而且同時還能隱約聽得到CPU正在發出100%全力運轉的悲鳴(?) 

所以,請務必想方設法找到擁有GPU的環境進行才有效率。



<2> Data Augmentation

這是我兒子,已當小天使


由於考慮到訓練資料的可能不足,我採用了資料擴增法(Data Augmentation)來進行處理,

Keras之中可以藉由設定ImageDataGenerator()來達到資料擴增,

而資料擴增此例又會需要使用到flow_from_dircectory()方式來讀取圖片

這裡有關於 Keras generators 講解用法:

訓練圖片的資料夾命名分類非常重要,請務必依照如下圖方式對應的標籤命名,



Class_id_name

id 是你要替這個分類的編號

name 是你替此分類的命名(不寫似乎也沒關係, 但有寫其實總是比較好辨識,btw 圖檔檔名沒有特別限制。)

例如,我在定義手勢類別的資料夾之中的命名方式是:

class_0_none

class_1_fist

class_2_iloveyou…. 

也請記住務必遵循規則,不要大小寫混雜,強烈建議   直接全部小寫!!

當初我沒有弄清楚也沒發現關鍵在這裡,

導致在測試後一直發現模型return 預測結果永遠都跟當初設定的不同。

光是這點又是N個小時的燒腦除錯...…(往事不堪回首)



<3> Create "zip" file, then upload

承上,要訓練的圖片資訊也一樣請先全部壓縮為zip後再上傳至Google Drive

因為訓練圖片可能是成千上萬的數量。

若不壓縮而是一張張上傳,Google Drive 處理的速度會讓你刻骨銘心......(?)



<4> Framework compatibility

務必要留意版本相容性,

Google Colab預設會採用最新版本的Keras & tensorflow

可是問題就出在不是最新的東西就最好,當初訓練過程時老是出現看不懂的錯誤訊息,

最後姑且一試,嘗試調整版本後才終於順利進行。

我採用的版本是Keras 2.3.1 & TensorFlow 2.2.0

在除錯過程中,不論是書或網路資源,我鮮少發現有特別提醒版本相容性,這坑實在……


關於環境相容性可參考這個清單 List of Available Environments



以上各種踩坑經驗談,

Hope you remember, Time is worth more than money!










[DL]Static Gestures Recognition(4): Preparing appropriate dataset

從構想、規劃、試錯到完成深度學習的手勢辨識模型。





4關 
準備資料<I>   Get dataset from Kaggle.

進行深度學習的過程中,尋找合適的訓練資料所耗費的成本並不亞於在學習的過程。


既然要很多圖片,從哪開始找呢?

我從 Kaggle 上找尋了關於手勢的圖片集

心想就先照著圖片分類來定義預測 0,1,2,3,4,5  的手勢吧!

依序照著流程處理,在jupyter lab 中看來測試時相當正常,但很快就發現失敗了…………

Why?

問題出在哪? 

 

 

讓機器訓練的圖片集(有雜訊背景),

但是實際上測試時卻是透過OpenCV取得的閾值畫面,這兩者根本不一樣!  

 (情境好比讓學生讀國文,但實際考題卻是考日文,雖然都是語言,但對機器來說這難以找出相同的特徵進行預測。)

再做一次嘗試,如果Kaggle來源圖片直接轉成閾值圖片去訓練呢?

在直接用圖片測試的過程中表現不錯,可是實際由Webcam擷取影像的過程依舊有問題。

奇怪?   

跟預期不同的地方在哪裡?




苦思許久,得出的結論是:

雖然是用現成的圖片集,但實際上機器預測所接收的圖片還是有落差,

圖片集已經先將手臂去背,僅留下手掌與手指;

但實際情境中,仍然有整隻手臂的圖像,訓練資料與現實生活中的影像有著明顯差異,極可能是失敗的主因

而且,我認為沒有必要透過影像處理非得將手腕以下的影像去除,

因為在手勢操作中,手臂也是手勢的一部份才合理。 

其次是這部分的程式我還不會寫XD 

與達成目標不見得有直接相關,評估目前太難兼無法確認效益的issue 沒有必要非去挑戰不可呀…… 其實是偷懶





準備資料<II>   Try again, capture the gesture by myself.


因為沒有辦法一次找到令人滿意的資料,所以我決定要重新錄製自己的手勢,

並同時參考網友做過類似的範例,發現確實有類似的成功案例,

既然有前例可循,也就代表自己所設想的主要方向沒錯。並設定條件如下:


● 用OpenCV拍照截圖 + 從Kaggle 找到適合的訓練圖,雙管齊下。

這裡自行取得圖片時,有將背景極簡化 + 並設定cv2.threshold()方法,

將訓練的內容盡可能的簡化,去除非必要的因素,採用灰階單色圖片。

再分別配置訓練training、驗證validation、測試test 等資料夾。


● 各個手勢應先定義有明確不同的形狀。

如果太過接近模稜兩可,以訓練圖片量不夠多的情況下,

我無法保證預測的效果是否可能令人滿意? 因此這個有疑點的因素需要先排除。


● 設定的手勢有沒有不符各國當地民情?  查了一下還真的有! 

大家習以為常的OK,居然在法國與比利時是罵人的意思,

發現幾乎不可能所有手勢都能夠在各地通用,大概只有 I LOVE YOU 是最沒問題的。

這9種手勢 出國亂比會出事




在這一階段,定義了以下5種手勢:


這裡先特別說明為什麼有none = 漆黑一片

因為在先前測試過程中,發現在沒有手勢進入ROI之前,

機器仍會將當下畫面判斷為一種結果,這可能導致預測將與真實偏離太遠。

而現階段目的是為了要先能確認透過CNN可以訓練辨識手勢,

因此先將無訊號也定義為一種輸入。


後話:

測試成功後,我參考 Gesture Jseter 定義的手勢,又再添加了兩種手勢,Straight & Thumb。

之所以增加新的手勢定義除了豐富性之外,也考慮到新增定義要與原本的手勢有明顯區別會比較好(免得增加誤判機率)。

本來也有想到 Star Trek 瓦肯人的問候手勢,但我實在比不出來!  只能放棄......這也是很講天份






Series link:

[DL]Static Gestures Recognition(1): Conception

[DL]Static Gestures Recognition(2): Solution finding

[DL]Static Gestures Recognition(3): Define workflow

[DL]Static Gestures Recognition(4): Preparing appropriate dataset

[DL]Static Gestures Recognition(5): Time is worth more than money

[DL]Static Gestures Recognition(6): Training Model & Next Step






[DL]Static Gestures Recognition(3): Define workflow

從構想、規劃、試錯到完成深度學習的手勢辨識模型。




3 深度學習 Detection & Recognition


除了將衡量範圍限縮到只有判斷手部外,

我們要將該區域的影像資訊傳給訓練過的CNN卷積神經網路模型,來辨識/預測結果(手勢)。

在進行之前,我們需要先理解影像偵測與識別是兩件事情   Detection & Recognition

舉例來說,圖片片中的人像、有車輛、有建築物,

Detection人物偵測能夠判斷,照片中可能有多少人,但無法分辨這些人是誰?

Recognition 是能夠指出,照片中的人是男、是女、進一步可能預測出年齡、姓名等資訊(如果背後的資料量足夠)







同樣地,以手勢辨識,如果畫面資訊中標記出手,那是偵測有沒有手或其他物件。

但手做出了甚麼動作,是OK? 還是比讚?,這行為叫做辨識 recognition






唯有先定義清楚問題,才能找出問題,往可能正確的方向邁進。

所以,我開始著手找尋資料,研究如何實現深度學習的圖像識別預測Recognition,

以達到最終專案的最終目標,有高度可靠性的手勢辨識模型。

經過第一個深度學習的Hello Wrold - MNIST的手寫數字辨識範例後,可參考網頁1網頁2

我瞭解到,就像玩遊戲的要去武器防具店購買裝備一樣,工具與知識都備齊了,才能繼續往下一關前進啊~




需要甚麼 & 做甚麼事情,工作流程

定義問題 Definition of Problem

     既然是手勢辨識,所以要準備關於手勢的圖片。


建立資料集 To build Dataset

     <1>很多的圖片,要有大量的資料讓機器去學習之間的差異。再將此切分為訓練、測試、驗證等區塊。

     <2>圖片對應的標籤,要告訴機器學習的圖片對應的答案(這裡稱為標籤),

先告訴機器答案,讓它去學習、去練習考題(在深度學習稱之為訓練training)。

回想學生時代不停考試+被老師用藤條激勵(X),鞭笞(O)大家奮發努力,

不停地練習題目,不停地背題型......機器一樣需要很多~很多~很多~的練習才能從中找到共同的特徵並記憶。


資料預處理 Data Preprocessing 

     圖片與標籤都必須要轉成神經網路模型能夠接受的格式才能進行訓練。


訓練模型 Training Model

     當資料備齊後,選擇合適的模型來訓練,不同的資料與問題有著不同的方式處理。

去比對預測結果與預定結果的落差,持續調整的過程中,落差應該要逐漸縮小,這個過程就是training.


 評估與驗證 Validation

     模型的輸入與輸出之間的關係,如準確率、損失函數(衡量模型的預測與真實不一致的程度有多少






Series link:

[DL]Static Gestures Recognition(1): Conception

[DL]Static Gestures Recognition(2): Solution finding

[DL]Static Gestures Recognition(3): Define workflow

[DL]Static Gestures Recognition(4): Preparing appropriate dataset

[DL]Static Gestures Recognition(5): Time is worth more than money

[DL]Static Gestures Recognition(6): Training Model & Next Step






[DL]Static Gestures Recognition(2): Solution finding

從構想、規劃、試錯到完成深度學習的手勢辨識模型。


2 – 最初的方向實驗


首先,我們必須先將判斷的區域限縮定義出ROI (Region Of Interest)

而不想因為其他的東西加入而造成影響判斷結果。

既然要辨識手勢,就應該先將圈選出手部區域,並去除之外不需要的部分。過多的背景資訊也是暫時不需要的。







發想/試錯/縮小目標範圍過程 - Using OpenCV 

 一開始從網路上找範例參考,使用 OpenCV 來檢測手部輪廓,

但發現光線因素將影響偵測結果的好壞,

如果沒有準確判斷出手部輪廓,且手指之間的凹點若沒有精準求出,並無法算出目前手勢中有伸出幾根指頭,

而且再複雜一點的手勢並無法用同一套演算法求得。


很快地我得出了結論,這並非是一個有效的解決方案。

必定要找更確實,能夠實現功能的方式。






接著,我回頭將最初的問題再思考 

如何讓手部的動作被電腦記住,並依據可靠的資訊判斷出正確手勢並給予回應?


答案是


影像偵測與辨識上已經有廣泛應用的

深度學習 

Deep Learning











[DL]Static Gestures Recognition(1): Conception

從構想、規劃、試錯到完成深度學習的手勢辨識模型。

 





第1關  – 構想


自從 Kinect & Leap Motion 出現後,

對於機器能夠辨識肢體動作或手勢的機制覺得很有趣。

儘管Kinect已經停產,Leap Motion在應用上仍有限制,目前在VR設備上的發展空間較多。

(還有幾乎沒有被人想起的Myo, 雷聲不大,雨點更小……)

 

 

人類手部、手指的靈活多變性仍是人機介面的直覺輸入工具。

例如手指在觸控平板上的直覺應用,現在是人們離不開的生活必備之物。

要求精準輸入,可以透過鍵盤、滑鼠、遊戲手把 等輸入介面,讓裝置接收到明確的指令。

相信這樣的概念仍會持續發展,

我也相信,未來ARVR設備最終仍需要可以解放雙手,才能更發揮其價值。

 

 

綜觀上述產品未能成功或延續其生命週期的原因,

-      沒有更適合的適用環境,導致熱度很快就消退,或被更新的產品取代。

-      為了要求精準的偵測,而不得不加上的諸多硬體條件與使用情境限制。

-      硬體的售價與占用的體積。

以上種種因素互相影響相乘,也因此形成了對一般用戶過高的門檻而無法普及的主因。

目前沒有非得一定要用到這些,而且又貴又佔空間,

Why do we need it?

 

 

讓我們想像未來可能在特定條件的使用情境:

當你在某些情況下找不到遙控器,如果你家的裝置可以辨別你的手勢,然後就能播放音樂、影片?  燈光開關?

手勢最直接讓人聯想到的應用就是手語,但不是每個人都能理解學習。若能藉由手勢辨識機制解讀,是否可能增進交流的機會呢?

裝置解讀連續的手勢訊息,而這組密碼只有你知道,可以當作家中大門的備用鑰匙方案嗎?

 


手勢辨識,基礎的條件應該要在甚麼樣的情境/環境下運作呢??

如果,可以降低使用硬體的門檻限制。

如果,在不便使用語音(吵雜環境)、不便裝設輸入裝置(空間限制沒有觸控螢幕),等情境下是否有發揮空間?

如果,能用簡單與相對平價的輸入裝置(如webcam),搭配運行程式的環境就能運作(避免上述提及高昂的硬體成本)。

當接收到影像時,便能根據影像資訊,判斷給予正確的回饋。

這一切是否有可能成真!?

 



 


 

Series link:

[DL]Static Gestures Recognition(1): Conception

[DL]Static Gestures Recognition(2): Solution finding

[DL]Static Gestures Recognition(3): Define workflow

[DL]Static Gestures Recognition(4): Preparing appropriate dataset

[DL]Static Gestures Recognition(5): Time is worth more than money

[DL]Static Gestures Recognition(6): Training Model & Next Step