本文方法针对的验证码为定长验证码,不包含中文。
本文的思路是:1. 使用keras中预训练好的模型,在python生成的验证码(5万条)上fine tune,得到python验证码模型;2. 使用python验证码模型,在实际验证码(500条)上fine tune;3. 增加样本,提高精度。
通俗的解释2个问题:
- keras中预训练好的模型是什么东西?
答: keras上有很多已经训练好的图像识别模型,诸如Alex Net,google net,VGG16,VGG19,ResNet50,Xception,InceptionV3,这些都是由ImageNet训练而来。那ImageNet又是什么的?ImageNet项目是一个用于视觉对象识别软件研究的大型可视化数据库,超过1400万的图像URL被ImageNet手动注释,以指示图片中的对象。说白了,上述已经训练好的图像识别模型是用来识别大千世界的各种物品的,如气球、草莓、汽车、楼房等等。这些个模型都能识别这么复杂的东西了,那我现在要识别一个验证码数据,岂不是很简单?这就是站在巨人的肩膀上,再微微调整一下模型就可以了。这其实就是迁移学习的概念。
- 为什么要先使用python生成得验证码进行fine tune?
答: 虽说我们站在巨人的肩膀上,利用已有的深度神经网络来微调我们的模型,但是从大千世界迁移到验证码图片,这两个样本集还是有很大的差别的。这就要求我们用“大量“的验证码数据再去训练我们的神经网络参数。这个”大量“我为什么用引号呢,因为其实只需要数万张(下文使用了5万)验证码图片就可以了,相对于ImageNet的1400万,这个数字其实很小,但是如果需要我们手工标记数万张验证码,那就是不小的工作量了。所以,我们先用python自动生成标记好的5万张验证码图片,先进行fine tune,保存好输出的模型,注意,这个模型已经不是识别大千世界的模型了,是识别数字和英文字母的模型了,但是直接应用于实际的验证码,效果还是很差,因为两种验证码长得不一样,然后我们进行再一次的迁移学习,再在我们手工标记好的、实际要识别的验证码(500条)进行fine tune,这样就可以识别很好的识别我们要识别的验证码了。
1. 利用python生成你所需要的验证码
一般的验证码都为4位,由数字和大小写字母构成。利用python的captcha模块,生成5万张样本图片:
from captcha.image import ImageCaptcha
from random import randint
def gen_captcha(num,captcha_len):
# # 纯数字,如果目标识别是10位数字,预训练用纯数字效果更好
# list = [chr(i) for i in range(48, 58)]
# # 10数字+26大写字母+26小写字母
list = [chr(i) for i in range(48, 58)] + [chr(i) for i in range(65, 91)] + [chr(i) for i in range(97, 123)]
for j in range(num):
if j % 100 == 0:
print(j)
chars = ''
for i in range(captcha_len):
rand_num = randint(0, 61)
chars += list[rand_num]
image = ImageCaptcha().generate_image(chars)
image.save('./train/' + chars + '.jpg')
num = 50000
captcha_len = 4
gen_captcha(num,captcha_len)
这样我们就轻松的获取到了5万张样本数据
2. 使用python生成的样本进行预训练
keras_weight中Alex Net,google net,VGG16,VGG19,ResNet50,Xception,InceptionV3。都是由ImageNet训练而来。这里使用Xception模型
Xception模型
参考keras文档:https://keras.io/zh/applications/#xception
keras.applications.xception.Xception(include_top=True,
weights='imagenet', input_tensor=None,
input_shape=None, pooling=None, classes=1000)
在 ImageNet 上预训练的 Xception V1 模型。
在 ImageNet 上,该模型取得了验证集 top1 0.790 和 top5 0.945 的准确率。
注意该模型只支持 channels_last 的维度顺序(高度、宽度、通道)。
模型默认输入尺寸是 299x299
参数
include_top: 是否包括顶层的全连接层。
weights: None 代表随机初始化, 'imagenet' 代表加载在 ImageNet 上预训练的权值。
input_tensor: 可选,Keras tensor 作为模型的输入(即 layers.Input() 输出的 tensor)。
input_shape: 可选,输入尺寸元组,仅当 include_top=False 时有效(否则输入形状必须是 (299, 299, 3),因为预训练模型是以这个大小