这是《使用腾讯云GPU学习深度学习》系列文章的第五篇,以车牌识别和简单OCR为例,谈了谈如何进行字母、数字的识别以及定位。本系列文章主要介绍如何使用腾讯云GPU服务器进行深度学习运算,前面主要介绍原理部分,后期则以实践为主。
往期内容:
使用腾讯云 GPU 学习深度学习系列之一:传统机器学习的回顾
使用腾讯云 GPU 学习深度学习系列之二:Tensorflow 简明原理
使用腾讯云 GPU 学习深度学习系列之三:搭建深度神经网络
使用腾讯云 GPU 学习深度学习系列之四:深度学习的特征工
上一节,我们简要介绍了一些与深度学习相关的数据预处理方法。其中我们特别提到,使用 基于深度学习的 Spatial Transform 方法,可以让“草书” 字体的手写数字同样也可以被高效识别。
但无论是工整书写的 Tensorflow 官网上的 MNIST 教程,还是上节提到“草书”数字,都是 单一的数字识别问题。 但是,在实际生活中,遇到数字、字母识别问题时,往往需要识别一组数字。这时候一个简单的深度神经网络可能就做不到了。本节内容,就是在讨论遇到这种情况时,应该如何调整深度学习模型。
固定长度的字符、数字识别,比较常见的应用场景包括:
识别验证码
识别机动车车牌
识别验证码的方法,这篇文章 有详细介绍。不过该文章使用的是版本较早的 Keras1,实际使用时会有一些问题。如果想尝试,根据Jupyter 的提示更改就好,最终效果也是相当不错:
我们这里要识别的内容,是中华人民共和国机动车车牌。相比上面例子的 4 位验证码,车牌长度更长,达到了 7 位,并且内容也更加丰富,第一位是各省的汉字简称,第二位是 A-Z 的大写字母,3-7位则是数字、字母混合。
由于车牌涉及个人隐私,我们使用了用户 szad670401 在 Github 上开源的一个车牌生成器,随机的生成一些车牌的图片,用于模型训练。当然这个项目同样提供了完整的 <code>MXNet</code> 深度学习框架编写的代码,我们接下来会用 <code>Keras</code> 再写一个。
首先做些准备工作,从 szad670401 的开源项目中获取必要的文件:
来看看生成器的效果:
看来 szad670401 开源的车牌生成器,随机生成的车牌确实达到了以假乱真的效果。于是我们基于这个生成器,再自己写一个生成器,用于深度神经网络的数据输入:
因为是固定长度,所以我们有个想法,就是既然我们知道识别七次,那就可以用七个模型按照顺序识别。这个思路没有问题,但实际上根据之前卷积神经网络的原理,实际上卷积神经网络在扫描整张图片的过程中,已经对整个图像的内容以及相对位置关系有所了解,所以,七个模型的卷积层实际上是可以共享的。我们实际上可以用一个 一组卷积层+7个全链接层 的架构,来对应输入的车牌图片:
训练模型:
可见五轮训练后,即便是位置靠后的几位车牌,也实现了 93% 的识别准确率。
展示下模型预测结果:
可见预测的其实相当不错,很多字体已经非常模糊,模型仍然可以看出来。图中一个错误是 皖TQZ680 被预测成了 皖TQZG8D,当然这也和图片裁剪不当有一定的关系。
车牌的应用场景中,我们固定了长度为7位,并且基于这个预设设计了卷积神经网络。但是在实际运用中,可能长度并不固定。此时如果长度过长,用这个架构也将会导致参数过多,占用过多显存。
针对这种情况,Keras 的案例中,提供了一种基于循环神经网络的方法,在 Keras Example 中有写到。具体而言,就是数据首先通过卷积神经网络部分扫描特征,然后通过循环神经网络部分,同时从左到右、从右到左扫描特征,最后基于扫描的结果,通过计算 Conectionist Temporal Classification(CTC) 损失函数,完成模型训练。
使用循环神经网络,是因为循环神经网络有一个很重要的特点,就是相邻的节点之间,可以相互影响。这里相邻节点,既可以是时间上的(前一秒数据和后一秒数据),也可以是位置关系上的,比如我们这里从左向右扫描,左边一列的扫描结果会影响右边一列的扫描结果。
图片来源:知乎:CNN(卷积神经网络)、RNN(循环神经网络)、DNN(深度神经网络)的内部网络结构有什么区别。
同时,对于循环神经网络的结果,由于长度不固定,可能会有空间上的“错配”:
图片来源:Connectionist Temporal Classification: Labelling Unsegmented Sequence Data with Recurrent Neural Networks
但由于这种错配实际上并没有什么严重的影响,如上图所示, <code>__TH____E</code> 和 <code>_T__H__EE</code> 其实都是 THE 这个单词,因此这里这种错配在损失函数的优化环节中,是需要被忽略掉的。于是这里就使用了<code>CTC</code> 优化函数。<code>CTC</code> 可以在计算过程中,通过综合所有可能情况的排列组合,进而忽略相对的位置关系。
Keras 的 CTC loss 函数位于 https://github.com/fchollet/keras/blob/master/keras/backend/tensorflow_backend.py 这个文件中,内容如下:
首先是一些必要的函数:
必要的参数:
使用这些函数以及对应参数构建生成器,生成不固定长度的验证码:
构建网络:
模型完整架构如下图所示:
执行训练:
完成一个 Epoch 后,输出文件夹 <code>image_ocr</code> 里,可以看到,一轮训练后,我们模型训练效果如下: