全國高校電腦能力挑戰賽驗證碼識別競賽一等獎調參經驗分享
- 2020 年 2 月 12 日
- 筆記
前言:這是為驗證碼識別競賽而開發的一個基於pytorch實現的端到端的驗證碼識別系統。前後開發大概有2個月,其中大部分時間都在調參,後期參考kaggle大神經驗,加入了一些trick,但是由於第一個榜截止了,所以沒有得到測試集結果,只有驗證集的參考結果。該庫比較簡單,適合入門競賽,不過調參難度比較大,需要嘗試合適的超參數,如果超參數不合適,可能會導致無法收斂,具體問題還需具體分析。
- 作者:pprp
- 編輯:BBuf
1. 競賽背景
本次比賽是全國高校電腦能力挑戰賽中的人工智慧賽道里的驗證碼識別,該比賽需要識別26(大寫)+26(小寫)+數字(10)= 62個字元,隨機組成的四位驗證碼圖片。
2. 賽題分析
- 訓練集僅有5000張,而所有的數字組合有 個組合。
- 驗證碼識別的難度係數較大,人眼也很容易識別出錯。
- 雜訊比較嚴重,存在遮擋字元的情況。
3. 數據集

1575527368225
比賽提供的數據集如上圖所示,12040的像素的圖片,然後標籤是由圖片名稱提供的。
訓練集測試集劃分:80%的數據用於訓練集,20%的數據用於測試集。
- 訓練圖片個數為:3988
- 測試圖片個數為:1000
訓練的數據還是明顯不夠的,考慮使用數據增強,最終選擇了Augmentor庫作為影像增強的庫。Augmentor庫很適合做影像分類的數據增強。由於驗證碼與普通的分類圖片有一定區別,所以選擇的增強方式有一定局限,比如不能翻轉,不能左右顛倒,不能crop等, 但是也有一些比較好用的方法,比如說distortion(彈性變形), perspective skewing (透視偏斜),圖片縮放等方法也適用於驗證碼識別。
經過幾輪實驗,最終選取了distortion類的方法作為具體增強方法,輸入為訓練所用的圖片,輸出設置為原來圖片個數的2倍,具體程式碼見dataAug.py, 核心程式碼如下:
def get_distortion_pipline(path, num): p = Augmentor.Pipeline(path) p.zoom(probability=0.5, min_factor=1.05, max_factor=1.05) p.random_distortion(probability=1, grid_width=6, grid_height=2, magnitude=3) p.sample(num) if __name__ == "__main__": # 生成訓練集兩倍的數據量 get_distortion_pipline("path to image folder", 2 * len(train_folder))
將得到的圖片重命名為auged_train文件夾,最終數據集組成如下:
root |---data |--- train:3988張 |--- test:1000張 |--- auged_train:7976張
訓練流程是每隔epoch先遍歷train文件夾,然後遍歷auged_train文件夾,最後對test文件夾進行一次測試,完成一次遍歷。PS:數據集下載鏈接在文末。
4. Trick總結

