最近入门了下深度学习,实战练手写了个定长的字符型验证码识别模型。网上对于验证码这一块好多都是tf1的案例和解决办法,tf2的还是比较少,git上的开源项目也大都基于tf1.x。最大的感触果然还是,纸上得来终觉浅,看书看文档读别人的代码总觉得会了,自己写还是遇到了各种各样的问题,梯度更新的一个大坑,卡了我两天多。。记录一下踩坑的过程。
我这边调试开发过程用的conda环境,对于我这种小白比较友好..tf版本是2.2.0 gpu版本,tensorboard 2.2.2,python是3.6.8。
首先是数据集的处理,我用的数据集是之前搞过的zxgk的验证码,为4位数字字母,保存的图片名字以"标签名_时间戳.png"命名,在处理时需要把标签内容提取出来,当时搞的后面接时间戳是为了防止图片重复。数据集我这一共差不多6万张图,应该可以训练出一个比较满意的准确率。









图片和标签预处理都做完之后,就可以建立数据集了。我选择的是使用tf.Dataset,从指定文件路径下创建数据管道。封装成一个类的形式:


这样调用build方法我们就可以同时拿到训练集和验证集啦。
接下来建立模型,模型选的是4层卷积+2层全连接层的结构。自定义模型,继承自tensorflow.keras.Model。





这里loss我选择的交叉熵,交叉熵也是常用于多分类问题的loss函数。优化器是老大哥Adam,学习率后面可能需要让他随训练次数的增加而减小,在刚开始训练时,学习率大一些,让loss收敛快一些,训练达到一定次数时降低学习率,防止过拟合。

接下来的过程,可能就不太稳了,我们保守点,先写个简单的训练函数,方便调试,让他跑起来看看有没有问题。为了保持训练的灵活度,这里没有用fit训练,需要编写梯度更新过程的代码。
先初始化相关参数:

然后自定义训练循环:



接下来需要加入测试集、tensorboard的支持,以及对一些配置字段的提取。这时我们可以把代码挪到Pycharm里封装一下了。
前面model和dataset的地方不用变,先写一个测试的逻辑,很简单,传入一个step的数据,预测并计算loss与准确率,这里不需要计算梯度。同时在传入特征时,需要设置training为False,否则会影响到BN层与Dropout层的权重更新。


然后在训练的地方添加上。另外再加一个,训练集准确率达到99%就结束训练:


完成之后的训练过程:



训练集的字符准确率与图片准确率曲线:



看起来还不错,最后写个预测类的代码就结束了:




还可以。结束睡觉。
完整代码的话,我已经放在github上了,之后随着学习的深入,我也会慢慢优化代码。随后有空的话会补上个简单的文档。
代码地址:https://github.com/startzm/captcha_cnn