最近主管突然想要大家識別某種生活物品,然後大家就卯起來幹了。
第一坑:數據少
一開始的問題是樣本極少,第一天還不到10張,之後也可預見的不好蒐集,所以其他人一頭熱用 YOLO 之類的演算法同時,我評估深度學習不是好方法。越老舊的方法雖然上限越低,但可解釋性比較好,一般來說需要的數據量比較少。
都用一些比較傳統的方法,一開始先用 Cascade(就是 Viola–Jones 那個)
第二坑:老演算法被新版棄用
這裡就來了第一個大坑,OpenCV 4.X 已經拿掉了 Cascade 相關的東西,網路上一找可以看到很多人抱怨,當然抱怨大本營是 Github issue,官方建議大家改用 DNN,但還是很多人想要用復古的東西。
好吧,我只好降低版本到 3.X,這連帶讓我找適合的 docker image 基底都變得困難(因為編譯 OpenCV 太久,不能每次都編譯),還好最後還是找到了。
然後隨著樣本增加到幾百個,效果也不是很好。中間還做了哪些努力?因為我自己的 MacBook Air 很慢,所以花了很多時間寫 Dockerfile 還有一些部署相關的 bash,讓計算可以在公司的服務器上跑。但 docker build 與 debug 還是吃自己電腦上的算力,電腦不夠快的影響還是有。
後來覺得為了 debug 而 docker build 的次數太多了、太浪費時間,所以決定:
- Dockerfile 只做 apt install 或 pip install 之類的事,所有的程式碼、數據全都用 mount 的。
- 所有的流程都寫在 docker run 最後面的指令(/bin/bash -c “…”)
- docker image、程式碼、數據集,各用一個 bash deploy 到 GPU server。
第三坑:用錯特徵
後來我就發現,預設的特徵擷取法是 Haar,那個是針對人臉的明暗變化擷取特徵,不太適合現在的檢測目標。另外兩種可選特徵是 LBP 與 HoG,這兩種我都在寫論文或寫作業自乾過了,HoG 應該是最佳選擇。理論上,這只要改個參數就可以看到辨識率爆炸性的推進了吧?我以為看到了一條很棒的近路。
第四坑:適合的特徵又被 Python 版棄用
結果發現 OpenCV 3.X 可以訓練基於 HoG 的 Cascade 模型,但是卻不能 load 基於 HoG 的 XML model?必須要 2.X 才能,那我就再度降低版本到 2.X 吧!這次更慘,發現沒得降低了,因為 Python 的 OpenCV 最低就是從 3.X 開始,如果降低到 OpenCV 2.X 那從 load XML model 以後的所有事情我都要用 CPP 寫,太累了!
https://github.com/shimat/opencvsharp/issues/1022
搜一下發現很多人用 HoG + SVM 的組合做目標檢測,尤其行人與車輛,感覺還蠻適合現在的目標。發現用的函式庫有兩大派別,老的 OpenCV 與新的 scikit-image。
第五坑:造好的輪子還是要自己補胎
然後就找一下 Github 現成的輪子,發現有一個看起來寫得不錯、夠規整、文件夠清楚,有把一些設定獨立在 config.cfg。clone 下來之後發現是除了 Python2 之外,還有一些錯字、一些API過時了,改了將近一天才跑起來。
跑起來之後有坑啊,一直跑出「array has an inhomogeneous shape after 1 dimensions.」,原來是我的訓練圖片大小都不一樣,沒有經過正規化。給模型的所有數據維度都要一樣大,這其實應該是個機器學習常識才對,甚至也是統計常識,只是現成的工具太方便了,習慣都被養壞了。
接下又要繼續解這個不是坑的坑…(待續)
(還有一些數據視覺化的坑沒寫,不過我懶了,下次再寫)