Abstract
SVHN 是街景数字的数据集, Google 在 2013 年发表的论文 "Multi-digit Number Recognition from Street View Imagery using Deep Convolutional Neural Networks" 提供了解决方法, 并声称该方法可以破解所有的验证码.
本篇博客将简要的总结这篇论文, 并使用 keras 实现模型并训练 SVHN 数据集.
这篇文章的方法主要作为训练 SVHN 数据集的一个 baseline. 作者说他的方法能达到百分之 96 以上的准确率.
任务要求
这里先看一下数据集的样子, 其实也就是 Number from Street View(街景数字).
过去的做法
Traditional approaches to solve this problem typically separate out the localization, segmentation, and recognition steps.(过去的做法要经历三步: 定位, 分割, 然后识别)
作者的做法
Propose a unified approach that integrates these three steps via the use of a deep convolutional neural network that operates directly on the image pixels.(作者把这三个步骤通过一个深度的卷积网络就能完成)
作者的贡献
- (a) A unified model to localize, segment, and recognize multi-digit numbers from street level photographs
- (b) A new kind of output layer, providing a conditional probabilistic model of sequences
- (c) Empirical results that show this model performing best with a deep architecture
- (d) Reaching human level performance at specific operating thresholds.
问题描述
图片中的数字: 每张图片的数字是一个字符串序列: , 如上面的第一张图片结果为 "379",.
字符的长度: 定义为 n, 绝大多数的长度小于 5. 作者这里假设字符的长度最大为 5.
实现方法
作者的方法是对于图片的 label, 训练一个概率模型. 这里作者定义:
S: 输出序列, 也就是训练数据的 label.
X: 输入的图片.
这里的目标也就是通过最大化, 来学习模型.
X 其实就是输入的图片, 这里看一下 S,S 是: 图片的数字序列 + 数字序列的长度 的一个集合. 比如上面的 "379" 是图片的数字序列, 序列的长度 len("379")为 3. 那么 S 就是 "3"+"379", 也就是 "3379".
这里 可以定义为: 字符长度的概率再乘以每个字符取值的概率.(每个字符取值是独立的).
上面的变量都是离散的,的取值有七种: 0,1,2,....,5, 比 5 大;有 10 种: 10 个数字.
训练这个模型, 就是在训练集上最大化, 作者这里每个参数都使用一个 Softmax 层.
模型结构
下面, 看下作者在论文里面发表的模型.
输入图片 是一个 128x128x3 的图片.
然后经过一系列的 CNN 层进行特征提取, 变成了一个含有 4096 个特征的向量.
之后根据这 4096 个特征, 分别让 ,,,,, 分别经过一个 Softmax 层
.
对于每个变量,
Keras 的实现
代码见:
环境依赖
- python 3.x
- TensorFlow 1.11
- Keras 2.x
- Pillow
- h5py
数据下载
首先去 http://ufldl.stanford.edu/housenumbers/ 下载 Format 1 的数据.
- wget http://ufldl.stanford.edu/housenumbers/test.tar.gz
- wget http://ufldl.stanford.edu/housenumbers/train.tar.gz
然后对数据进行解压, 解压后发现会多两个文件夹: test 和 train.
- tar zvxf test.tar.gz
- tar zvxf train.tar.gz
构建数据集
这个数据集可以使用 h5py 读取.
其中 bbox 存了图片数字的框, 而 name 则是图片的文件名. 比如说读取出来是下面这样的图片:
然后通过框框把图片裁剪一下.
网络模型
网络模型这里分为卷积层 + 全连接层部分, 代码如下.
卷积层
这里就是三个卷积层. 为了让神经网络接受了参数符合同一分布, 这里使用了 Batch Normalization 层, 对 ConvNet 的输入进行批归一化.
全连接层
卷积层最后经过 Flatten 之后, 进入了全连接层. 全连接层最后, 输出了到 6 个 softmax 层中, 分别代表: 字符的长度, 第一个字符, 第二个字符, 第三个字符, 第四个字符, 第四个字符.
注意: 这里字符的类别是 0-10, 一共 11 种, 10 代表不存在.
训练与测试
接下来调用 fit 方法训练就好了, 这里一共有 7 个 loss 和 6 个 accuracy.loss 的话是每个 softmax 输出层都有一个, 还有个总的. accuracy 就是 6 个 softmax 层的 accuracy 了.
最后我们 evaluate 一下, 可以 6 个 accuracy 都达到了 85% 以上的准确率了. 如果想提高的话, 可以使用 VGG16 等结构, 网上说可以提升到百分之 97, 不过训练的话估计就要很慢了.
扩展案例: 微博验证码
另外, 笔者这里还使用该方法给出了新浪微博的登录验证码识别的实现代码, 见: captcha-break/weibo.com.
不过不知道现在新浪微博的验证码变了没有, 我当时用云打码的时候它的验证码长下面这个样子:
参考
https://github.com/potterhsu/SVHNClassifier
来源: https://juejin.im/post/5c04e342f265da6165015391