福音:不懂代码也能用TensorFlow做验证码识别了

项目地址:https://github.com/kerlomz/captcha_trainer/tree/cnn欢迎各位大佬们指点,开发环境为:Pyhon 3.6,Mac请安装CPU版本的TensorFlow(只能使用CPU版,很慢很慢,还烫得可以煮鸡蛋,CPU使用pip安装的版本默认是不支持AVX2指令集的,需要下载源码自行编译,会有不少的速度提升。普通的CPU尝鲜:pip install tensorflow),所以强烈建议训练GPU性能爆炸的电脑。
目前主分支持续维护中,对应的文章为:https://www.jianshu.com/p/80ef04b16efc,旧的分支已经不维护啦,大家请用新的版本哦。

项目更新速报:

  1. 项目新建了一个分支,基于CNN+LSTM+CTC的不定长验证码识别,移步:https://github.com/kerlomz/captcha_trainer/tree/lstm (2018/10/16)
  2. 项目中新增了量化模块,能够缩小为原大小的1/4(2018/09/16)
  3. 项目新增了验证码在线标注工具,包含了四个流程:请求验证码上级页面,请求验证码,将免费识别的结果发至验证码正误反馈页面,保存分类后的结果。

长话短说,开门见山,网络上现有的代码以教学研究为主,对于验证码识别有刚需的朋友们,无需阅读代码,几个参数任何人都能使用机器学习技术训练一个模型,如本文有不严谨之处还请告知与谅解,此文旨在献给不求甚解,拿来主义者。

笔者选用的时下最为流行的CNN卷积神经网络进行端到端的验证码识别
懒人们仅仅需要了解一点基本的理念即可,下面笔者将带领大家走马观花瞧一瞧如何为之:

1.故事从两个配置文件说起

config.yaml # 系统配置

# Device: [gpu:0, cpu:0] The default device is GPU.
# - requirement.txt  -  GPU: tensorflow-gpu, CPU: tensorflow
# - If you use the GPU version, you need to install some additional applications.
# TrainRegex and TestRegex: Default matching apple_20181010121212.jpg file.
# TrainsPath and TestPath: The local absolute path of your training and testing set.
System:
  NeuralNet: 'CNNNet'
  Device: 'cpu:0'
  DeviceUsage: 0.9
  TrainsPath: 'd:\tmp\'
  TrainRegex: '.*?(?=_.*\.)'
  TestPath: 'E:\Task\TestGroup\patchca\'
  TestRegex: '.*?(?=_.*\.)'

# SavedStep: A Session.run() execution is called a Step,
# - Used to save training progress, Default value is 100.
# TestNum: The number of samples for each test batch.
# - A test for every saved steps.
# CompileAcc: When the accuracy reaches the set threshold,
# - the model will be compiled together each time it is archived.
# - Available for specific usage scenarios.
# EndAcc: Finish the training when the accuracy reaches [EndAcc*100]%.
# EndStep: Finish the training when the step is greater than the [-1: Off, EndStep >0: On] step.
# LearningRate: Find the fastest relationship between the loss decline and the learning rate.
Trains:
  SavedStep: 100
  TestNum: 500
  CompileAcc: 0.8
  EndAcc: 0.95
  EndStep: -1
  LearningRate: 0.001

笔者十分怀念大学时光,就用校园生活的大白话捋一捋何为机器学习吧。
简单来说,给机器刷题(训练集),机器边做题边对照标准答案(结合测试集进行训练),机器用学习收获的结晶(模型)通过套公式写出了标准答案(识别)。学习指的就是找到特征与标签的映射关系。这样当有特征而无标签的未知数据输入时,我们就可以通过已有的关系得到未知数据标签。

综上所述,我们得出了第一个结论:我们需要 训练集测试集 来训练 模型

1.1 训练集

