时间: 2020-09-03 00:08:26 人气: 2286 评论: 0
喜欢就关注我们吧!
原创文
JAVAandPython君
最近一直没出文,是因为最近在写一个爬虫项目,这个项目里面,碰到了一个比较棘手的事情,那就是验证码。各种方法用尽,最后我还是决定去训练自己的模型,但是,有一个问题---我深度学习可以说是0基础,这可咋弄?想来想去,我只能靠着百度&谷歌两位大佬来写了。
1 验证码样本获取(数据集的准备)
首先给大家基本的思路,最开始我们需要的是你的破解目标---验证码,因为每一个网站的验证码是不同的,所以我们需要获取你想要破解的验证码类型。
例如:
上面这个验证码就是我这几天折腾的验证码,我们看看它有些什么样的特征,为什么要看验证码的特征呢?因为我们需要大量的已标记的验证码数据集,已标记的验证码数据集又是啥意思?我直接给大家看张图吧↓
大家可以看到,每一张验证码的名字前面四个字母或数字刚好对应的就是我们验证码中的字母数字,这个就是我们待会需要训练的数据(我这里是准备了2w张)
但是一个问题来了,我怎么获取这些图片?去网站下载?那名字岂不是要我一个个改?当然不!虽然那也是一种方法,但是未免也太折磨人了...我这里就给大家推荐两个验证码生成的库,kaptcha(JAVA里的库) 和captcha(python里的库),我这次使用的是 kaptcha,因为我这个验证码需要设置相关的属性,例如验证码图片里面字体的颜色、各种效果,captcha里面貌似是不可以设置的,所以我就选择了kaptcha。验证码生成这一块大家可以直接去百度搜索这两个关键字:kaptcha,captcha。
2 处理数据集
处理数据集:
1.色彩在验证码中并不重要,我们将彩色验证码图片转为黑白,3维转1维,减少干扰数据。
2.将黑白验证码图片及其文本内容转化为数值数据。
3.设置验证码图片组,以便让图片数据分批次进行训练。
process.py
import numpy as np from demo1.getimg import file_name from demo1.getimg import load_allimg from demo1.getimg import CAPTCHA_HEIGHT, CAPTCHA_WIDTH, CAPTCHA_LEN, CAPTCHA_LIST import random import cv2 # 图片转为黑白,3维转1维 def convert2gray(img): if len(img.shape)>2: img = np.mean(img, -1) return img # 验证码文本转为向量 def text2vec(text,captcha_len=CAPTCHA_LEN, captcha_list=CAPTCHA_LIST): text_len = len(text) if text_len > captcha_len: raise ValueError("验证码超过4位啦!") vector = np.zeros(captcha_len * len(captcha_list)) for i in range(text_len): vector[captcha_list.index(text[i]) + i * len(captcha_list)] = 1 return vector # 验证码向量转为文本 def vec2text(vec, captcha_list=CAPTCHA_LIST, size=CAPTCHA_LEN): vec_idx = vec text_list = [captcha_list[v] for v in vec_idx] return ''.join(text_list) # 返回特定shape图片 def wrap_gen_captcha_text_and_image(shape=(CAPTCHA_HEIGHT, CAPTCHA_WIDTH, 3)): t_list = [] # flie_name方法是我自己定义的,获取目录中所有验证码图片的名字 t = file_name("E://DeskTop//codeimg") # 对名字进行处理,只保留前四位 for i in t: index = i.rfind('-') name = i[:index] t_list.append(name) # print(t_list) # 这个也是我定义的,获取所有的验证码图片对象 im = load_allimg() im_list = [] for i in range(0, len(im)): if im[i].shape == shape: im_list.append(im[i]) # print(len(im_list)) # print(len(t_list)) return t_list, im_list # 获取训练图片组 def next_batch(batch_count=60, width=CAPTCHA_WIDTH, height=CAPTCHA_HEIGHT): batch_x = np.zeros([batch_count, width * height]) batch_y = np.zeros([batch_count, CAPTCHA_LEN * len(CAPTCHA_LIST)]) text, image = wrap_gen_captcha_text_and_image() for i in range(batch_count): # 随机抽取一张图片 text_a = random.choice(text) image_a = image[text.index(text_a)] # print(text.index(text_a)) # print(text_a) image_a = convert2gray(image_a) # 将图片数组一维化 同时将文本也对应在两个二维组的同一行 batch_x[i, :] = image_a.flatten()/ 255 batch_y[i, :] = text2vec(text_a) # 返回该训练批次 return batch_x, batch_y if __name__ == '__main__': x,y = next_batch(batch_count=1) print(x,'\n\n',y)
运行之后返回的是如下结果:
3 创建模型、训练模型
创建模型:
这里用到了 5 层网络,前 3 层为卷积层,第 4、5 层为全连接层。对 4 层隐藏层都进行 dropout。网络结构如下所示: input——>conv——>pool——>dropout——>conv——>pool——>dropout——>conv——>pool——>dropout——>fully connected layer——>dropout——>fully connected layer——>output
训练数据
这里选择交叉熵损失函数。sigmod_cross适用于每个类别相互独立但不互斥,如图中可以有字母和数字。每批次采用 64 个训练样本,每训练100次测试一次样本识别的准确度,当准确度大于 95% 时保存模型,当准确度大于99%时训练结束。我们这里采用CPU来训练模型,我大概训练了6-7小时,准确度达到了99%。
train.py
import os import tensorflow as tf from demo1.process import next_batch from demo1.getimg import CAPTCHA_HEIGHT, CAPTCHA_WIDTH, CAPTCHA_LEN, CAPTCHA_LIST from datetime import datetime # 随机生成权重 def weight_variable(shape, w_alpha=0.01): initial = w_alpha * tf.random_normal(shape) return tf.Variable(initial) # 随机生成偏置项 def bias_variable(shape, b_alpha=0.1): initial = b_alpha * tf.random_normal(shape) return tf.Variable(initial) # 局部变量线性组合,步长为1,模式‘SAME’代表卷积后图片尺寸不变,即零边距 def conv2d(x, w): return tf.nn.conv2d(x, w, strides=[1, 1, 1, 1], padding='SAME') # max pooling,取出区域内最大值为代表特征, 2x2pool,图片尺寸变为1/2 def max_pool_2x2(x): return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME') # 三层卷积神经网络计算图 def cnn_graph(x, keep_prob, size, captcha_list=CAPTCHA_LIST, captcha_len=CAPTCHA_LEN): # 图片reshape为4维向量 image_height, image_width = size x_image = tf.reshape(x, shape=[-1, image_height, image_width, 1]) # 第一层 # filter定义为3x3x1, 输出32个特征, 即32个filter w_conv1 = weight_variable([3, 3, 1, 32]) b_conv1 = bias_variable([32]) # rulu激活函数 h_conv1 = tf.nn.relu(tf.nn.bias_add(conv2d(x_image, w_conv1), b_conv1)) # 池化 h_pool1 = max_pool_2x2(h_conv1) # dropout防止过拟合 h_drop1 = tf.nn.dropout(h_pool1, keep_prob) # 第二层 w_conv2 = weight_variable([3, 3, 32, 64]) b_conv2 = bias_variable([64]) h_conv2 = tf.nn.relu(tf.nn.bias_add(conv2d(h_drop1, w_conv2), b_conv2)) h_pool2 = max_pool_2x2(h_conv2) h_drop2 = tf.nn.dropout(h_pool2, keep_prob) # 第三层 w_conv3 = weight_variable([3, 3, 64, 64]) b_conv3 = bias_variable([64]) h_conv3 = tf.nn.relu(tf.nn.bias_add(conv2d(h_drop2, w_conv3), b_conv3)) h_pool3 = max_pool_2x2(h_conv3) h_drop3 = tf.nn.dropout(h_pool3, keep_prob) # 全连接层 image_height = int(h_drop3.shape[1]) image_width = int(h_drop3.shape[2]) w_fc = weight_variable([image_height * image_width * 64, 1024]) b_fc = bias_variable([1024]) h_drop3_re = tf.reshape(h_drop3, [-1, image_height * image_width * 64]) h_fc = tf.nn.relu(tf.add(tf.matmul(h_drop3_re, w_fc), b_fc)) h_drop_fc = tf.nn.dropout(h_fc, keep_prob) # 全连接层(输出层) w_out = weight_variable([1024, len(captcha_list) * captcha_len]) b_out = bias_variable([len(captcha_list) * captcha_len]) y_conv = tf.add(tf.matmul(h_drop_fc, w_out), b_out) return y_conv # 最小化loss def optimize_graph(y, y