上圖就是整個驗證碼識別的流程圖,也是baseline, 在此基礎上可以使用很多分類網路中用到的trick。
比賽從以下幾個角度進行調參優化:
- 調整超參數:
- CosineAnnealingLR
- ReduceLROnPlateau
- StepLR
- MultiStepLR
- GradualWarmupScheduler(warm up)
- Learning Rate 調整
- decay參數調整
- learning rate scheduler嘗試:
- 更改優化器:
- Adam優化器
- RAdam優化器
- AdamW優化器
- AdaBound優化器(嘗試過後效果很差,網路不收斂,可能是由於超參數設置問題)
- 數據增強
- augmentor庫中的distortion方法
- attention機制
- 嘗試se模組
- 修改backbone:
- 添加dual pooling 模組
- 添加bnneck模組
- 添加ibn模組
- senet
- densenet
- resnet18
- 更換loss:
- 使用center loss+CrossEntropyLoss,收斂比較慢,對參數敏感
5. 調參過程記錄
調參過程記錄:null代表未記錄
Name |
item1 |
item2 |
item3 |
item4 |
item5 |
測試:線上 |
---|---|---|---|---|---|---|
baseline0 |
Ret18 |
lr=1e-3 |
4:1劃分 |
Adam |
|
88%:84% |
baseline1 |
Res34 |
lr=1e-3 |
4:1劃分 |
Adam |
|
90%:84% |
baseline2 |
Res18 |
lr=1e-3 |
4:1劃分 |
RAdam |
|
null:90% |
baseline3 |
Res18 |
lr=3e-4 |
4:1劃分 |
RAdam |
|
未收斂 |
baseline4 |
Res18 |
lr=1e-1 |
4:1劃分 |
RAdam |
|
96.4%:87% |
baseline5 |
Res18 |
lr=1e-1 |
4:1劃分 |
RAdam |
aug0 |
98%:93% |
baseline6 |
Res18 |
lr=1e-1 |
9:1劃分 |
RAdam |
aug1 |
60%:null |
baseline7 |
Res18 |
lr=1e-3 |
4:1劃分 |
RAdam |
aug2 |
null:94% |
baseline8 |
Res18 |
lr=1e-3 |
4:1劃分 |
AdamW |
aug2 |
98.4%:92.56% |
baseline9 |
Res18 |
lr=1e-3 |
4:1劃分 |
RAdam |
aug3 |
null:93.52% |
baseline10 |
Res18 |
lr=1e-3 |
4:1劃分 |
RAdam |
aug4 |
null:94.16% |
baseline11 |
Res18 |
lr=1e-3 |
9:1劃分 |
RAdam |
aug5 |
60%:null |
baseline12 |
Res18 |
lr=3.5e-4 |
4:1劃分 |
RAdam |
aug2 |
null:94.72% |
baseline13 |
Res18 |
lr=3.5e-4 decay:6e-4 |
4:1劃分 |
RAdam |
aug2 |
null:95.16% |
baseline14 |
Res18 |
lr=3.5e-4 decay:7e-4 |
4:1劃分 |
RAdam |
aug2 |
bad |
baseline15 |
Res18 |
lr=3.5e-5 decay:6.5e-4 |
4:1劃分 |
RAdam |
aug2 |
null:95% |
baseline16 |
Res18 |
lr=3.5e-5 decay:6.5e-4 |
4:1劃分 |
RAdam |
drop(0.5) |
null:97% |
以上的aug代表數據增強:
- aug0: +distrotion
- aug1: 9:1劃分+擴增3倍
- aug2: +distortion+zoom
- aug3: +tilt+擴增兩倍
- aug4: aug2+aug3混合
- aug5: 9:1劃分 +tilt傾斜
數據增強示意圖:
example1 |
example2 |
example3 |
---|---|---|
|
|
|
後期嘗試的主要方案有以下:
- learning rate scheduler嘗試:CosineAnnealingLR, ReduceLROnPlateau,StepLR,MultiStepLR
- 更改backbone: senet, densenet
- 在res18基礎上添加:attention機制,dual pooling, ibn模組,bnneck等
- 嘗試center loss,收斂很慢,但是效果應該不錯
還未嘗試的方案:
- label smooth
- 多模型ensemble
6. 相關鏈接
最終庫地址:https://github.com/pprp/captcha.Pytorch
augmentor API:https://augmentor.readthedocs.io/en/master/index.html
鏈接:https://pan.baidu.com/s/13BmN7Na4ESTPAgyfBAHMxA 提取碼:v4nk
增強後的數據集,建議使用dataset2
後記:整個比賽下來得到了一等獎,整個過程可謂過山車一般,比賽還沒有放榜的時候,覺得問題不會很難,因為提前查看了網上的驗證碼庫,研究了一下發現,大部分驗證碼都很簡單,比較清晰,但是這次驗證碼下來以後就發現難度比較大。之後就選擇了一個能達到80%準確率的baseline開始調整。其中比較有感觸的是比賽結束前突發奇想,加入了dropout,效果一下提升了很多,榜一排名到了30左右。