這是《使用騰訊雲GPU學習深度學習》系列文章的第五篇,以車牌識别和簡單OCR為例,談了談如何進行字母、數字的識别以及定位。本系列文章主要介紹如何使用騰訊雲GPU伺服器進行深度學習運算,前面主要介紹原理部分,後期則以實踐為主。
往期内容:
使用騰訊雲 GPU 學習深度學習系列之一:傳統機器學習的回顧
使用騰訊雲 GPU 學習深度學習系列之二:Tensorflow 簡明原理
使用騰訊雲 GPU 學習深度學習系列之三:搭建深度神經網絡
使用騰訊雲 GPU 學習深度學習系列之四:深度學習的特征工
上一節,我們簡要介紹了一些與深度學習相關的資料預處理方法。其中我們特别提到,使用 基于深度學習的 Spatial Transform 方法,可以讓“草書” 字型的手寫數字同樣也可以被高效識别。
但無論是工整書寫的 Tensorflow 官網上的 MNIST 教程,還是上節提到“草書”數字,都是 單一的數字識别問題。 但是,在實際生活中,遇到數字、字母識别問題時,往往需要識别一組數字。這時候一個簡單的深度神經網絡可能就做不到了。本節内容,就是在讨論遇到這種情況時,應該如何調整深度學習模型。
固定長度的字元、數字識别,比較常見的應用場景包括:
識别驗證碼
識别機動車車牌
識别驗證碼的方法,這篇文章 有詳細介紹。不過該文章使用的是版本較早的 Keras1,實際使用時會有一些問題。如果想嘗試,根據Jupyter 的提示更改就好,最終效果也是相當不錯:
我們這裡要識别的内容,是中華人民共和國機動車車牌。相比上面例子的 4 位驗證碼,車牌長度更長,達到了 7 位,并且内容也更加豐富,第一位是各省的漢字簡稱,第二位是 A-Z 的大寫字母,3-7位則是數字、字母混合。
由于車牌涉及個人隐私,我們使用了使用者 szad670401 在 Github 上開源的一個車牌生成器,随機的生成一些車牌的圖檔,用于模型訓練。當然這個項目同樣提供了完整的 <code>MXNet</code> 深度學習架構編寫的代碼,我們接下來會用 <code>Keras</code> 再寫一個。
首先做些準備工作,從 szad670401 的開源項目中擷取必要的檔案:
來看看生成器的效果:
看來 szad670401 開源的車牌生成器,随機生成的車牌确實達到了以假亂真的效果。于是我們基于這個生成器,再自己寫一個生成器,用于深度神經網絡的資料輸入:
因為是固定長度,是以我們有個想法,就是既然我們知道識别七次,那就可以用七個模型按照順序識别。這個思路沒有問題,但實際上根據之前卷積神經網絡的原理,實際上卷積神經網絡在掃描整張圖檔的過程中,已經對整個圖像的内容以及相對位置關系有所了解,是以,七個模型的卷積層實際上是可以共享的。我們實際上可以用一個 一組卷積層+7個全連結層 的架構,來對應輸入的車牌圖檔:
訓練模型:
可見五輪訓練後,即便是位置靠後的幾位車牌,也實作了 93% 的識别準确率。
展示下模型預測結果:
可見預測的其實相當不錯,很多字型已經非常模糊,模型仍然可以看出來。圖中一個錯誤是 皖TQZ680 被預測成了 皖TQZG8D,當然這也和圖檔裁剪不當有一定的關系。
車牌的應用場景中,我們固定了長度為7位,并且基于這個預設設計了卷積神經網絡。但是在實際運用中,可能長度并不固定。此時如果長度過長,用這個架構也将會導緻參數過多,占用過多顯存。
針對這種情況,Keras 的案例中,提供了一種基于循環神經網絡的方法,在 Keras Example 中有寫到。具體而言,就是資料首先通過卷積神經網絡部分掃描特征,然後通過循環神經網絡部分,同時從左到右、從右到左掃描特征,最後基于掃描的結果,通過計算 Conectionist Temporal Classification(CTC) 損失函數,完成模型訓練。
使用循環神經網絡,是因為循環神經網絡有一個很重要的特點,就是相鄰的節點之間,可以互相影響。這裡相鄰節點,既可以是時間上的(前一秒資料和後一秒資料),也可以是位置關系上的,比如我們這裡從左向右掃描,左邊一列的掃描結果會影響右邊一列的掃描結果。
圖檔來源:知乎:CNN(卷積神經網絡)、RNN(循環神經網絡)、DNN(深度神經網絡)的内部網絡結構有什麼差別。
同時,對于循環神經網絡的結果,由于長度不固定,可能會有空間上的“錯配”:
圖檔來源:Connectionist Temporal Classification: Labelling Unsegmented Sequence Data with Recurrent Neural Networks
但由于這種錯配實際上并沒有什麼嚴重的影響,如上圖所示, <code>__TH____E</code> 和 <code>_T__H__EE</code> 其實都是 THE 這個單詞,是以這裡這種錯配在損失函數的優化環節中,是需要被忽略掉的。于是這裡就使用了<code>CTC</code> 優化函數。<code>CTC</code> 可以在計算過程中,通過綜合所有可能情況的排列組合,進而忽略相對的位置關系。
Keras 的 CTC loss 函數位于 https://github.com/fchollet/keras/blob/master/keras/backend/tensorflow_backend.py 這個檔案中,内容如下:
首先是一些必要的函數:
必要的參數:
使用這些函數以及對應參數建構生成器,生成不固定長度的驗證碼:
建構網絡:
模型完整架構如下圖所示:
執行訓練:
完成一個 Epoch 後,輸出檔案夾 <code>image_ocr</code> 裡,可以看到,一輪訓練後,我們模型訓練效果如下: