類vgg網絡實現端到端識別驗證碼

項目起因

大二在做weibo爬蟲抓取用於情感分析語料時遇到了模擬登陸的問題,其中關鍵的一環就是驗證碼識別。由於當時專業知識有限選擇了對接打碼平臺來解決這個痛點,在時間不充分情況下這是效率最高的方法。但這也在我心中埋下了一個小小的種子。大二暑假在校同肖老師一同學習深度學習課程後,抱着學習的態度我把weibo驗證碼識別做爲了我的軟件工程課設題目同時也是我的第一個深度學習實戰項目。

爲什麼採用端到端的方式

驗證碼的作用就是幫助網站過濾掉一部分惡意的流量,所以驗證中加入了很多對字符的干擾例如粘連,空心, 加入背景,扭曲,旋轉等。微博的驗證碼採用了空心和粘連的干擾方法,使用常規的分割算法驗證碼很難被有效的分割。採用端到端識別的方式避免了分割圖像,經過簡單的灰度處理後直接對原圖像提取特徵進行識別。
微博驗證碼例圖

數據集和訓練結果

由於數據集的特殊性目前網上沒有找到公開的數據集,由於微博驗證碼字符采用大小寫區分的方式而且一般的打碼平臺只提供大小寫的不區分的打碼服務(他們的後臺用的是人工打碼,即使提供打碼服務可靠性也不高,你需要把圖片上標註大小寫區分工人看到了纔會給你按照要求打碼而且大部分工人來着網賺平臺一般不會按照要求==)。 在一番苦苦搜尋無果後決定手動標驗證碼,這樣數據集的質量也有保證。
目前的訓練集大小是5000,由於數據獲取困難我把絕大部分數據用來做訓練集了只留了很小一部分用作驗證集,模型訓練結束的準確率在91%左右,但實際準確率應該比這個低,模型在新抓取的驗證碼上表現如下:
在這裏插入圖片描述

模型搭建

卷積與maxpooling

對卷積與maxpooling操作的個人理解:
由數據驅動的卷積神經網絡在訓練過程中逐層抽取到到由簡單到複雜的特徵。
在這裏插入圖片描述
Maxpooling層與卷積的操作方式類似但作用不同,Maxpooing在每個小塊內只取最大的值捨棄其他節點後,保持原有的平面結構得到輸出。經過卷積後得到的數值可以理解爲隱層特徵,pooling的作用就是從這些特徵中保留影響最大的(類似PCA),所以說pooling的一個重要作用就是降維。
在這裏插入圖片描述

Dropout

在網絡結構過深時由於參數過多容易出現過擬和,dropou在深度學習網絡的訓練過程中,對於神經網絡單元,按照一定的概率將其暫時從網絡中隨機丟棄由於只時暫時丟棄,故而相當於每一個mini-batch都在訓練不同的網絡,從而·
Dropout

輸出頭

由於微博驗證碼採用的是五位字符,模型的輸出頭部採用了五個獨立的Dense激活後再拼接而沒有直接採用全連接,這樣能大幅降低參數數量同時每個分支能學習到獨立的識別特定位置的參數,這是端到端模型的關鍵。
在這裏插入圖片描述

由於代碼過長這裏只放部分模型搭建的關鍵代碼:

class VGGNet(object):
    @staticmethod
    def conv_module(x, filters, cha_dim, l2_rate, name=None)
        conv_name, bn_name = None, Non
        if name is not None:
            conv_name = name + "_conv"
            bn_name = name + "_bn
        x = Conv2D(filters, (3, 3), kernel_regularizer=l2(l2_rate), activation='relu', padding='same',
                   name=conv_name)(x)
        x = BatchNormalization(axis=cha_dim, name=bn_name)(x)
        return x

    @staticmethod
    def build(width, height, depth, conv_nums, filters, l2_rate)
        input_shape = height, width, depth
        chan_dim = -1
        if K.image_data_format() == 'channels_first':
            input_shape = depth, height, width
            chan_dim = 1

        input_image = Input(shape=input_shape)
        layer = input_image
        for block, (conv_num, filter) in enumerate(zip(conv_nums, filters)):
            for stage in range(conv_num):
                layer = VGGNet.conv_module(layer, filter, chan_dim, l2_rate,
                                           name='block_{0}_stage_{1}'.format(block, stage))
            if block == len(conv_nums) - 1:
                layer = GlobalAveragePooling2D(K.image_data_format())(layer)
                layer = Dropout(rate=0.5)(layer)
            else:
                layer = MaxPooling2D(pool_size=(2, 2))(layer)
                layer = Dropout(rate=0.25)(layer)

        # outputs
        model = Model(inputs=input_image, outputs=layer)
        return mode

另外我還嘗試實現了ResNet用同樣的數據集訓練,得到的結果與vgg相差無幾。個人覺得對於這種簡單的圖像處理問題模型的優勢並不能很明顯的體現應該以數據爲王道,如果在現有的5000個圖像的基礎上加大訓練集能該能得到更效果。

運行環境

操作系統:windows x64 8g內存
顯卡:GTX1050
keras:2.24
tensorflow:1.12
python:3.6.9

使用gpu加速的化大概十幾分鍾就能train完,效率還是挺高的,感覺第二代圖形驗證碼在防爬蟲方面越來越喫力了,急需新型對抗驗證碼。

結語

第一次實戰深度學習,經過不斷努力終於做出了我想要的東西,自己已經滿足了hhh

道阻且長 行則將至 行而不輟 未來可期

本文內容僅提供用於學習交流,如有侵權請聯繫[email protected]刪除

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