写给程序员的TensorFlow教程-网站备案查询API及验证码识别

终于迎来了我们的《写给程序员的TensorFlow教程》的第二弹,离第一弹时间已经过去了好久好久好久好久…

等了这么久,是不是很多朋友已经晋升币圈大佬,再也不用看AI教程了。不过金钱如过眼云烟,还是有一技傍身才是真正的安全。

话不多说,先看之前的基础教程:

Discuz验证码识别(准备篇)-写给程序员的TensorFlow教程

前面算是带大家入个门。今天咱们就尽量少废话,直接进入主题。

之前说第四篇文章要讲一讲赶集的电话识别,然而貌似现在赶集的电话已经不公开展示了。所以我们今天继续看看验证码,不过换汤不换药,思路是完全一样的。今天我们要处理的是备案查询网站的验证码识别,地址是:http://www.miitbeian.gov.cn/publish/query/indexFirst.action。

我们先来看看这个验证码长什么样子:

神箭手上已经把整个验证码识别和爬虫部分整合成了一个API可以直接调用,懒得写的同学可以直接移步:

ICP域名备案查询API

 

我们继续来看这个验证码,看着似乎比Discuz验证码要稍微复杂一些。不过在实际的解决过程中,会复杂很多,主要还是因为Discuz的验证码我们是有源码的,但是这个的验证码我们是没有源码的,因此我们需要自己去猜去生成。手动去猜这些验证码的生成方式主要就在四点:

1.字体 2.颜色 3.混淆 4.倾斜。

大家看完这篇文章,其实就可以举一反三,比较轻松的解决知乎登录的那个汉字翻转验证码问题了。

对于2.颜色其实相对比较简单,只要注意一下颜色深浅的配置以及不同文字不同颜色,基本就可以。3和4只要根据具体的验证码的特点进行生成即可。只有1相对比较麻烦,这个暂时也没有什么好办法,只能一个一个找,经过我们耐心的寻找,确定了这个字体是:Lucida Sans Unicode

 

剩下的事情就好办了,只要根据这个样子写一个自动生成验证码的程序生成图片即可,值得注意的是,这个验证码包含的字符有ABCDEFGHIJKLMNOPQRSTUVWXYZ3456789。我们根据情况生成了100万张图片及标注信息。这里我们把这个生成程序打包在了精灵标注助手( www.colabeler.com )当中,大家有需要的可以直接下载这个软件,点击工具,生成验证码,填写一些参数就可以生成了,不过现在生成的数据必须上传到神箭手上,需要导出的话可以先上传再导出。看一下我们生成的数据:

内容打包成了base64方便serving和training的过程的统一。

 

好了,数据准备好了。下面就是找大神的算法然后实现了。由于普通的CNN,包括VGG系列算法中含有大量的全连接层节点,导致变量很多,随便一个模型都得200m。无论是保存起来还是serving起来压力都有点大,因此我们采用现在最流行算法之一:CNN变体ResNet来实现,对于这样一个问题生成的模型只有9m,应该说是业界良心了。当然大家也可以选用GoogleNet,不过训练过程会有点长。

根据网上的resnet代码进行简单改动,结合我们前面三篇文章讲到的图片预处理,我们就得到了一个tensorflow针对resnet的实现,我们只需要读取数据进行训练即可,部分训练代码如下:

Discuz验证码识别(上线篇)-写给程序员的TensorFlow教程

经过前两篇文章的开发,咱们今天终于要进入令人激动的上线篇了。(最近刚刚发布的TensorFlow lite其实也是部署上线的工具集之一)话说我在学习TensorFlow的时候,发现这部分的教程是尤其少。大部分教程都是先上来教一个回归,再来一个CNN,在来几篇保存模型和TensorBoard就结束了。我们这篇文章就来重点聊一聊部署上线。

前两篇文章传送门:

Discuz验证码识别(准备篇)-写给程序员的TensorFlow教程

Discuz验证码识别(编码篇)-写给程序员的TensorFlow教程

这篇文章会被分成四个部分,第一部分继续上篇文章,聊一聊第四步调参;第二部分聊一聊训练中的模型保存和载入;第三部分,介绍TensorFlow Serving;第四部分 就是最重要的部署上线流程。

Part 1 训练中的调参

还是先回顾下我们再三提及的解题思路:

第一步:将问题分解成输入(x)到输出(y)这样的结构,如Discuz验证码的输入是图片,输出是四个字符的字符串

第二步:找到很多同时包含输入输出的数据,比如很多有识别结果的验证码图片

第三步:针对不同问题,找到算法大神们的已经定义好的算法并实现成代码

第四步:尝试使用这个算法训练这些数据,如果效果不好,算法中有一些参数可以手动调整,至于怎么调,可以参考前人经验,也可以自己瞎调积累经验。

第五步:写一个程序载入模型,接受一个新的输入值,通过模型计算出新的输出值。

前两篇文章已经走完了前三步,那么我们现在来看的第四步。不负责任的讲,其实机器学习工程师大部分时间都是在调参。毕竟,大神都想好的算法就几个,但是却留了很多参数来调整。我们总还是得体现出自己的价值是不是,那我们来看看一般都有哪些参数值得调整(大家最好对照代码来看,这个是熟悉代码最好的方式):

1.图片最终压缩的长宽

image_resized = tf.image.resize_images(image_gray, [48, 48],tf.image.ResizeMethod.NEAREST_NEIGHBOR)

这一段是我们前面代码中压缩图片的逻辑,那么最终图片压缩到多大是最合适的呢?太大的训练的慢,内存占用高;太小了又会丢失重要信息。一般来说,我们挑一个样本图片,压缩完之后用肉眼看一下,如果你自己肉眼还能识别的话,那就是ok的。

2.神经网络层数和节点数

看了两节课,大家应该大体能知道我们的神经网络是由一层一层的节点组成的,比如这就是一层,这一层实现的是卷积层:

Discuz验证码识别(编码篇)-写给程序员的TensorFlow教程

欢迎大家回到《写给程序员的TensorFlow教程》系列中来,本系列希望能给广大想转型机器学习的程序员带来一些不一样的内容,我们不讲公式,只调方法,不聊文献,只说代码。不求最好,只求有用。带大家迅速上手TensorFlow(以下简称TF。我是强迫症患者,每次都敲驼峰太累了)。

系列教程前篇:

Discuz验证码识别(准备篇)-写给程序员的TensorFlow教程

下面正式要开始了我们真正的TensorFlow编程,这篇文章主要内容分为两部分,一部分是介绍TF的基础知识和一些常用接口;第二部分是接着上节课的内容继续执行我们的解题思路。

我们先进入第一部分

Part 1、TF基础知识

虽然我们机器学习的基础概念可以先不深究,但是TF还是得讲一讲的,不然咱们就算抄再多代码也是天书,完全达不到渗透法的学习目的,所以我们先给大家讲一讲TF的基本代码结构。

对于开发网页或者移动应用来说,程序是沿着我们写出来的代码逻辑一步一步执行的,因此我们一般都是可以在代码中任意地方插入print来打印我们需要了解的变量的值。但是在TF中却不是这样,TF中我们的代码一般会被分为两个模块:

1.先预定义一张图

注意:这个图不是图片的图,而是一个节点之间相互连接的结构,为了能打击大家的学习积极性,我先放一张简单的图给大家看看:

2.再循环把数据扔进这张图中执行

举一个不恰当的比方:

机器学习任务类似与起房子,一条一条的数据就是一块一块的砖,最终训练出来的模型就是房子本身,那么相对应的起房子的流程就是:

1.先画一个设计的图纸

2.根据这个设计的图纸,用砖一点一点把房子造出来

这里稍微有些不恰当的细节,不过初学者不用在意这些细节。

那么接着我们就要认识到TF中的一个最重要的概念,那就是Session,这个Session就可以理解为施工队,Session的具体用法如下:

Discuz验证码识别(准备篇)-写给程序员的TensorFlow教程

蛰伏了快两个月了,终于迎来了新系列的第一篇文章。斟酌来斟酌去,决定将系列名字定为-《写给程序员的TensorFlow教程》也算是给这个系统文章定个基调。

太多的TensorFlow入门教程上来就是列了一系列国外的文献,视频。或者直接扔一堆代码,实在难以称之为入门。我们希望针对想学习TensorFlow的程序员来写一系列教程,聊一聊如何在基本掌握python的情况下,能够快速的使用TensorFlow这个工具解决实际问题。

首先,这个系列文章是之前的系列-《反爬与反反爬的奇技淫巧》的番外篇,

之所以是反爬系列的番外篇,因为我们主要是讨论如果使用TensorFlow解决爬虫中常见的问题,包括验证码,图片电话号码识别这类问题(这个系列主要是图像识别)。不过虽然跟反爬相关,但是这个系列依然可以独立来看,不做爬虫的朋友也不会受影响。

作为系列文章第一篇,先说说这个系列的定位,我们希望能给广大想转型机器学习(准确说是Tensorflow实现的神经网络)的程序员带来一些不一样的内容,我们不讲公式,只调方法,不聊文献,只说代码。不求最好,只求有用。正如下面这个自带bgm的表情:

那么我认为对于想要转型的程序员来说,做到以下四点就算基本转型成功了:

1.了解一定的机器学习原理(类似写web,我们要知道http的包结构,知道tcp的三次握手即可)

2.大方向上知道遇到什么问题该用什么机器学习算法来解决(成熟的大类就几个,很容易掌握)

3.熟悉主流算法的实现方案和用法,最好自己有一套对主流方案的封装(做到这一点其实已经很好了)

4.掌握整个从测试环境到生产环境的完整流程(通俗点就是会做能上线的产品,这一点很重要却最容易被忽略)

好了,扯了这么多题外话,我们正式开始:

一、准备部分

在我们动手写代码之前还是要有一些准备工作:

首先我们要对整个问题和解决方案有一个宏观的认知,另外为了方便,本文所有的提到机器学习的地方都可以等价为神经网络实现的监督学习这个领域,关于其他机器学习的领域不在本系列的讨论范围以内。(如果没入门的朋友可以忽略这句话)

1.知识的准备

先说说问题,我们今天要从一个最简单的验证码识别问题入手,我们看下我们的敌人:

就是这货,看着不复杂,没有太多杂点杂线。不过我们说他最简单,绝对不是说的这些,而是这个验证码我们是有生成代码的(Discuz是开源的)。这就意味着我们有无穷多的标注好的验证码图片(就是自带识别结果的图片)。这个对于机器学习来说简直就是无敌了。

聊完问题,我们再整体聊一聊Tensorflow和机器学习的解题思路。我们上学的时候,无论遇到什么问题总有一个解题思路,否则绝对是一头雾水。所谓隔行如隔山,很多时候是因为我们不了解那个行业解决一个常规问题的解题思路,那么机器学习的解题思路是什么呢?

当我们拿到一个问题决定用机器学习的方法解决他,我们要做以下几步:

1