最近自己尝试了网上的验证码识别代码项目,该小项目见以下链接:
>https://cuijiahua.com/blog/2018/01/dl_5.html

数据也就用了作者上传的60000张Discuz验证码。作者是创建了一个 封装了所有的变量和函数,我看了他的代码之后自己尝试着不用类去实现该网络。

作者说自己可以训练到90%以上的精度。然而我看了他的代码后发现,作者是用训练过的数据来进行测试,即训练集和测试集是一样的

我想着,测试集应该是不能参与训练过程中的,比如说我们在做mnist手写数字识别的时候,训练集与测试集就一定是不一样的。

from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("/tmp/data/", one_hot=False) Extracting /tmp/data/train-images-idx3-ubyte.gz
Extracting /tmp/data/train-labels-idx1-ubyte.gz
Extracting /tmp/data/t10k-images-idx3-ubyte.gz
Extracting /tmp/data/t10k-labels-idx1-ubyte.gz

于是我在自己实现的过程中,将数据集打乱后取10000个作为测试集,不参与训练,剩余的50000张验证码作为训练集。

训练过程中发现只有将学习率设置为0.001时,loss才会降下去,太高,loss会卡在0.07;其次,我的训练精度最多只能到50%左右,但是我用训练数据来测试保存的模型,精度确实达到了90%,即作者看到的精度。不过这个模型不具有泛化能力,它在没见过的测试集上只有50%的精确度。

同时这个代码还有问题:测算精确度时,一张图中4个验证码有两个错误的话,正确率是50%而不是0.当一张图中4个验证码识别有一个错误时,该验证码识别就应该是失败的。因此这个精确度实在是有相当大的水分。

于是要考虑解决办法。首先我尝试着下调学习率,发现永远还是到50%就上不去了。

接下来我在原来的3层卷积层上,又加了一层卷积层。然而这并没有提升多少精度。

随后我又加入了一层全连接层,期望可以拟合得更好一些,但是这样让我陷入了麻烦。

我的loss值卡在了0.07,无论我的学习率是0.1还是0.00001.哪怕迭代一百万次也是如此。这时候的测试精度只有······3%。

我不知道是什么问题更不知道如何改进。

这更让我觉得没有人带我,多么地难受;同时也更深刻地体验到理论知识是多么地重要(当然我一直知道)。

我自己的代码附上,大家可以相互交流。数据可以在文章顶部的链接里下载,作者压缩好的。

以下是训练脚本:(理论上python3和python2应该都能跑。我是用2写的)

训练中我使用了学习率衰减,本来还想用dropout结果发现这个训练基本不给我过拟合的机会所以训练加了没有意义。

from __future__ import print_function, division, absolute_import
import tensorflow as tf
import os
import cv2
import matplotlib.pyplot as plt
import random
import numpy as np
from optparse import OptionParser path = 'Discuz/' #存放数据的路径
imgs = os.listdir(path) #以列表形式读取所有图片名称
random.shuffle(imgs) #打乱
max_steps = 1000000 #最大迭代步数
save_path = 'model4cnn-1fcn' #保存模型的路径,会自动生成
dropout = 1 #没用到 trainnum = 50000 #定义训练集和测试集的大小
testnum = 10000 traindatas = imgs[:trainnum] #取出训练集和测试集及其标签
trainlabels = list(map(lambda x: x.split('.')[0],traindatas)) testdatas = imgs[trainnum:]
testlabels = list(map(lambda x: x.split('.')[0],testdatas)) #定义取数据集的指针
train_ptr = 0
test_ptr = 0 def next_batch(batch=100, train_flag=True):
global train_ptr
global test_ptr
batch_x = np.zeros([batch,30*100])
batch_y = np.zeros([batch, 4*63]) if train_flag == True:
if batch + train_ptr < trainnum:
trains = traindatas[train_ptr:(train_ptr+batch)]
labels = trainlabels[train_ptr:(train_ptr+batch)]
train_ptr += batch
else:
new_ptr = (train_ptr + batch) % trainnum
trains = traindatas[train_ptr:] + traindatas[:new_ptr]
labels = trainlabels[train_ptr:] + traindatas[:new_ptr]
train_ptr = new_ptr for index, train in enumerate(trains):
img = np.mean(cv2.imread(path + train), -1)
batch_x[index,:] = img.flatten() /255
for index, label in enumerate(labels):
batch_y[index,:] = text2vec(label) else:
if batch + test_ptr < testnum:
tests = testdatas[test_ptr:(test_ptr+batch)]
labels = testlabels[test_ptr:(test_ptr+batch)]
test_ptr += batch
else:
new_ptr = (test_ptr + batch) % testnum
tests = testdatas[test_ptr:] + testdatas[:new_ptr]
labels = testlabels[test_ptr:] + testlabels[:new_ptr]
test_ptr = new_ptr for index, test in enumerate(tests):
img = np.mean(cv2.imread(path + test), -1)
batch_x[index, :] = img.flatten() /255
for index, label in enumerate(labels):
batch_y[index,:] = text2vec(label) return batch_x, batch_y def text2vec(text):
if len(text) > 4:
raise ValueError('too long captcha') vector = np.zeros(4*63)
def char2pos(c):
if c == '_':
k = 62
return k
k = ord(c)-48
if k > 9:
k = ord(c)-55
if k > 35:
k = ord(c) - 61
if k > 61:
raise ValueError('No Map') return k for i, c in enumerate(text):
idx = i*63 + char2pos(c)
vector[idx] = 1 return vector X = tf.placeholder(tf.float32, [None, 30*100])
Y = tf.placeholder(tf.float32, [None,4*63])
_lr = tf.placeholder(tf.float32)
keep_prob = tf.placeholder(tf.float32) def conv2d(x, W, b, strides=1):
x = tf.nn.conv2d(x, W, strides=[1, strides, strides, 1], padding='SAME')
x = tf.nn.bias_add(x, b)
return tf.nn.relu(x) def max_pool2d(x, k=2):
x = tf.nn.max_pool(
x, ksize=[
1, k, k, 1], strides=[
1, k, k, 1], padding='SAME')
return x weights = {
'wc1': tf.Variable(0.01*tf.random_normal([3, 3, 1, 32])),
'wc2': tf.Variable(0.01*tf.random_normal([3, 3, 32, 64])),
'wc3': tf.Variable(0.01*tf.random_normal([3, 3, 64, 64])),
'wc4': tf.Variable(0.01*tf.random_normal([3, 3, 64, 64])),
'wf1': tf.Variable(0.01*tf.random_normal([2 * 7 * 64, 1024])),
'wf2': tf.Variable(0.01*tf.random_normal([1024, 1024])),
'wout': tf.Variable(0.01*tf.random_normal([1024, 4*63]))
} biases = {
'bc1': tf.Variable(0.1*tf.random_normal([32])),
'bc2': tf.Variable(0.1*tf.random_normal([64])),
'bc3': tf.Variable(0.1*tf.random_normal([64])),
'bc4': tf.Variable(0.1*tf.random_normal([64])),
'bf1': tf.Variable(0.1*tf.random_normal([1024])),
'bf2': tf.Variable(0.1*tf.random_normal([1024])),
'bout': tf.Variable(0.1*tf.random_normal([4*63]))
} def conv_net(x, weights, biases, dropout):
x = tf.reshape(x, [-1,100,30,1]) conv1 = conv2d(x, weights['wc1'], biases['bc1'], 1)
conv1 = max_pool2d(conv1, 2) conv2 = conv2d(conv1, weights['wc2'], biases['bc2'], 1)
conv2 = max_pool2d(conv2, 2) conv3 = conv2d(conv2, weights['wc3'], biases['bc3'], 1)
conv3 = max_pool2d(conv3, 2) conv4 = conv2d(conv3, weights['wc4'], biases['bc4'], 1)
conv4 = max_pool2d(conv4, 2) fc1 = tf.reshape(
conv4, shape=[-1, weights['wf1'].get_shape().as_list()[0]])
fc1 = tf.matmul(fc1, weights['wf1'])
fc1 = tf.add(fc1, biases['bf1'])
fc1 = tf.nn.relu(fc1) out = tf.add(tf.matmul(fc1, weights['wout']), biases['bout']) return out output = conv_net(X, weights, biases, keep_prob) loss_op = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(
logits=output, labels=Y))
optimizer = tf.train.AdamOptimizer(learning_rate=_lr).minimize(loss_op) y = tf.reshape(output, [-1,4,63])
y_ = tf.reshape(Y, [-1,4,63]) correct_pred = tf.equal(tf.argmax(y, 2), tf.argmax(y_,2))
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
init = tf.global_variables_initializer()
lr = 0.001
saver = tf.train.Saver()
with tf.Session() as sess:
sess.run(init)
for step in range(1,1+max_steps):
batch_x, batch_y = next_batch(100,True)
loss_value,_ = sess.run([loss_op, optimizer],
feed_dict = {X:batch_x, Y:batch_y, keep_prob:dropout,_lr:lr})
if step % 10 == 0:
batch_x_test, batch_y_test = next_batch(100, False)
acc = sess.run(accuracy,
feed_dict={X:batch_x_test, Y:batch_y_test,keep_prob:1})
print('step{}, loss={}, accuracy={}'.format(step,loss_value, acc)) if step % 500 == 0:
random.shuffle(traindatas)
trainlabels = list(map(lambda x: x.split('.')[0],traindatas)) if step % 3000 == 0:
lr *= 0.9 if step % 10000 == 0:
saver.save(sess, save_path + "/model.ckpt-%d" % step)
print('model saved!')

