字符验证码杀手--CNN
1 abstract
目前随着深度学习,越来越蓬勃的发展,在图像识别和语音识别中也表现出了强大的生产力。对于普通的深度学习爱好者来说,一上来就去跑那边公开的大型数据库,比如ImageNet或者CoCo,可以会觉得这个屠龙之技离生活好遥远。那么本文就是希望将此技术运用到一些普通用户日常就能感知的场景上,让普通用户切实能够体会到深度学习工具的非凡能力。
关键字:深度学习,验证码,破解,识别,CNN
2 验证码概述
很多普通程序员在入门爬虫的时候,基本上都会遇到的环节---“验证码”。就是这个东西使得很多程序的自动化工作止步,让人懊恼不已。关于验证码的功能,以前提到过(todo),本文不再赘述,只用一句话来概括下:验证是一种防止程序自动化的一个措施,其最常见的表现形式就是看图识别字符。
验证码技术就是一种反自动化技术。本文所解决的问题则是,使用深度学习技术来实现“全自动化的识别验证码”(这听起来有那么点人工智能的味道了)。
因为现在新的形式的验证产品很多,光从外界的展现形式上就有:
- 完整滑动解锁式
- 随机滑动拼图式
- 随机点选汉字式
- 图片分类选择式
- 其它
但是本文是以学习为目标,并不指向任何一种验证形式,而是指向传统的字符型验证码。由浅入深来对验证码进行一些科普。下图就是网络上的各色各样的字符型验证码,敬请大家赏析:
3 验证码场景
首先说明本文的观点:随着深度学习技术在图像处理技术上越来越强大的表现,这些传统的纯依靠简单图片的码式验证已经没有任何的安全性可言。
但是这些不安全的验证码却即使是在今天写这篇文章的时候,还存在于互联网的各个角落,存在于大互联网公司,基于像银行,证券和保险等等这些金融领域。
这些主要的应用场景包括:注册,登录,找回密码,抢购下单,评论,投票等等。如果这个地方不安全的话,也就是说能够通过程序做自动化,那么网络上的资源就会全部被自动化程序抢夺过去,或者说直接落入少数会做自动化的人的手中。为什么呢?因为普通计算机程序的计算能力是人的几万甚至几百万倍。
如果还不能理解,我说一个简单的例子吧,如果你自己去注册你的帐号密码需要3分钟完成,但是通过程序可以一秒钟注册300个账号。讲到这个地方,如果你还不理解,那么你想象在去年的时候互联网金融行业非常火爆时,每注册一个账号就有20块钱可以拿。也就是说比较厉害的人可以通过这个程序,一秒钟赚6000块钱。
如果你还不能理解这个东西的话,再举一些和大家日常生活中非常相关度高的一个场景:
- 网上春节购买火车票。春节的时候大家会买火车票吧?你是不是发现你守在电脑面前不管怎么用心,不管怎么努力,结果发现放出火车票的时候,那些票一扫而光?然后发现身边好多人都没买到票,但是网上黄牛那儿却票源充足,但是不好意思,得加价。
- 网上手机新品发布秒杀。国内大厂手机新品发布时,网上瞬间秒光,自己买不到,但是黄牛那儿也有,得加钱。
- 网上开盘选房子。你要买房子,网上开盘选房,虽然你已经做好了不看户型,有房就抢的准备,但是开盘瞬间,你就发现网络被挤爆,然后等线上网页缓过来时,房子已经完了。但是身边加钱找专业人员代抢的人却抢到了房子,为什么?
- 网上拍汽车牌照。在国内某些大城市里面对于汽车牌照的发放量的把控是是非常严格的。每次在网上拍牌照的那天,很多人都会请假一天,然后在一个网络环境非常好的网吧里面等待来处理这个事情,但是发现还是抢不过别人付费请的专业团队的那些人。当然抢不过有一方面是自己业务不熟悉的原因,还有一方面就是:可能你在拿一个小铲子的辛苦的小打小闹的,别人直接操纵在一个大型挖掘机上战场了。生产力是完全不一样的。
类似的事情特别特别多。这个产业就叫做“薅羊毛”,顾名思义就是积少成多,有很小的成本把一点点的小的利益聚集起来就会变成一个比较可观的利益。
4 应用举例
4.1 互联网大厂
4.1.1 美橙互联
https://www.cndns.com/members/signin.aspx
4.1.2 中国互联网络信息中心
http://www.cnnic.net.cn/
4.1.3 百度
https://wappass.baidu.com/
4.1.4 阿里支付宝
https://omeo.alipay.com/service/checkcode?sessionID=a2a5fc056b8e3ef8b32758835333d673&t=0.3144848125469759
4.1.5 网易邮箱
http://reg.email.163.com/unireg/call.do?cmd=register.entrance&from=163navi®Page=163
4.1.6 58同城
https://passport.58.com/validcode/get?vcodekey=d5S2Tk7dofqN30VwIN6WTwvOHP6AkyvC&time=1466065243496
4.2 互联网金融
4.2.1 平安保险
https://www.pingan.com.cn/pinganone/pa/index.screen?sid_source=toagw
4.2.2 宜信
https://www.creditease.cn/a/user/loadRegisterUserPage
4.2.3 大地保险
http://www.95590.cn/ebiz/loginSkin.jsp?loginBackUrl=http://www.95590.cn/
5 图像识别
下面是字符验证码两种比较极端的表现形式:
简单类型的特点:
- 背景和前景可以很容易完全分离
- 字符的取值范围仅为[0,9]这样的最小有限域
- 生成图片的字符为单一字体
- 多位字符串可以通过简单算法进行完美切割
复杂类型的特点:
- 背景有随机干扰点或者干扰线条
- 字符范围为所有数字,字母,甚至汉字集
- 生成的图片的字体多样化
- 多位字符在图片上的位置出现重合,无法完美切割
在上一部分内容中举的现在线上应用的例子,基本上属于比较复杂的类型,但是由于它的设计理念仍然停留在图像学上,所以对于现在的CNN来说,是完全没有技术上的问题,毕竟很多深度学习框架的入门教程就是对手写数字数据库MNIST进行识别。它们有的区别只是前期准备工作的工作量的不同,这里所说的前期准备工作就是指:带标记的数据的准备工作。所谓的“带标记的数据”是指,需要人预先告诉计算机什么样的图片对应着是什么样的字符串,因为本问题中所用的CNN方法是属于有监督学习的范围,需要有个场外的“老师”进行指导。
关于上面两种极端的字符验证码的识别的技术方法,请移步文章末尾链接。
里面有两个例子,并附上了完整的源码:
- 使用传统机器学习SVM对简单验证码识别
- 使用CNN对多位字符验证端到端的识别
当然后面的那种CNN的方法是对于解决此类问题是属于核武器级别的,CNN模式的优点缺点都很明显:
- 优点:通用性强,换一个模式后,可以不用修改代码就可以直接训练出新的模型。
- 缺点:需要大量的带标注的数据,特别是端到端的复杂一点的,可能需要几万带标记的先验数据集。
在CNN的文章中给出的demo,因为只是做效果演示,里面的数据集的生成是直接用的第三方标准库无限生成的。如果是在具体的场景去使用,则需要准备大量的带标记数据,像本文提到的困难的字符验证,如果要达到90%以上的正确识别率,估计需要5万带标记数据。下图是生成的部分先验数据集:
对于不同的多字符验证码,根据其难易程度分类,可以有一些不同的处理方式,有“蛮力型”的通用识别方法,也有“特事特办”的特别识别方法。
5.1 通用识别方法
所谓的通用识别方法就是:流程化作业,基本不太需要在编程上思考太多。
通用步骤如下:
- 下载一定数量的目标验证码图片。根据验证图片的复杂程度而定,有的需要几百张,有的需要几万张。
- 已经事先准备好一套标准的CNN图像分类的项目模板,需要事先做好的功课。
- 对项目模板进行简单的参数调整,以适配当前问题的图片尺寸。
- 将图像输入CNN,将输出的结果和先验标记的类型做误差对比
- 不断迭代生成模型
这其实是一个深度学习对分类问题处理的标准化流程。有不明白的地方,请补充一点相关的知识:
https://www.tensorflow.org/get_started/mnist/beginners
https://www.tensorflow.org/get_started/mnist/pros
由Google公司主推的深度学习框架tensorflow的入门文档里面就介绍了分别用矩阵回归和CNN神经网络对手写数字识别的方法。
当然,关于如何获取带标记的数据,目前也有比较便宜的获取渠道,直接在网上搜索“打码平台”,提供这“人工智能”领域的“人工”服务的厂家也不少,而且是明码标价:
对于字符型验证码,基本上是几分钱一张标记图吧。
5.2 特别识别方法
虽然上面的通用型方法可以百试不爽,但是每次来一个新的问题,你都要准备大量的带标记数据,这个未免也太繁琐了,而且像一些简单的字符验证码的问题,其实倒没有必要去大动干戈。那么这个时候就需要一些小的技巧了。
这里所说的特别识别方法,仍然是基于深度学习这种通用方法来做的,只是我们可以将一些复杂问题进行适当的简化,这个思想有点类似于“降维”处理的意思。
因为深度学习具有这样的神奇效果:理论上对绝大多数的线性或者非线性问题都能实现非常好的拟合。
但是对于越复杂的问题,对数据的需求量越大。这个现状是无法避免的,但是我们却能够做一些人为的自动化工作,以达成此目标。
比如像这些验证:
不管它们色彩有多么的变化,不管背后加些啥乱七八糟的干扰点或者线,但是有一个事实他们无法回避,就是:他们的字符之间都是非常好分割的。也就是说,像这些类型的验证码,可以很容易将一个本来要判定N位字符串的问题简化为“判定1位字符,然后将N个这样的图片再组合起来”。这样网络的复杂度可以大大的简化,训练所需要的样数量,还有训练的时长都会大量减少。
如果验证码图片可以从N维“降维”到1维了,这个字符的字体如果是单一的,比如下面这些验证:
那么问题就更简单了:只需要为每个字符分类准备一张图片即可。也不是说如果你的验证码范围是[0,9],则只需要从下载的图片集中对0~9这几个数字每个标记一张即可,然后就是使用一些普通的数据增强技术:贴图,绽放,上下自由截取,随机噪点等等,可以生成无限多的数据集了,当然这些全部是由程序自动化完成。
好的图像预处理也很重要,所谓好的图像预处理,就是指能够将图像里面的主体特征变得更加明显,例如:
好的图像预处理会使识别问题难度直线下降,比如上面左图如果用CNN估计可能要1万样本,而右边的那个经过预处理后,估计只需要1千样本就OK了。
关于如何做数据增强,在后续的文章中会进行具体介绍。
6 文末小结
如果对本话题有兴趣请持续关注本系列文章。
如果还想进一步讨论相应的技术,请加入QQ群:592109504
手机QQ扫描二维码:https://mp.weixin.qq.com/s/7RCtZH0ljuF5Ti6jgQxyww
验证识别合辑技术文章:https://zhuanlan.zhihu.com/p/30871712
后续会有更多干货文章,敬请期待。。。
我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan