成人av在线资源一区,亚洲av日韩av一区,欧美丰满熟妇乱XXXXX图片,狠狠做五月深爱婷婷伊人,桔子av一区二区三区,四虎国产精品永久在线网址,国产尤物精品人妻在线,中文字幕av一区二区三区欲色
    您正在使用IE低版瀏覽器,為了您的雷峰網賬號安全和更好的產品體驗,強烈建議使用更快更安全的瀏覽器
    此為臨時鏈接,僅用于文章預覽,將在時失效
    人工智能開發者 正文
    發私信給AI研習社
    發送

    0

    詳解如何用 LSTM 自動識別驗證碼

    本文作者: AI研習社 2017-06-19 16:41
    導語:還在為驗證碼糟心?

    雷鋒網按:本文作者 Slyne_D,原載于作者個人博客,雷鋒網已獲授權。

    這是去年博主心血來潮實現的一個小模型,現在把它總結一下。由于樓主比較懶,網上許多方法都需要切割圖片,但是樓主思索了一下感覺讓模型有多個輸出就可以了呀,沒必要一定要切割的吧?切不好還需要損失信息啊!本文比較簡單,只基于傳統的驗證碼。

    Part 0 模型概覽

    詳解如何用 LSTM 自動識別驗證碼

    從圖片到序列實際上就是Image2text也就是seq2seq的一種。encoder是Image, decoder是驗證碼序列。由于keras不支持傳統的在decoder部分每個cell輸出需要作為下一個rnn的cell的輸入(見下圖),所以我們這里把decoder部分的輸入用encoder(image)的最后一層復制N份作為decoder部分的每個cell的輸入。

    詳解如何用 LSTM 自動識別驗證碼

    典型的seq2seq

    詳解如何用 LSTM 自動識別驗證碼

    keras可以直接實現的image2text

    當然利用 recurrentshopseq2seq,我們也可以實現標準的seq2seq的網絡結構(后文會寫)。

    Part I 收集數據

    網上還是有一些數據集可以用的,包括dataCastle也舉辦過驗證碼識別的比賽,都有現成的標注好了的數據集。(然而難點是各種花式驗證碼啊,填字的,滑動的,還有那個基于語義的reCaptcha~)。

    因為我想弄出各種長度的驗證碼,所以我還是在github上下載了一個生成驗證碼的python包。

    下載后,按照例子生成驗證碼(包含26個小寫英文字母):

    #!/usr/bin/env python

    # -*- coding: utf-8

    from captcha.image import ImageCaptcha

    from random import sample


    image = ImageCaptcha() #fonts=[ "font/Xenotron.ttf"]

    characters =  list("abcdefghijklmnopqrstuvwxyz")


    def generate_data(digits_num, output, total):

        num = 0

        while(num<total):

            cur_cap = sample(characters, digits_num)

            cur_cap =''.join(cur_cap)

            _ = image.generate(cur_cap)

            image.write(cur_cap, output+cur_cap+".png")

            num += 1


    generate_data(4, "images/four_digit/", 10000)  #產生四個字符長度的驗證碼

    generate_data(5, "images/five_digit/", 10000) #產生五個字符長度的驗證碼

    generate_data(6, "images/six_digit/", 10000) #產生六個字符長度的驗證碼

    generate_data(7, "images/seven_digit/",10000) # 產生七個字符長度的驗證碼

    產生的驗證碼

    詳解如何用 LSTM 自動識別驗證碼詳解如何用 LSTM 自動識別驗證碼詳解如何用 LSTM 自動識別驗證碼

    (目測了一下生成驗證碼的包的代碼,發現主要是在x,y軸上做一些變換,加入一些噪音)

    Part II 預處理

    由于生成的圖片不是相同尺寸的,為了方便訓練我們需要轉換成相同尺寸的。另外由于驗證碼長度不同,我們需要在label上多加一個符號來表示這個序列的結束。

    處理之后的結果就是圖像size全部為Height=60, Width=250, Channel=3。label全部用字符id表示,并且末尾加上表示<EOF>的id。比如假設a-z的id為0-25,<EOF>的id為26,那么對于驗證碼"abdf"的label也就是[0,1,3,5,26,26,26,26],"abcdefg"的label為[0,1,2,3,4,5,6,26]。

    由于我們用的是categorical_crossentropy來判斷每個輸出的結果,所以對label我們還需要把其變成one-hot的形式,那么用Keras現成的工具to_categorical函數對上面的label做一下處理就可以了。比如abdf的label進一步轉換成:

    [[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],

    [0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],

    [0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],

    [0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],

    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],

    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],

    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],

    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1]]

    Part III 構建模型

    不借助外部包可以實現的模型

    def create_simpleCnnRnn(image_shape, max_caption_len,vocab_size):

        image_model = Sequential()

        # image_shape : C,W,H

        # input: 100x100 images with 3 channels -> (3, 100, 100) tensors.

        # this applies 32 convolution filters of size 3x3 each.

        image_model.add(Convolution2D(32, 3, 3, border_mode='valid', input_shape=image_shape))

        image_model.add(BatchNormalization())

        image_model.add(Activation('relu'))

        image_model.add(Convolution2D(32, 3, 3))

        image_model.add(BatchNormalization())

        image_model.add(Activation('relu'))

        image_model.add(MaxPooling2D(pool_size=(2, 2)))

        image_model.add(Dropout(0.25))

        image_model.add(Convolution2D(64, 3, 3, border_mode='valid'))

        image_model.add(BatchNormalization())

        image_model.add(Activation('relu'))

        image_model.add(Convolution2D(64, 3, 3))

        image_model.add(BatchNormalization())

        image_model.add(Activation('relu'))

        image_model.add(MaxPooling2D(pool_size=(2, 2)))

        image_model.add(Dropout(0.25))

        image_model.add(Flatten())

        # Note: Keras does automatic shape inference.

        image_model.add(Dense(128))

        image_model.add(RepeatVector(max_caption_len)) # 復制8份

        image_model.add(Bidirectional(GRU(output_dim=128, return_sequences=True)))

        image_model.add(TimeDistributed(Dense(vocab_size)))

        image_model.add(Activation('softmax'))

        sgd = SGD(lr=0.002, decay=1e-6, momentum=0.9, nesterov=True)

        image_model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])

        return image_model

    借助recurrentshop和seq2seq可以實現的結構

    def create_imgText(image_shape, max_caption_len,vocab_size):

        image_model = Sequential()

        # image_shape : C,W,H

        # input: 100x100 images with 3 channels -> (3, 100, 100) tensors.

        # this applies 32 convolution filters of size 3x3 each.

        image_model.add(Convolution2D(32, 3, 3, border_mode='valid', input_shape=image_shape))

        image_model.add(BatchNormalization())

        image_model.add(Activation('relu'))

        image_model.add(Convolution2D(32, 3, 3))

        image_model.add(BatchNormalization())

        image_model.add(Activation('relu'))

        image_model.add(MaxPooling2D(pool_size=(2, 2)))

        image_model.add(Dropout(0.25))

        image_model.add(Convolution2D(64, 3, 3, border_mode='valid'))

        image_model.add(BatchNormalization())

        image_model.add(Activation('relu'))

        image_model.add(Convolution2D(64, 3, 3))

        image_model.add(BatchNormalization())

        image_model.add(Activation('relu'))

        image_model.add(MaxPooling2D(pool_size=(2, 2)))

        image_model.add(Dropout(0.25))

        image_model.add(Flatten())

        # Note: Keras does automatic shape inference.

        image_model.add(Dense(128))

        image_model.add(RepeatVector(1)) # 為了兼容seq2seq,要多包一個[]

        #model = AttentionSeq2Seq(input_dim=128, input_length=1, hidden_dim=128, output_length=max_caption_len, output_dim=128, depth=2) 

        model = Seq2Seq(input_dim=128, input_length=1, hidden_dim=128, output_length=max_caption_len,

                                 output_dim=128, peek=True)

        image_model.add(model)

        image_model.add(TimeDistributed(Dense(vocab_size)))

        image_model.add(Activation('softmax'))

        image_model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])


        return image_model

    Part IV 模型訓練

    之前寫過固定長度的驗證碼的序列準確率可以達到99%,項目可以參考這里

    另外,我們在用Keras訓練的時候會有一個acc,這個acc是指的一個字符的準確率,并不是這一串序列的準確率。也就是說在可以預期的情況下,如果你的一個字符的準確率達到了99%,那么如果你的序列長度是5的時候,理論上你的序列準確率是0.99^5 = 0.95, 如果像我們一樣序列長度是7,則為0.99^8=0.923。

    所以當你要看到實際的驗證集上的準確率的時候,應該自己寫一個callback的類來評測,只有當序列中所有的字符都和label一樣才可以算正確。

    class ValidateAcc(Callback):

        def __init__(self, image_model, val_data, val_label, model_output):

            self.image_model = image_model

            self.val = val_data

            self.val_label = val_label

            self.model_output = model_output


        def on_epoch_end(self, epoch, logs={}):  # 每個epoch結束后會調用該方法

            print '\n———————————--------'

            self.image_model.load_weights(self.model_output+'weights.%02d.hdf5' % epoch)

            r = self.image_model.predict(val, verbose=0)

            y_predict = np.asarray([np.argmax(i, axis=1) for i in r])

            val_true = np.asarray([np.argmax(i, axis = 1) for i in self.val_label])

            length = len(y_predict) * 1.0

            correct = 0

            for (true,predict) in zip(val_true,y_predict):

                print true,predict

                if list(true) == list(predict):

                    correct += 1

            print "Validation set acc is: ", correct/length

            print '\n———————————--------'



    val_acc_check_pointer = ValidateAcc(image_model,val,val_label,model_output)

    記錄每個epoch的模型結果

    check_pointer = ModelCheckpoint(filepath=model_output + "weights.{epoch:02d}.hdf5")

    訓練

    image_model.fit(train, train_label,

                    shuffle=True, batch_size=16, nb_epoch=20, validation_split=0.2, callbacks=[check_pointer, val_acc_check_pointer])

    Part V 訓練結果

    在39866張生成的驗證碼上,27906張作為訓練,11960張作為驗證集。

    第一種模型:

    序列訓練了大約80輪,在驗證集上最高的準確率為0.9264, 但是很容易變化比如多跑一輪就可能變成0.7,主要原因還是因為預測的時候考慮的是整個序列而不是單個字符,只要有一個字符沒有預測準確整個序列就是錯誤的。

    第二種模型:

    第二個模型也就是上面的create_imgText,驗證集上的最高準確率差不多是0.9655(當然我沒有很仔細的去調參,感覺調的好的話兩個模型應該是差不多的,驗證集達到0.96之后相對穩定)。

    Part VI 其它

    看起來還是覺得keras實現簡單的模型會比較容易,稍微變形一點的模型就很糾結了,比較好的是基礎的模型用上其他包都可以實現。keras 2.0.x開始的版本跟1.0.x還是有些差異的,而且recurrentshop現在也是支持2.0版本的。如果在建模型的時候想更flexible一點的話,還是用tensorflow會比較好,可以調整的東西也比較多,那下一篇可以寫一下img2txt的tensorflow版本。

    Part VII 代碼

    完整源代碼:https://github.com/Slyne/CaptchaVariLength

    Part VIII 后續

    現在的這兩個模型還是需要指定最大的長度,后面有時間會在訓練集最多只有8個字符的情況下,利用rnn的最后一層進一步對于有9個以及以上字符的驗證碼效果,看看是不是可以再進一步的擴展到任意長度。(又立了一個flag~)

    雷鋒網相關閱讀:

    LSTM Networks 應用于股票市場探究

    一文詳解如何用 TensorFlow 實現基于 LSTM 的文本分類(附源碼)

    雷峰網版權文章,未經授權禁止轉載。詳情見轉載須知

    詳解如何用 LSTM 自動識別驗證碼

    分享:
    相關文章

    編輯

    聚焦數據科學,連接 AI 開發者。更多精彩內容,請訪問:yanxishe.com
    當月熱門文章
    最新文章
    請填寫申請人資料
    姓名
    電話
    郵箱
    微信號
    作品鏈接
    個人簡介
    為了您的賬戶安全,請驗證郵箱
    您的郵箱還未驗證,完成可獲20積分喲!
    請驗證您的郵箱
    立即驗證
    完善賬號信息
    您的賬號已經綁定,現在您可以設置密碼以方便用郵箱登錄
    立即設置 以后再說