接下来是我写的一个直观观察训练效果的,新建一个脚本,添加如下代码,然后运行该脚本,将会随机展示4张验证码和你的预测结果,终端还会显示本次预测的精确度。

from __future__ import print_function, division, absolute_import
import tensorflow as tf
import os
import cv2
import matplotlib.pyplot as plt
import random
import numpy as np
from datasplit import use
#from optparse import OptionParser testnumber = 4 #要更改的话需要改画图部分的代码否则会出错
path = 'Discuz/'
imgs = os.listdir(path)
model_path = 'model4cnn-1fcn/model.ckpt-500000' #读取你训练好的模型
testdatas = random.sample(imgs,testnumber)
testlabels = list(map(lambda x: x.split('.')[0],testdatas))
#testnum = len(testdatas)
#test_ptr = 0 X = tf.placeholder(tf.float32, [None, 30*100])
Y = tf.placeholder(tf.float32, [None,4*63])
keep_prob = tf.placeholder(tf.float32) def text2vec(text):
if len(text) > 4:
raise ValueError('too long captcha') vector = np.zeros(4*63)
def char2pos(c):
if c == '_':
k = 62
return k
k = ord(c)-48
if k > 9:
k = ord(c)-55
if k > 35:
k = ord(c) - 61
if k > 61:
raise ValueError('No Map') return k for i, c in enumerate(text):
idx = i*63 + char2pos(c)
vector[idx] = 1 return vector def vec2text(vec): char_pos = vec.nonzero()[0]
text = []
for i, c in enumerate(char_pos):
char_at_pos = i #c/63
char_idx = c % 63
if char_idx < 10:
char_code = char_idx + ord('0')
elif char_idx < 36:
char_code = char_idx - 10 + ord('A')
elif char_idx < 62:
char_code = char_idx - 36 + ord('a')
elif char_idx == 62:
char_code = ord('_')
else:
raise ValueError('error')
text.append(chr(char_code))
return "".join(text) batch_x = np.zeros([testnumber,30*100])
batch_y = np.zeros([testnumber, 4*63]) for index, test in enumerate(testdatas):
img = np.mean(cv2.imread(path + test), -1)
batch_x[index, :] = img.flatten() /255
for index, label in enumerate(testlabels):
batch_y[index, :] = text2vec(label) def conv2d(x, W, b, strides=1):
x = tf.nn.conv2d(x, W, strides=[1, strides, strides, 1], padding='SAME')
x = tf.nn.bias_add(x, b)
return tf.nn.relu(x) def max_pool2d(x, k=2):
x = tf.nn.max_pool(
x, ksize=[
1, k, k, 1], strides=[
1, k, k, 1], padding='SAME')
return x weights = {
'wc1': tf.Variable(0.01*tf.random_normal([3, 3, 1, 32])),
'wc2': tf.Variable(0.01*tf.random_normal([3, 3, 32, 64])),
'wc3': tf.Variable(0.01*tf.random_normal([3, 3, 64, 64])),
'wc4': tf.Variable(0.01*tf.random_normal([3, 3, 64, 64])),
'wf1': tf.Variable(0.01*tf.random_normal([2 * 7 * 64, 1024])),
'wf2': tf.Variable(0.01*tf.random_normal([1024, 1024])),
'wout': tf.Variable(0.01*tf.random_normal([1024, 4*63]))
} biases = {
'bc1': tf.Variable(0.1*tf.random_normal([32])),
'bc2': tf.Variable(0.1*tf.random_normal([64])),
'bc3': tf.Variable(0.1*tf.random_normal([64])),
'bc4': tf.Variable(0.1*tf.random_normal([64])),
'bf1': tf.Variable(0.1*tf.random_normal([1024])),
'bf2': tf.Variable(0.1*tf.random_normal([1024])),
'bout': tf.Variable(0.1*tf.random_normal([4*63]))
} def conv_net(x, weights, biases, dropout):
x = tf.reshape(x, [-1,100,30,1]) conv1 = conv2d(x, weights['wc1'], biases['bc1'], 1)
conv1 = max_pool2d(conv1, 2) conv2 = conv2d(conv1, weights['wc2'], biases['bc2'], 1)
conv2 = max_pool2d(conv2, 2) conv3 = conv2d(conv2, weights['wc3'], biases['bc3'], 1)
conv3 = max_pool2d(conv3, 2) conv4 = conv2d(conv3, weights['wc4'], biases['bc4'], 1)
conv4 = max_pool2d(conv4, 2) fc1 = tf.reshape(
conv4, shape=[-1, weights['wf1'].get_shape().as_list()[0]])
fc1 = tf.matmul(fc1, weights['wf1'])
fc1 = tf.add(fc1, biases['bf1'])
fc1 = tf.nn.relu(fc1) out = tf.add(tf.matmul(fc1, weights['wout']), biases['bout']) return out output = conv_net(X, weights, biases, keep_prob) y = tf.reshape(output, [-1,4,63])
y_ = tf.reshape(Y, [-1,4,63]) predict = tf.argmax(y,2)
correct_pred = tf.equal(predict, tf.argmax(y_,2))
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
saver = tf.train.Saver() with tf.Session() as sess:
saver.restore(sess, model_path) pred, acc = sess.run([predict,accuracy], feed_dict ={ X:batch_x, Y:batch_y,keep_prob:1})
print('accuracy={}'.format(acc))
for i in range(1,testnumber+1): plt.subplot(2,2,i)
img = cv2.imread(path+testdatas[i-1])
plt.imshow(img)
plt.title('number%d' %i)
plt.xticks([])
plt.yticks([])
vect = np.zeros([4*63]) #print(pred[i-1])
for ind,j in enumerate(pred[i-1]):
vect[ind*63+j] = 1 xlabel = 'True label:{};Pred label:{}'.format(testlabels[i-1], vec2text(vect))
plt.xlabel(xlabel) plt.show()

有任何问题欢迎讨论。

神经网络实现Discuz验证码识别的更多相关文章

  1. Tensorflow实战(二):Discuz验证码识别

    一.前言 验证码是根据随机字符生成一幅图片,然后在图片中加入干扰象素,用户必须手动填入,防止有人利用机器人自动批量注册.灌水.发垃圾广告等等 . 验证码的作用是验证用户是真人还是机器人. 本文将使用深 ...

  2. 字符型图片验证码,使用tensorflow实现卷积神经网络,进行验证码识别CNN

    本项目使用卷积神经网络识别字符型图片验证码,其基于 TensorFlow 框架.它封装了非常通用的校验.训练.验证.识别和调用 API,极大地减低了识别字符型验证码花费的时间和精力. 项目地址: ht ...

  3. 使用卷积神经网络CNN完成验证码识别

    gen_sample_by_captcha.py 生成验证码图片 # -*- coding: UTF-8 -*- """ 使用captcha lib生成验证码(前提:pi ...

  4. Matlab神经网络验证码识别

    本文,将会简述如何利用Matlab的强大功能,调用神经网络处理验证码的识别问题.  预备知识,Matlab基础编程,神经网络基础.  可以先看下: Matlab基础视频教程 Matlab经典教程--从 ...

  5. 写给程序员的机器学习入门 (八) - 卷积神经网络 (CNN) - 图片分类和验证码识别

    这一篇将会介绍卷积神经网络 (CNN),CNN 模型非常适合用来进行图片相关的学习,例如图片分类和验证码识别,也可以配合其他模型实现 OCR. 使用 Python 处理图片 在具体介绍 CNN 之前, ...

  6. 验证码进阶(TensorFlow--基于卷积神经网络的验证码识别)

    本人的第一个深度学习实战项目,参考了网络上诸多牛人的代码,在此谢过,因时间久已,不记出处,就不一一列出,罪过罪过. 我的数据集是我用脚本在网页上扒的,标签是用之前写的验证码识别方法打的.大概用了400 ...

  7. 字符型图片验证码识别完整过程及Python实现

    字符型图片验证码识别完整过程及Python实现 1   摘要 验证码是目前互联网上非常常见也是非常重要的一个事物,充当着很多系统的 防火墙 功能,但是随时OCR技术的发展,验证码暴露出来的安全问题也越 ...

  8. 基于tensorflow的‘端到端’的字符型验证码识别源码整理(github源码分享)

    基于tensorflow的‘端到端’的字符型验证码识别 1   Abstract 验证码(CAPTCHA)的诞生本身是为了自动区分 自然人 和 机器人 的一套公开方法, 但是近几年的人工智能技术的发展 ...

  9. [验证码识别技术]字符验证码杀手--CNN

    字符验证码杀手--CNN 1 abstract 目前随着深度学习,越来越蓬勃的发展,在图像识别和语音识别中也表现出了强大的生产力.对于普通的深度学习爱好者来说,一上来就去跑那边公开的大型数据库,比如I ...

随机推荐

  1. mybatis学习(六)——参数处理

    先总结一下,后面再一个个解释: 单个参数:直接使用#{参数名}进行取值,mybatis没做特殊处理,参数名可以随便写. 多个参数:使用#{param1},#{param2}取值 命名参数:通过@par ...

  2. bzoj 4804 欧拉心算 欧拉函数,莫比乌斯

    欧拉心算 Time Limit: 15 Sec  Memory Limit: 256 MBSubmit: 408  Solved: 244[Submit][Status][Discuss] Descr ...

  3. redhat安装Xvfb

    1.下载xvfb的rpm包进行安装 下载rpm安装包:http://rhn.redhat.com/errata/RHBA-2013-0083.html 安装rpm包:#rpm -ivh --nodep ...

  4. javascript进阶一

    一 window对象 http://www.w3school.com.cn/jsref/dom_obj_window.asp 二 setInterval的应用 模拟计时器 <!DOCTYPE h ...

  5. es6 Number.isFinite()、Number.isNaN()、Number.isInteger()、Math.trunc()、Math.sign()、Math.cbrt()、Math.fround()、Math.hypot()、Math 对数方法

    ES6在Number对象上,新提供了Number.isFinite()和Number.isNaN()两个方法,用来检查Infinite和NaN这两个特殊值. Number.isFinite()用来检查 ...

  6. Codeforces 877E Danil and a Part-time Job(dfs序 + 线段树)

    题目链接   Danil and a Part-time Job 题意    给出一系列询问或者修改操作 $pow$ $x$表示把以$x$为根的子树的所有结点的状态取反($0$变$1$,$1$变$0$ ...

  7. HDU 5890 Eighty seven(DP+bitset优化)

    题目链接 Eighty seven 背包(用bitset预处理)然后对于每个询问O(1)回答即可. 预处理的时候背包. #include <bits/stdc++.h> using nam ...

  8. Codeforces 691E Xor-sequences

    矩阵快速幂.递推式:dp[k][i]=sum(dp[k-1][j]*f[i][j]),dp[k][i]表示的意义是序列中有k个元素,最后一个元素是i的方案数,f[i][j]=1表示i与j能放在一起,反 ...

  9. Oracle 12c JDBC方式连接PDB数据库

    1.配置监听 这里假定CDB数据库名为ORCL,PDB在CDB下面名称为PDBORCLlistener.ora添加(#后面为注释,不要添加进去) SID_LIST_LISTENER = (SID_LI ...

  10. C#深入学习:泛型修饰符in,out、逆变委托类型和协变委托类型

    在C#中,存在两个泛型修饰符:in和out,他们分别对应逆变委托和协变委托. 我们知道,在C#中要想将一个泛型对象转换为另一个泛型对象时,必须要将一个泛型对象拆箱,对元素进行显式或隐式转换后重新装箱. ...