在學(xué)習(xí)了 CNN 之后,我一直想去做一個(gè)驗(yàn)證碼識(shí)別。網(wǎng)上找了很多資料,雜七雜八的一大堆,但是好多是 tf1 寫(xiě)的。我對(duì) tf1 不太熟悉,于是自己開(kāi)始了基于 TensorFlow 2 的摸索實(shí)踐。
摸索的過(guò)程異常艱難,一開(kāi)始我直接用 captcha 生成了 10080 張驗(yàn)證碼去識(shí)別,發(fā)現(xiàn) loss 一直停留在 2.3 左右,accuracy 一直是 0.1 左右,訓(xùn)練了 100 回合,也沒(méi)什么提升,電腦都快要跑廢了,咋辦呀?于是網(wǎng)上各種問(wèn)大佬,找到機(jī)會(huì)就提問(wèn),其中一位大佬的回答讓我受到了啟發(fā),他說(shuō):你可以先識(shí)別 1 位,然后 2 位,3 位,最后 4 位,一步一步來(lái)……。
本文主要描述我在驗(yàn)證碼識(shí)別過(guò)程中的一些摸索,整理出來(lái)以供大家參考:
第一回:搭建網(wǎng)絡(luò)結(jié)構(gòu)
首先我們需要搭建網(wǎng)絡(luò)結(jié)構(gòu),如下:
model=tf.keras.models.Sequential([ tf.keras.Input(shape=(H, W, C)), layers.Conv2D(32, 3, activation='relu'), layers.MaxPooling2D((2, 2)), layers.Conv2D(64, 3, activation='relu'), layers.MaxPooling2D((2, 2)), layers.Conv2D(64, 3, activation='relu'), layers.MaxPooling2D((2, 2)), layers.Conv2D(64, 3, activation='relu'), layers.MaxPooling2D((2, 2)), layers.Conv2D(64, 3, activation='relu'), layers.MaxPooling2D((2, 2)), layers.Flatten(), layers.Dense(1024, activation='relu'), layers.Dense(D * N_LABELS, activation='softmax'), layers.Reshape((D, N_LABELS)), ]) model.compile(optimizer='adam', loss='categorical_crossentropy', metrics= ['accuracy']) callbacks=[ tf.keras.callbacks.TensorBoard(log_dir='logs'), tf.keras.callbacks.ModelCheckpoint(filepath=check_point_path, save_weights_only=True, save_best_only=True) ] history = model.fit(train_gen, steps_per_epoch=len(train_idx)//batch_size, epochs=100, callbacks=callbacks, validation_data=valid_gen, validation_steps=len(valid_idx)//valid_batch_size)
summary:

我的訓(xùn)練數(shù)據(jù)量:train count: 7408, valid count: 3176, test count: 4536
樣本圖:
訓(xùn)練結(jié)果:
Train for 231 steps, validate for 99 steps Epoch 1/100 1/231 […] - ETA: 4:18 - loss: 2.2984 - accuracy: 0.1328 231/231 [==============================] - 143s 618ms/step - loss: 2.3032 - accuracy: 0.0971 - val_loss: 2.3029 - val_accuracy: 0.0987 Epoch 2/100 230/231 [============================>.] - ETA: 0s - loss: 2.3026 - accuracy: 0.1014 231/231 [==============================] - 121s 525ms/step - loss: 2.3026 - accuracy: 0.1013 - val_loss: 2.3031 - val_accuracy: 0.0986 Epoch 3/100 230/231 [============================>.] - ETA: 0s - loss: 2.3026 - accuracy: 0.1029 231/231 [==============================] - 138s 597ms/step - loss: 2.3026 - accuracy: 0.1026 - val_loss: 2.3032 - val_accuracy: 0.0986 Epoch 4/100 230/231 [============================>.] - ETA: 0s - loss: 2.3025 - accuracy: 0.1031 231/231 [==============================] - 124s 537ms/step - loss: 2.3025 - accuracy: 0.1031 - val_loss: 2.3032 - val_accuracy: 0.0987 Epoch 5/100 230/231 [============================>.] - ETA: 0s - loss: 2.3025 - accuracy: 0.1040 231/231 [==============================] - 123s 532ms/step - loss: 2.3025 - accuracy: 0.1039 - val_loss: 2.3032 - val_accuracy: 0.0989 Epoch 6/100 230/231 [============================>.] - ETA: 0s - loss: 2.3025 - accuracy: 0.1039 231/231 [==============================] - 118s 509ms/step - loss: 2.3025 - accuracy: 0.1038 - val_loss: 2.3033 - val_accuracy: 0.0988 … Epoch 20/100 230/231 [============================>.] - ETA: 0s - loss: 2.3025 - accuracy: 0.1038 231/231 [==============================] - 120s 521ms/step - loss: 2.3025 - accuracy: 0.1038 - val_loss: 2.3034 - val_accuracy: 0.0988 Epoch 21/100 190/231 [=======================>…] - ETA: 20s - loss: 2.3025 - accuracy: 0.1032
loss 一直沒(méi)有變化,accuracy 也很低,不知道出現(xiàn)了什么原因,困擾一兩個(gè)星期,都想要放棄了,太難了。但是我不死心,非要把它搞出來(lái),4 位識(shí)別不出來(lái),能不能先識(shí)別一位呢?好,那就開(kāi)始搞,一位比較簡(jiǎn)單,跟 Mnist 數(shù)據(jù)集很相似,在這我就不贅述了。
第二回:2 位彩色驗(yàn)證碼訓(xùn)練
接著來(lái)識(shí)別 2 位的驗(yàn)證碼。train count: 441, valid count: 189, test count: 270
樣本圖:
下面是我用 2 位驗(yàn)證碼進(jìn)行訓(xùn)練的結(jié)果:

30 張圖片進(jìn)行測(cè)試,結(jié)果:

哎呦,有感覺(jué)了,有了起色了,但是出現(xiàn)了過(guò)擬合的現(xiàn)象,解決過(guò)擬合的方法主要有:
Get more training data
Reduce the capacity of the network
Add weight regularization
Add dropout
Data-augmentation
Batch normalization
第三回:增加彩色驗(yàn)證碼數(shù)據(jù)集
于是我就增加了數(shù)據(jù)集。train count: 4410, valid count: 1890, test count: 2700
然后又出現(xiàn)了 loss 一直在 2.3,accuracy 在 0.09 左右,這是什么鬼呢?但是我還是不死心呀,繼續(xù)想辦法呀,既然彩色的有難度,我先識(shí)別黑白的樣本行不行呢,先試試吧。
第四回:2 位黑白驗(yàn)證碼訓(xùn)練
網(wǎng)絡(luò)結(jié)構(gòu)依然采用上面的,input_shape(100,120,3)。
這是我用 2 位的黑白圖片的驗(yàn)證碼進(jìn)行了訓(xùn)練,效果很好,收斂也很快。

訓(xùn)練第 50 回合時(shí):
Epoch 50/50 26/27 [============>…] - ETA: 0s - loss: 0.0150 - accuracy: 0.9940 27/27 [==============] - 8s 289ms/step - loss: 0.0212 - accuracy: 0.9936 - val_loss: 0.2348 - val_accuracy: 0.9446
隨機(jī)選取了 30 張圖片進(jìn)行了測(cè)試,2 張識(shí)別錯(cuò)了:

樣本圖:

看著這結(jié)果,我露出了潔白的大牙,信心大增呀,繼續(xù)搞,直接上 4 位驗(yàn)證碼。
第五回:4 位黑白驗(yàn)證碼訓(xùn)練
依然采用上面的網(wǎng)絡(luò)結(jié)構(gòu),這次使用的是 4 位黑白圖片的驗(yàn)證碼。train count: 2469, valid count: 1059, test count: 1512

訓(xùn)練第 20 回合:
Epoch 20/20 76/77 [====>.] - ETA: 0s - loss: 0.0409 - accuracy: 0.9860 77/77 [======] - 33s 429ms/step - loss: 0.0408 - accuracy: 0.9861 - val_loss: 0.3283 - val_accuracy: 0.9221
隨機(jī)選取 30 張圖片進(jìn)行測(cè)試,8 張錯(cuò)誤:

4 位驗(yàn)證碼的樣本圖:

從結(jié)果來(lái)看,有點(diǎn)過(guò)擬合,沒(méi)關(guān)系,繼續(xù)加大數(shù)據(jù)集。
第六回:增加黑白驗(yàn)證碼數(shù)據(jù)集
依舊采用上面的網(wǎng)絡(luò)結(jié)構(gòu),這次我增加了數(shù)據(jù)集 4939 張,依舊使用的是 4 位黑白的驗(yàn)證碼,訓(xùn)練結(jié)果還是挺好的:train count: 4939, valid count: 2117, test count: 3024

第 20 回合:
Epoch 20/20 153/154 [==>.] - ETA: 0s - loss: 0.0327 - accuracy: 0.9898 154/154 [====] - 75s 488ms/step - loss: 0.0329 - accuracy: 0.9898 - val_loss: 0.1057 - val_accuracy: 0.9740
可以看出 訓(xùn)練集的準(zhǔn)確率 跟驗(yàn)證集上很接近,隨機(jī)選取 30 張圖片進(jìn)行測(cè)試,6 張錯(cuò)誤圖如下:

好了,搞了這么多,由此我覺(jué)得是噪點(diǎn)影響了深度學(xué)習(xí)的識(shí)別,maxpool 的時(shí)候連帶著噪點(diǎn)也采樣了,我們需要將噪點(diǎn)處理掉,再喂入神經(jīng)網(wǎng)絡(luò)。
第七回:預(yù)處理
在上面的推理中,我感覺(jué)是噪點(diǎn)影響了神經(jīng)網(wǎng)絡(luò)的識(shí)別,于是乎我在送入網(wǎng)絡(luò)之前進(jìn)行了去噪,二值化操作,訓(xùn)練如下:train count: 4939, valid count: 2117, test count: 3024

從圖中可以看出,模型收斂了,但有點(diǎn)過(guò)擬合,第 20 回合訓(xùn)練結(jié)果如下:
Epoch 20/20 153/154 [==>.] - ETA: 0s - loss: 0.0407 - accuracy: 0.9861 154/154 [===] - 69s 450ms/step - loss: 0.0408 - accuracy: 0.9860 - val_loss: 0.3227 - val_accuracy: 0.9244
隨機(jī)選取了 30 張圖片進(jìn)行了測(cè)試,8 張錯(cuò)誤:

做到這里, 我對(duì)之前的推測(cè)有了猜疑:是噪點(diǎn)影響的嗎?我覺(jué)得不完全是。核心原因是我在嘗試的過(guò)程中對(duì)驗(yàn)證碼進(jìn)行了處理,從 RGB 的驗(yàn)證碼變成了單通道的黑白驗(yàn)證碼,使得圖片的信息減少了,神經(jīng)網(wǎng)絡(luò)的計(jì)算量也大大減少了,網(wǎng)絡(luò)模型很快得到了收斂,loss 顯著減少,accuracy 在不斷提高。
整個(gè)過(guò)程是使用 CPU 進(jìn)行訓(xùn)練的,電腦配置是 Intel_Corei7-6700HQ_CPU@_2.60GHz,8G 內(nèi)存。如果大家的電腦配置高,用 GPU 進(jìn)行訓(xùn)練,我覺(jué)得即使不做預(yù)處理,效果也能出來(lái)。
責(zé)任編輯:lq
-
cnn
+關(guān)注
關(guān)注
3文章
355瀏覽量
23426 -
tensorflow
+關(guān)注
關(guān)注
13文章
334瀏覽量
62187 -
驗(yàn)證碼
+關(guān)注
關(guān)注
2文章
20瀏覽量
4883
原文標(biāo)題:經(jīng)驗(yàn)總結(jié):使用 TensorFlow 2 識(shí)別驗(yàn)證碼過(guò)程中踩過(guò)的坑
文章出處:【微信號(hào):tensorflowers,微信公眾號(hào):Tensorflowers】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
從零開(kāi)始做嵌入式數(shù)字時(shí)鐘,我踩過(guò)的三個(gè)大坑
從踩坑到高效落地:關(guān)鍵詞搜索淘寶天貓商品列表 API 的實(shí)操心得
塑料激光焊接機(jī)怎么選?看完這篇不踩坑
K8s生產(chǎn)環(huán)境10大踩坑記錄復(fù)盤(pán)
記ESP32CAM踩坑解決指南,已反映商家
RK3576+Android15+Linux6.1調(diào)試EM05 4G模塊全記錄:從底層到上層的踩坑與破局
智能工廠改造踩坑?有人物聯(lián)網(wǎng)手把手教你挑對(duì)系統(tǒng)
工業(yè)電子EMC整改:工業(yè)場(chǎng)景下90%工程師踩過(guò)的雷區(qū)
STM32 5 個(gè)容易踩坑的外設(shè)使用技巧
為什么360°鏡頭容易“踩坑”?
JLink、RV Debugger及串口下載使用體驗(yàn)和踩坑
自動(dòng)化測(cè)試如何繞過(guò)Cloudflare驗(yàn)證碼?Python + Selenium 腳本實(shí)戰(zhàn)指南!
UWB自動(dòng)跟隨技術(shù)原理、算法融合優(yōu)化和踩坑實(shí)錄
使用Word/Excel管理需求的10個(gè)痛點(diǎn)及解決方案Perforce ALM
使用TensorFlow 2識(shí)別驗(yàn)證碼過(guò)程中踩過(guò)的坑
評(píng)論