大致常见的有以下几种方案:

  1. 人工打码
  2. 认真分析验证码特征,自己生成几乎一样的验证码来代替训练集(Kaptcha
  3. 对接打码平台:前提是要写一个爬虫,并且该爬虫需要具备以下功能:(1)下载验证码图片、(2)接入打码平台识别验证码、(3)将打码结果输入到验证码网站进行对错校验
  4. 专用的免费训练集下载工具:在线标注工具
    # Headers: 请求头部 Headers
    # Payload: 请求参数 Payload
    # - @captcha 代替识别结果.
    # - @timestamp 代替时间戳.
    # - @random 代替随机数.
    # BeforeUrl: 验证码的上一级页面URL(为了生成验证码对应的Session).
    # CaptchaUrl: 验证码URL.
    # FeedbackUrl: 验证码正误判断反馈接口 URL.
    # FeedbackCharset: 验证码正误判断反馈接口 字符集(有些网站使用GBK返回).
    # Method: [POST, GET, JSON]. 验证码正误判断反馈接口请求方式
    # TrueMsg: 验证码正确反馈 消息.
    # TrueCode: 验证码正确反馈 请求状态码.
    # FalseMsg: 同上,二者选其一即可.
    # FalseCode: 同上,二者选其一即可.
    # CharLength: 验证码长度.
    # CharSet: [ALPHANUMERIC, ALPHABET, NUMERIC]. 验证码字符集.
    # PrintFeedback: 打印反馈消息.
    # PrintPayload: 打印反馈请求参数.
    YourModelName:
      Headers: {
        user-agent: 'Chrome'
      }
      Payload: {
        'checkCode': '@captcha',
        'tm': '@timestamp'
      }
      BeforeUrl: None
      CaptchaUrl: None
      FeedbackUrl: None
      Method: 'POST'
      FalseMsg: ''
      FalseCode: 200
      CharLength: 3
      CharSet: 'NUMERIC'
    #  PrintFeedback: True
    #  PrintPayload: True
    

1.2 测试集

极力推荐外部打码+人肉打码混合(特别是一些机器容易识别错的)

1.3 开始刷题

训练集和测试集到手之后就可以开搞了。

System:
  Device: 'gpu:0' # 配置用来训练的设备,GPU比CPU快得多的多,但是要安装额外的环境依赖
  Language: 'en-US' # [zh-CN, en-US] 训练输出信息的语言
  NeuralNet: 'CNNNet'  # [CNNNet] 目前阉割掉了DenseNet待后期优化后放出
  TrainsPath: 'E:\Task\Trains\cn_exec' # 训练集的存放路径
  TrainRegex: '.*?(?=_.*\.)' # 训练集的文件名匹配,一般有两个原则:不重名、包含标注
  TestPath: 'E:\Task\TestGroup\cn_exec' # 同上
  TestRegex: '.*?(?=_.*\.)' # 同上

默认的命名规则为 正确标注_时间戳.jpg
上面对应的命名规则通过正则 .*?(?=_.*\.) 提取到正确标注,所以如果不按照这个规则命名,就需要自己另写对应于正确标注的匹配正则

正则这里补充一下,因为很多人踩坑了。大多数人感觉都是像这样的文件名:xxxx.jpgxxxx是验证码的标注,那么正则这么写:.+?(?=\.),这个匹配的目的是为了匹配出正确的标注

Trains:
  TestNum: 300 # 每个批次测试样本数,换言之:每次小测验出300题
  SavedStep: 100 # 训练过程中每100个步长保存模型,接地气的说法:每背100个单词消化一下
  EndAcc: 0.97 # 结束训练的准确率指标,换句话说,100分考97分就能毕业了
  CompileAcc: 0.9 # 编译精度,超过这个精度就编译一次,适合奇葩需求,不要在意
  EndStep: -1 # 结束训练的步长指标,换句话说,跑10公里就结束了,不看成绩了
  LearningRate: 0.0003 # 学习率和loss值密切相关,按默认的来就好了,一般还有几种选项:0.1, 0.01

2.可以嘴角开始疯狂上扬了

先晒出模型方面的参数,不要被吓到,讲一讲其实很简单的

model.yaml # 模型配置

# Convolution: The number of layers is at least 3.
# - The number below corresponds to the size of each layer of convolution.
# Provide flexible neural network construction,
# Adjust the neural network structure that suits you best
# [Convolution, Pool, Optimization: {Dropout}]
CNNNet:
  Layer:
    - Convolution: 32
    - Pool: [1, 2, 2, 1]
    - Optimization: Dropout
    - Convolution: 64
    - Pool: [1, 2, 2, 1]
    - Optimization: Dropout
    - Convolution: 64
    - Pool: [1, 2, 2, 1]
    - Optimization: Dropout
  ConvCoreSize: 3
  FullConnect: 1024

# ModelName: Corresponding to the model file in the model directory,
# - such as YourModelName.pb, fill in YourModelName here.
# CharSet: Provides a default optional built-in solution:
# - [ALPHANUMERIC, ALPHANUMERIC_LOWER, ALPHANUMERIC_UPPER, NUMERIC]
# - Or you can use your own customized character set like: ['a', '1', '2'].
# ImageChannel: [1 - Gray Scale, 3 - RGB].
# CharLength: Captcha Length.
Model:
  ModelName: patchca
  ImageChannel: 1
  CharLength: 4
  CharSet: ALPHANUMERIC_LOWER

# Magnification: [ x2 -> from size(50, 50) to size(100,100)].
# OriginalColor: [false - Gray Scale, true - RGB].
# Binaryzation: [-1: Off, >0 and < 255: On].
# Smoothing: [-1: Off, >0: On].
# Blur: [-1: Off, >0: On].
# Resize: [WIDTH, HEIGHT].
Pretreatment:
  Magnification: 0
  OriginalColor: false
  Binaryzation: 240
  Smoothing: 3
  Invert: false
  Blur: 5
#  Resize: [160, 60]·

2.1 神经网络

我们选用的神经网络是最基础的CNN模型了,一般来说就是

卷积层+池化层+卷积层+池化层...+全连接层

笔者曾经上课时存了一个很好理解的图示,斯坦福大学的CS231N的课程的传送门
卷积运算显然是一个线性操作,而神经网络要拟合的是非线性的函数,因此和全连接网络类似,我们需要加上激活函数,笔者的代码选取的为ReLU函数。
池化层的作用:通过卷积操作,我们完成了对输入向图像的降维和特征抽取,但特征图像的维数还是很高。维数高不仅计算耗时,而且容易导致过拟合。为此引入了下采样技术,也称为pooling即池化操作。池化的做法是对图像的某一个区域用一个值代替,如最大值或平均值。在这里,笔者选择的是最大值,因为前者是非线性的,一般情况下将获得更好的效果。(笔者在此便不徒增各位的选择困难了,私下决定在代码里定死)

2.2 模型

忘了和大家说一件很重要的事,光把验证码丢给计算机纯属耍流氓,好比要考试了,老师不告诉你考试范围,所以,我们还要告诉机器 这图片对应的验证码是几位的,用的是什么字符集等,例如 “AB3D” 是 4位,字符集用的是英文+数字混合。

字符集给各位安排好了

  • ALPHANUMERIC: 英文大小写与数字混合
  • ALPHANUMERIC_LOWER: 英文小写与数字混合
  • ALPHANUMERIC_UPPER: 英文大写与数字混合
  • NUMERIC: 纯数字
  • ['a', 'A', '1', ...]: 当然也不会忘了有奇葩需求的你们,还可以自定义,但是要和部署配置对应上哦

注: 本来想加中文的,但大家需要知道,中文的难度太大了,这个基本的神经网络结构完全不足以支撑,即使能训练,最多只有很低的识别率,训练时间也极高,所以这个Demo就一切从简,只考虑最常见的

2.3 预处理

节奏很快,给了考试范围,预处理又是为了什么呢,这个不知道从何说起了,这个并不是必须的环节,更像是优化,好比老师出题,出的都是无限维向量空间上的泛函,一题要解一百年,那我们分析个锤子,我们通过预处理,把维度降低到一元一次方程,识别难度降低了,识别速度也快了。
一般情况下,预处理有这么几种:
笔者的训练系统自带了 二值化、滤波、模糊
特别强调一下:为什么网上没人提及过模糊处理呢,待我举个栗子:


类型A - 处理前

类型B - 处理前

类型A - 处理后

类型B - 处理后

经过处理,类型A和类型B在肉眼上看是不是很像一个模子刻出来的。滤波主要是为了降噪,二值化旨在排除颜色的干扰,经过这些预处理,足够解决大部分简单的字符型验证码了。

2.4 开工

训练Console截图.png

不用过多介绍了吧,上图也没讲什么,大致就告诉我们两样东西:
第一,测试环节的预测报告
第二,识别率

每100步的检验有两种格式输出消息:

  1. Flag: ****, Predict: ****
  2. False, Flag: ****, Predict: ****
    输出这些消息的意义在于,满足笔者不肯放过每一个细节的监视欲望。
    acc_on_train 说的是是准确率
    注:这个100%是要强调一下的,仅仅说明抽样的300个测试集中,预测率100%。
    该模型实际线上的识别率是99.8%,大约1w个测试样本。

感谢时间:十分感谢全国失信网的验证码用以学习和研究
http://zxgk.court.gov.cn/zhzxgk/captcha.do?captchaId=08578d94beef4817afaa7b9fe1c64d58&random=0.11016792282004739
再次声明:本人未以任何形式收集该网站上的个人信息,仅作研究学习用途,该软件仅限于个人玩耍使用,请勿用于商业用途,否则作者概不负责。```

3. 惊!玩转深度学习的原因竟然是

到这里差不多已经接近尾声了,经过封装打包,傻瓜式训练神器锻造出炉。下面简单介绍一下:

  1. CPU版不需要安装额外的依赖,但有些版本低的电脑需要安装VC运行时库,还有,Win7 SP1以下是不支持TensorFlow的。

最便捷的验证码训练工具 - CPU版/GPU版
链接: https://pan.baidu.com/s/12NB-goVKT2xUUpgcRqqm8A
密码: w9cr

  1. GPU版的话需要安装CUDA 和 对应版本的 cuDNN,鉴于官网经常崩溃,我这里也给出百度云备用的下载地址:

链接: https://pan.baidu.com/s/113op-T7tQZC0V90NWHrBcg
密码: pg59

下面祭出神器界面:

CNN模型训练工具 - 非专业人员版

笔者思前想后:光训练模型可不行,还要会部署。
笔者准备在下一篇将祭出杀手锏“验证码平台一键部署神器”。

后记

如果各位好汉对验证码识别感兴趣的,可以加QQ群(857149419)交流,新群,欢迎大家一起学习和交流。
思来想去,源代码还是上传一下
走过路过点个星在此谢谢大家了!
https://github.com/kerlomz/captcha_trainer

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容

  • 文章主要分为:一、深度学习概念;二、国内外研究现状;三、深度学习模型结构;四、深度学习训练算法;五、深度学习的优点...
    艾剪疏阅读 21,807评论 0 58
  • 4月5日至7日放假调休,共3天。4月8日(星期日)照常上课。 放假期间请家长协助做好以下几点 1. 放假期...
    liangman阅读 398评论 0 0