CNN識別學庫bao的驗證碼

前言

  • 背景
    最近在看深度學習相關知識,正好手上一個爬蟲外包有個需求:爬取 學庫bao的全站數據。官方傳言題目有一千多萬道,其中每道題要查看答案和解析,都需要識別驗證碼(數字+字母,四個字符)。一般的,打碼平臺一塊錢可以識別200張,算下來得要5萬的打碼費用,還沒算失敗率。

  • 圖片示例
    驗證碼示例1      驗證碼示例2    驗證碼示例3    驗證碼示例4

  • 參考
    本文參考了《CNN破解簡單驗證碼(Tensorflow實現)》。網上一搜”驗證碼 CNN”,大部分都是類似的文章,用captcha模塊生成驗證碼進行訓練、識別,甚至代碼都是一樣的,真沒意思。後來發現51CTO視頻課程裏也有講這個案例,我把它上傳到雲盤了(鏈接: https://pan.baidu.com/s/1iuMfSlWyTm8SbxHYeDoBSQ 密碼: shjm),感覺視頻裏的講解比其他博客詳細多了。

  • 代碼
    GitHub地址:cnn_on_captchacaptcha_identify

  • 正確率
    訓練樣本6500,測試樣本500,識別率達92.4%。

以往的,識別驗證碼的流程一般是先去噪,再切割,然後用最近鄰去分類識別。但是去噪和切割這兩個步驟,經常都不那麼好做。而CNN不需要去噪和切割,直接整張驗證碼拿去訓練和識別。不用做針對性的去噪和切割,可以省去很大工作量。



正文

採集樣本

CNN識別驗證碼有優點也有不足,它其中的一個缺陷就是需要更多的樣本做訓練。文章《識別扭曲干擾性驗證碼》中提到94%的識別率需要400W張圖片,不知真假,但確實嚇人。
驗證碼識別率
難怪網上一搜”CNN 驗證碼識別”,出來的全都是用captcha模塊生成的驗證碼做訓練,敢情他們是找不到訓練樣本呀。

然而我的任務是識別學庫bao的驗證碼,就算不能收集這麼多的驗證碼,也要試一試。採集驗證碼的流程是下載驗證碼 —> 打碼平臺打碼 —> 返回給學庫bao判別正誤。有些博客說人工識別並標註驗證碼,有些原始,我用的是雲打碼,採集了7000張驗證碼,費用還不到40元,何苦爲難自己。另外,打碼平臺識別的結果並不一定百分百正確,必須返回給原網站,根據反饋判斷識別正誤。

採集驗證碼圖片的代碼:crawl_captcha.py,如果要採集其他網站的驗證碼,稍加修改即可。
(圖片可以自行跑上面的代碼採集,我將我採集到的放在雲盤了,可以拿來直接用,鏈接: https://pan.baidu.com/s/18i2xoGth8INChhCWfROZpw 密碼: vrew 。如果百度網盤失效就用新浪微盤:http://vdisk.weibo.com/lc/3AO6EQDinZjxwfeVbuZ 密碼:L70M)


訓練和測試

模型的訓練和測試,這個沒什麼好說的,CSDN上一搜,千篇一律。我這裏只是將圖片源換成了本地採集好的驗證碼,代碼中調一下圖片大小。


嘗試和改進

嗯,好玩的在這裏。無知的初學者,瞎搗鼓系列。
(注意,要先把訓練樣本和測試樣本(captchas文件夾和test文件夾)放到項目目錄。除了captcha01,其他都要先運行crop_captcha.py將圖片切割成單字符,再進行訓練。)

  1. 初版本
    代碼:captcha01
    最初,6500張圖片,不做任何處理,每次隨機抽取64張,訓練2W批次。耗時80分鐘,準確率3.4%,低的可憐,不忍直視。

  2. 切割
    代碼:captcha02
    看來這點數據量,基本上是沒法直接訓練了。網絡模型還沒能學習到驗證碼的特徵,那我們就清除一些無用的雜質和邊緣,將更清楚、更精準的樣本餵給它。去噪我是不想做的,但切割還是比較容易的,把四個字符單獨切割出來,把不必要的圖片邊緣清除掉。這樣可以很大程度地降低模型學習的壓力,而且樣本量也變成原來的四倍了。
    a2    b1    c    d    e    f    g     h    i    j    k
    切割以後總共2.6萬張圖,訓練2W批次,耗時23分鐘,準確率82.2%(四個字符同時正確)。這準確率立馬上來了,基本上可以拿來用了。
    (注:因打碼平臺經常將大小寫忽略,故訓練的時候將全部大寫字母作小寫看待。)

  3. 除去pooling層
    代碼:captcha03
    切割後的圖片大小爲6*18,字符已經精細到1個像素上去了,已經不能再縮減了。而pooling層很重要的一個作用就是在保留主要特徵的同時降低參數(緯度)和計算量,此時這個作用並不大,所以可以考慮把pooling層去掉。
    這裏寫圖片描述     這裏寫圖片描述    這裏寫圖片描述    這裏寫圖片描述
    訓練2W批次,耗時37分鐘,準確率89.2%

  4. 新增一層網絡
    代碼:captcha04
    驗證碼的識別,一般的選擇三層卷積就已經有比較好的效果,但我還是好奇四層卷積,識別率將會升降多少。
    訓練2W批次,耗時44分鐘,準確率91.2%
    訓練6W批次,耗時135分鐘,準確率91.6%

  5. 將第三層的厚度64變成128
    代碼:captcha05
    訓練2W批次,耗時53分鐘,準確率88.8%
    訓練6W批次,耗時207分鐘,準確率92.4%


開啓驗證碼識別服務

好了,模型已經訓練好了。接下來就是使用了。我使用了Django開了一個服務,需要識別驗證碼的時候只需將驗證碼post過去就能返回識別結果了。代碼:captcha_identify
啓動命令:python manage.py runserver 127.0.0.1:8000

在爬蟲中,只需要調用下面的方法即可。

def identify(filename):
    try:
        r = requests.post('http://127.0.0.1:8000/captcha_identify/', files={'image': (filename, open(filename, 'rb'), 'image/png')})
        return r.content
    except Exception as e:
        return ''



結語

92.4%的識別率,這已經算比較高了,畢竟訓練樣本才這麼些。而且識別率跟噪聲有關,這個網站有些驗證碼的噪聲線條,已經讓字符完全無法識別了。所以識別率提高到一定程度就很難再提高了。
無法識別1    無法識別2    無法識別3    無法識別4

一年多沒寫文章了,有點生疏。本文借鑑captcha驗證碼的識別案例,記錄識別學庫bao驗證碼的過程,目的是總結和分享,學藝不精,純屬搗鼓,錯誤之處各位多批評指出。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章