SVHN的Keras實現
SVHN是街景數字的資料集,Google在2013年發表的論文“ Multi-digit Number Recognition from Street View Imagery using Deep Convolutional Neural Networks ”提供瞭解決方法,並聲稱該方法可以破解所有的驗證碼。
本篇部落格將簡要的總結這篇論文,並使用Keras實現模型並訓練SVHN資料集。
這篇文章的方法主要作為訓練SVHN資料集的一個baseline。作者說他的方法能達到百分之96以上的準確率。
任務要求
這裡先看一下資料集的樣子,其實也就是Number from Street View(街景數字)。

過去的做法
Traditional approaches to solve this problem typically separate out the localization, segmentation, and recognition steps.(過去的做法要經歷三步:定位,分割,然後識別)
作者的做法
Propose a unified approach that integrates these three steps via the use of a deep convolutional neural network that operates directly on the image pixels.(作者把這三個步驟通過一個深度的卷積網路就能完成)
作者的貢獻
- (a) A unified model to localize, segment, and recognize multi-digit numbers from street level photographs
- (b) A new kind of output layer, providing a conditional probabilistic model of sequences
- (c) Empirical results that show this model performing best with a deep architecture
- (d) Reaching human level performance at specific operating thresholds.
問題描述
圖片中的數字:每張圖片的數字是一個字串序列: ,如上面的第一張圖片結果為"379", 。
字元的長度:定義為n,絕大多數的長度小於5。作者這裡假設字元的長度最大為5。
實現方法
作者的方法是對於圖片的label,訓練一個概率模型。這裡作者定義:
- S:輸出序列,也就是訓練資料的label。
- X:輸入的圖片。
這裡的目標也就是通過最大化 ,來學習模型 。
X其實就是輸入的圖片,這裡看一下S,S是:圖片的數字序列 + 數字序列的長度 的一個集合。比如上面的"379"是圖片的數字序列,序列的長度len("379")為3。那麼S就是"3"+"379",也就是"3379"。
這裡 可以定義為:字元長度的概率再乘以每個字元取值的概率。(每個字元取值是獨立的)。
上面的變數都是離散的, 的取值有七種:0,1,2,....,5,比5大; 有10種:10個數字。
訓練這個模型,就是在訓練集上最大化 ,作者這裡每個引數都使用一個Softmax層。
模型結構
下面,看下作者在論文裡面發表的模型。

- 輸入圖片 是一個128x128x3的圖片。
- 然後經過一系列的CNN層進行特徵提取,變成了一個含有4096個特徵的向量。
- 之後根據這4096個特徵,分別讓 、 、 、 、 、 分別經過一個Softmax層 。
- 對於每個變數,
Keras的實現
程式碼見: ofollow,noindex">github.com/nladuo/ml-s…
環境依賴
- python 3.x
- TensorFlow 1.11
- Keras 2.x
- Pillow
- h5py
資料下載
首先去 ufldl.stanford.edu/housenumber… 下載 Format 1 的資料。
wget http://ufldl.stanford.edu/housenumbers/test.tar.gz wget http://ufldl.stanford.edu/housenumbers/train.tar.gz 複製程式碼
然後對資料進行解壓,解壓後發現會多兩個資料夾:test和train。
tar zvxf test.tar.gz tar zvxf train.tar.gz 複製程式碼
構建資料集
這個資料集可以使用h5py讀取。

其中bbox存了圖片數字的框,而name則是圖片的檔名。比如說讀取出來是下面這樣的圖片:

然後通過框框把圖片裁剪一下。

網路模型
網路模型這裡分為卷積層+全連線層部分,程式碼如下。

卷積層
這裡就是三個卷積層。為了讓神經網路接受了引數符合同一分佈,這裡使用了Batch Normalization層,對ConvNet的輸入進行 批歸一化 。
全連線層
卷積層最後經過Flatten之後,進入了全連線層。全連線層最後,輸出了到6個softmax層中,分別代表:字元的長度、第一個字元、第二個字元、第三個字元、第四個字元、第四個字元。
注意:這裡字元的類別是0-10,一共11種,10代表不存在。
訓練與測試
接下來呼叫fit方法訓練就好了,這裡一共有7個loss和6個accuracy。loss的話是每個softmax輸出層都有一個,還有個總的。accuracy就是6個softmax層的accuracy了。

最後我們evaluate一下,可以6個accuracy都達到了85%以上的準確率了。如果想提高的話,可以使用VGG16等結構,網上說可以提升到百分之97,不過訓練的話估計就要很慢了。

擴充套件案例:微博驗證碼
另外,筆者這裡還使用該方法給出了新浪微博的登入驗證碼識別的實現程式碼,見: captcha-break/weibo.com 。
不過不知道現在新浪微博的驗證碼變了沒有,我當時用雲打碼的時候它的驗證碼長下面這個樣子:
