??最近入門了下深度學(xué)習(xí),實(shí)戰(zhàn)練手寫了個(gè)定長的字符型驗(yàn)證碼識別模型祠挫。網(wǎng)上對于驗(yàn)證碼這一塊好多都是tf1的案例和解決辦法捶索,tf2的還是比較少,git上的開源項(xiàng)目也大都基于tf1.x问潭。最大的感觸果然還是,紙上得來終覺淺婚被,看書看文檔讀別人的代碼總覺得會了狡忙,自己寫還是遇到了各種各樣的問題,梯度更新的一個(gè)大坑址芯,卡了我兩天多灾茁。。記錄一下踩坑的過程谷炸。
??我這邊調(diào)試開發(fā)過程用的conda環(huán)境北专,對于我這種小白比較友好..tf版本是2.2.0 gpu版本,tensorboard 2.2.2旬陡,python是3.6.8逗余。
??首先是數(shù)據(jù)集的處理,我用的數(shù)據(jù)集是之前搞過的zxgk的驗(yàn)證碼季惩,為4位數(shù)字字母录粱,保存的圖片名字以"標(biāo)簽名_時(shí)間戳.png"命名,在處理時(shí)需要把標(biāo)簽內(nèi)容提取出來画拾,當(dāng)時(shí)搞的后面接時(shí)間戳是為了防止圖片重復(fù)啥繁。數(shù)據(jù)集我這一共差不多6萬張圖,應(yīng)該可以訓(xùn)練出一個(gè)比較滿意的準(zhǔn)確率青抛。
??圖片和標(biāo)簽預(yù)處理都做完之后脚乡,就可以建立數(shù)據(jù)集了。我選擇的是使用tf.Dataset滨达,從指定文件路徑下創(chuàng)建數(shù)據(jù)管道奶稠。封裝成一個(gè)類的形式:
??這樣調(diào)用build方法我們就可以同時(shí)拿到訓(xùn)練集和驗(yàn)證集啦画株。
??接下來建立模型辆飘,模型選的是4層卷積+2層全連接層的結(jié)構(gòu)。自定義模型谓传,繼承自tensorflow.keras.Model蜈项。
??這里loss我選擇的交叉熵恐锦,交叉熵也是常用于多分類問題的loss函數(shù)。優(yōu)化器是老大哥Adam疆液,學(xué)習(xí)率后面可能需要讓他隨訓(xùn)練次數(shù)的增加而減小踩蔚,在剛開始訓(xùn)練時(shí),學(xué)習(xí)率大一些枚粘,讓loss收斂快一些馅闽,訓(xùn)練達(dá)到一定次數(shù)時(shí)降低學(xué)習(xí)率,防止過擬合馍迄。
??接下來的過程福也,可能就不太穩(wěn)了,我們保守點(diǎn)攀圈,先寫個(gè)簡單的訓(xùn)練函數(shù)暴凑,方便調(diào)試,讓他跑起來看看有沒有問題赘来。為了保持訓(xùn)練的靈活度现喳,這里沒有用fit訓(xùn)練,需要編寫梯度更新過程的代碼犬辰。
??先初始化相關(guān)參數(shù):
??然后自定義訓(xùn)練循環(huán):
??接下來需要加入測試集、tensorboard的支持浴栽,以及對一些配置字段的提取荒叼。這時(shí)我們可以把代碼挪到Pycharm里封裝一下了。
??前面model和dataset的地方不用變典鸡,先寫一個(gè)測試的邏輯被廓,很簡單,傳入一個(gè)step的數(shù)據(jù)萝玷,預(yù)測并計(jì)算loss與準(zhǔn)確率伊者,這里不需要計(jì)算梯度。同時(shí)在傳入特征時(shí)间护,需要設(shè)置training為False亦渗,否則會影響到BN層與Dropout層的權(quán)重更新。
然后在訓(xùn)練的地方添加上。另外再加一個(gè)肛度,訓(xùn)練集準(zhǔn)確率達(dá)到99%就結(jié)束訓(xùn)練:
??完成之后的訓(xùn)練過程:
??訓(xùn)練集的字符準(zhǔn)確率與圖片準(zhǔn)確率曲線:
??看起來還不錯(cuò),最后寫個(gè)預(yù)測類的代碼就結(jié)束了:
??還可以绸贡。結(jié)束睡覺加袋。
??完整代碼的話凛辣,我已經(jīng)放在github上了,之后隨著學(xué)習(xí)的深入锁荔,我也會慢慢優(yōu)化代碼蟀给。隨后有空的話會補(bǔ)上個(gè)簡單的文檔蝙砌。
??代碼地址:https://github.com/startzm/captcha_cnn