python使用深度神經網絡實現識別暹羅與英短
先來上兩張圖看看那種貓是暹羅?那種貓是英短?
第一張暹羅
第二張英短
你以后是不是可以識別了暹羅和英短了?大概能,好像又不能。這是因為素材太少了,我們看這兩張圖能分別提取出來短特征太少了。那如果我們暹羅短放100張圖,英短放100張圖給大家參考,再給一張暹羅或者英短短照片是不是就能識別出來是那種貓了,即使不能完全認出來,是不是也有90%可能是可以猜猜對。那么如果提供500張暹羅500張英短短圖片呢,是不是猜對的概率可以更高?
我們是怎么識別暹羅和英短的呢?當然是先歸納兩種貓的特征如面部顏色分布、眼睛的顏色等等,當再有一張要識別短圖片時,我們就看看面部顏色分布、眼睛顏色是不是可暹羅的特征一致。
同樣把識別暹羅和英短的方法教給計算機后,是不是計算機也可以識別這兩種貓?
那么計算機是怎么識別圖像的呢?先來看一下計算機是怎么存儲圖像的。
圖像在計算機里是一堆按順序排列的數字,1到255,這是一個只有黑白色的圖,但是顏色千變萬化離不開三原色——紅綠藍。
這樣,一張圖片在計算機里就是一個長方體!depth為3的長方體。每一層都是1到255的數字。
讓計算機識別圖片,就要先讓計算機了解它要識別短圖片有那些特征。提取圖片中的特征就是識別圖片要做的主要工作。
下面就該主角出場了,卷及神經網絡(Convolutional Neural Network, CNN).
最簡單的卷積神經網絡就長下面的樣子。
分為輸入、卷積層、池化層(采樣層)、全連接和輸出。每一層都將最重要的識別信息進行壓縮,并傳導至下一層。
卷積層:幫助提取特征,越深(層數多)的卷積神經網絡會提取越具體的特征,越淺的網絡提取越淺顯的特征。
池化層:減少圖片的分辨率,減少特征映射。
全連接:扁平化圖片特征,將圖片當成數組,并將像素值當作預測圖像中數值的特征。
?卷積層
卷積層從圖片中提取特征,圖片在計算機中就上按我們上面說的格式存儲的(長方體),先取一層提取特征,怎么提???使用卷積核(權值)。做如下短操作:
觀察左右兩個矩陣,矩陣大小從6×6 變成了 4×4,但數字的大小分布好像還是一致的??聪抡鎸崍D片:
圖片好像變模糊了,但這兩個圖片大小沒變是怎么回事呢?其實是用了如下的方式:same padding
在6×6的矩陣周圍加了一圈0,再做卷積的時候得到的還是一個6×6的矩陣,為什么加一圈0這個和卷積核大小、步長和邊界有關。自己算吧。
上面是在一個6×6的矩陣上使用3X3的矩陣做的演示。在真實的圖片上做卷積是什么樣的呢?如下圖:
對一個32x32x3的圖使用10個5x5x3的filter做卷積得到一個28x28x10的激活圖(激活圖是卷積層的輸出).
?池化層
減少圖片的分辨率,減少特征映射。怎么減少的呢?
池化在每一個縱深維度上獨自完成,因此圖像的縱深保持不變。池化層的最常見形式是最大池化。
可以看到圖像明顯的變小了。如圖:
在激活圖的每一層的二維矩陣上按2×2提取最大值得到新的圖。真實效果如下:
隨著卷積層和池化層的增加,對應濾波器檢測的特征就更加復雜。隨著累積,就可以檢測越來越復雜的特征。這里還有一個卷積核優化的問題,多次訓練優化卷積核。
下面使用apple的卷積神經網絡框架TuriCreate實現區分暹羅和英短。(先說一下我是在win10下裝的熬夜把電腦重裝了不下3次,系統要有wls,不要用企業版,mac系統和ubuntu系統下安裝turicreae比較方便)
首先準備訓練用圖片暹羅50張,英短50長。測試用圖片10張。
上代碼:(開發工具anaconda,python 2.7)
數據放到了h盤image目錄下,我是在win10下裝的ubuntu,所以h盤掛在mnt/下。
test的文件:(x指暹羅,y指英短,這樣命名是為了代碼里給測試圖片區分貓咪類型)
test_data[‘label’] = test_data[‘path’].apply(lambda path: ‘xianluo’ if ‘x’ in path else ‘yingduan’)
第一次結果如下:
訓練精度0.955 驗證精度才0.75 正確率才0.5。好吧,看來是學習得太少,得上三年高考五年模擬版,將暹羅和英短的圖片都增加到100張。在看結果。
這次訓練精度就達到0.987了,驗證精度1.0,正確率1.0 牛逼了。
看下turicreate識別的結果:
我們實際圖片上貓是:(紅色為真實的貓的類型-在代碼里根據圖片名稱標記的,綠色為識別出來的貓的類型)
可以看到兩者是一致的。牛逼了訓練數據才兩百張圖片,就可以達到這種效果。