15.4 示例:在TensorFlow下识别验证码(一)

完整演示代码请见本书GitHub上的15-1.py。

1.数据清洗与特征提取

我们依然使用MNIST数据集合,使用TensorFlow的softmax回归算法,MNIST详细介绍请参考第3章中的介绍。唯一不同的地方是我们使用one-hot编码处理标记数据,原有的标记数据使用长度为1的向量标记结果,取值范围为0~9,one-hot编码又称一位有效编码,其方法是使用N位状态寄存器来对N个状态进行编码,每个状态都有其独立的寄存器位,并且在任意时刻,其中只有一位有效。使用one-hot编码后,使用一个长度为10的向量标记结果,转换的函数实现为:


def get_one_hot(x,size=10):
    v=[]
    for x1 in x:
        x2=[0]*size
        x2[(x1-1)]=1
        v.append(x2)
    return v

我们使用离线版的MNIST文件,下载链接为:


http://www.iro.umontreal.ca/~lisa/deep/data/mnist/mnist.pkl.gz

文件读取方式为:


import pickle
import gzip
def load_data():
    with gzip.open('./mnist.pkl.gz') as fp:
        training_data, valid_data, test_data = pickle.load(fp)
    return training_data, valid_data, test_data

其中各个返回集合分别为:

·training_data,训练数据集合;

·valid_data,校验数据集合;

·test_data,测试数据集合。

加载数据,并针对标记数据转换成one-hot编码。


training_data, valid_data, test_dat=load_data()
x_training_data,y_training_data=training_data
x1,y1=test_dat
y_training_data=get_one_hot(y_training_data)
y1=get_one_hot(y1)

2.训练

我们使用经典的softmax回归算法来处理,如图15-9所示。

softmax算法的数学化的表现为:y=softmax(Wx+b)

使用TensorFlow的计算模型展现处理过程,如图15-10所示。

图15-9 TensorFlow官网对softmax算法的图解

图15-10 TensorFlow计算模型示例图

使用placeholder函数设置占位符,用于定义整个数据流的输入和输出。在这个例子中x和_y都是这种情况,其中,x对应整个系统输入,是一个维度为784的向量集合,且长度不限制;_y是整个系统的输出,对应一个维度为10的向量集合,两者的特征数据类型都是浮点型:


x = tf.placeholder("float", [None, 784])
y_ = tf.placeholder("float", [None,10])

定义整个系统中的变量,包括W、b,初始化均为0。整个系统的操作为y=softmax(Wx+b),x的维度为784,所以W为一个784乘以10的数组,b是一个维度为10的向量:


W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))

定义整个系统的操作函数:


y = tf.nn.softmax(tf.matmul(x,W) + b)

定义衰减函数,这里的衰减函数使用交叉熵来衡量,通过梯度下降算法以0.01的学习速率最小化交叉熵:


cross_entropy = -tf.reduce_sum(y_*tf.log(y))
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

初始化全部变量并定义会话,在TensorFlow中每个会话都是独立的,相互不干扰。


init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)

在理想情况下,我们希望用所有的数据来进行每一步的训练,因为这能给我们更好的训练结果,但显然这需要很大的计算开销。所以,每一次训练我们可以使用不同的数据子集,这样做既可以减少计算开销,又可以最大化地学习到数据集的总体特性。我们定义每次训练的数据子集的个数:


batch_size=100

每次我们都顺序取出100个数据用于训练,便于梯度下降算法快速收敛,整个训练次数取决于整个数据集合的长度以及每次训练的数据个数:


for i in range(int(len(x_training_data)/batch_size)):
    batch_xs=x_training_data[(i*batch_size):((i+1)*batch_size)]
    batch_ys=y_training_data[(i*batch_size):((i+1)*batch_size)]
    sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

3.验证

TensorFlow的数据验证非常简单,使用自带的API即可:


correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
print(sess.run(accuracy, feed_dict={x: x1, y_: y1}))

运行结果如下,准确率约为90%:


can't determine number of CPU cores: assuming 4
I tensorflow/core/common_runtime/local_device.cc:25] Local device intra op parallelism threads: 4
can't determine number of CPU cores: assuming 4
I tensorflow/core/common_runtime/local_session.cc:45] Local session inter op parallelism threads: 4
0.9097