TensorFlow识别验证码

卷积神经网络很强大,我们这里只是识别4位的字母+数字的验证码,如果我们有大量中文的验证码作为学习材料,识别中文也是可以的。也就是说:我们喂给模型什么东西,它就学到什么。

更多:TensorFlow

第06课:TensorFlow 实战二:验证码识别

一、前期回顾:

通过前面几篇文章,大家应该已经初步掌握了:如何使用 TensorFlow,如何搭建一个 CNN 模型,如何对模型进行优化,如何对模型进行可视化。

本篇文章,将和大家一起解决一个实际问题:“破解验证码”。

二、需要准备的:

  • 一台有 NVIDIA 显卡的电脑,因为这次的模型比较大,如果是用 CPU 训练起来会很慢,甚至直接死机。如果没有好显卡,也可以在 AWS(亚马逊云)上申请一个竞价的 GPU 服务器,一个小时也就几块钱,租几个小时即可,比国内要便宜的多。后面我可以写一篇如何在 AWS 上租服务器的文章。
  • 先安装好 Keras、captcha、tqdm 这几个包

三、代码实现:

1,生成随机验证码图片

我们自己做一个生成验证码的程序,这样可以生成无数的验证码进行学习

from captcha.image import ImageCaptcha
import matplotlib.pyplot as plt
import numpy as np
import random

//%matplotlib inline
//%config InlineBackend.figure_format = 'retina'

import string

###---------------
###一、生成随机验证码
### --------------
#设置字符集
characters = string.digits + string.ascii_uppercase
print(characters)

#设置图片长宽、字符个数和字符集类别数量
width, height, n_len, n_class = 170, 80, 4, len(characters)

#定义生成器
generator = ImageCaptcha(width=width, height=height)

#随机生成4个字符
random_str = ''.join([random.choice(characters) for j in range(n_len)])

#把字符转变成图片
img = generator.generate_image(random_str)

#显示图片
plt.imshow(img)
plt.title(random_str)



#定义数据生成器
def gen(batch_size=32):

    X = np.zeros((batch_size, height, width, 3), dtype=np.uint8)
    y = [np.zeros((batch_size, n_class), dtype=np.uint8) for i in range(n_len)]
    generator = ImageCaptcha(width=width, height=height)
    while True:
        for i in range(batch_size):
            # 生产随机字符
            random_str = ''.join([random.choice(characters) for j in range(4)])
            # 生产图片
            X[i] = generator.generate_image(random_str)
            # 把Y设置成4个列表
            for j, ch in enumerate(random_str):
                y[j][i, :] = 0
                y[j][i, characters.find(ch)] = 1
        yield X, y


#把数组y转换成字符

def decode(y):
    y = np.argmax(np.array(y), axis=2)[:,0]
    return ''.join([characters[x] for x in y])
图片生成的实例

2,构造模型

这里构造了一个比较深的模型,所以训练的速度会比较慢。

###---------------
###二、构造模型  ai8py.com
### --------------

from keras.models import *
from keras.layers import *
from keras.optimizers import *

input_tensor = Input((height, width, 3))
x = input_tensor
x = Lambda(lambda x:(x-127.5)/127.5)(x)

#搭建一个CNN,使用两个卷积、一个池化作为单元,循环4次;
#然后Flatten和Dropout,全连接
input_tensor = Input((height, width, 3))
x = input_tensor
for i in range(4):
    x = Convolution2D(32*2**i, 3, 3, activation='relu')(x)
    x = Convolution2D(32*2**i, 3, 3, activation='relu')(x)
    x = MaxPooling2D((2, 2))(x)

x = Flatten()(x)
x = Dropout(0.25)(x)
x = [Dense(n_class, activation='softmax', name='c%d'%(i+1))(x) for i in range(4)]

# 这里和之前不同的是,input和output指定方式不一样
model = Model(input=input_tensor, output=x)

model.compile(loss='categorical_crossentropy',
              optimizer='adadelta',
              metrics=['accuracy'])

# 查看模型
model.summary()
模型参数展示

3、训练模型

如果没有显卡,真心是慢。这……是不是给了大家升级机器配置的理由?O(∩_∩)O哈哈~

# 训练模型
model.fit_generator(gen(), samples_per_epoch=51200, nb_epoch=5, 
                    nb_worker=2, pickle_safe=True, 
                    validation_data=gen(), nb_val_samples=1280)
训练模型

4、测试结果

测试单次的结果:

 测试结果
X, y = next(gen(1))
y_pred = model.predict(X)
plt.title('real: %s\npred:%s'%(decode(y), decode(y_pred)))
plt.imshow(X[0], cmap='gray')
plt.axis('off')
单个样本测试

测试大批量样本的平均准确率:

from tqdm import tqdm
def evaluate(model, batch_num=100):
    batch_acc = 0
    generator = gen()
    for i in tqdm(range(batch_num)):
        X, y = generator.next()
        y_pred = model.predict(X)
        batch_acc += np.mean(map(np.array_equal, np.argmax(y, axis=2).T, np.argmax(y_pred, axis=2).T))
    return batch_acc / batch_num

evaluate(model)
平均准确率

小结

卷积神经网络很强大,我们这里只是识别4位的字母+数字的验证码,如果我们有大量中文的验证码作为学习材料,识别中文也是可以的。也就是说:我们喂给模型什么东西,它就学到什么。

到这里,TensorFlow 可以说已经入门了,如果希望能再深入学习。建议如下:

  • 目前机器学习中大部分应用都基于深度学习,这一次人工智能浪潮的到来,也是因为深度学习的发展,所以深度学习是目前推荐的方向。
  • 掌握了 TensorFlow,只是学会了一个工具,最多是“手中有剑”。我们还要对机器学习和深度学习的理论进行系统学习。
  • 在掌握了理论知识后,可以开始看各种学术论文,然后尝试自己实现。如果觉得实现有难度,可以到 GitHub 上去查找前人实现的代码。我们做过的事,肯定别人已经做过无数次了。
  • 看过若干论文和实现了若干论文上的模型后,相信你已经做到“手中有剑,心中也有剑”。可以到 Kaggle 上尝试参加比赛,加入我的深度学习爱好者社群,在群里大家思维一起碰撞,说不定就会找到 Magic Feature。

发表评论

电子邮件地址不会被公开。 必填项已用*标注