用TensorFlow进行算法设计、训练的核心步骤:
(1)定义算法公式,即神经网络forward时的计算。
(2)定义loss,选定优化器,并指定优化器优化loss。
(3)迭代地对数据进行训练。
(4)在测试集或验证集上对准确率进行测评。
MNIST(Mixed National Institute of Standards and Technology database)是一个非常简单的机器视觉数据集,由几万张28像素*28像素的手写数字组成,这些图片只包含灰度值信息。任务是对这些手写数字的图片进行分类,转成0~9一共10类。
mnist数据集中的训练集有55000个样本,测试集有10000个样本,验证集有5000个样本,每个样本都有其对应的标注信息,即Label。在训练集上训练模型,在验证集上检验效果并决定何时完成训练,最后在测试集上评测模型的效果。
每个样本有28*28=784维特征,这里丢弃了图片的二维结构方面的信息,只是把图片变成一个很长的一维向量。
我们训练数据的特征是一个55000*784的Tensor,第一个维度是图片的编号,第二个维度是图片中像素点的编号,训练数据的Label是一个55000*10的Tensor,这里对10个种类进行one-hot编码,Label是一个10维的向量,只有一个值为1,其余值为0。
One-hot编码(独热编码)
独热编码使用N位代表N种状态,任意时候只有其中一位有效。
采用独热编码的例子
性别:
[0, 1]代表女,[1, 0]代表男
数字0-9:
[0,0,0,0,0,0,0,0,0,1]代表9,[0,1,0,0,0,0,0,0,0,0]代表1
独热编码的优点
- 能够处理非连续型数值特征
- 在一定程度上也扩充了特征。比如性别本身是一个特征,经过编码以后,就变成了男或女两个特征。
- 在神经网络中,独热编码其实具有很强的容错性,比如神经网络的输出结果是 [0,0.1,0.2,0.7,0,0,0,0,0, 0]转成独热编码后,表示数字3。即值最大的地方变为1,其余均为0。[0,0.1,0.4,0.5,0,0,0,0,0, 0]也能表示数字3。numpy中有一个函数,numpy.argmax()可以取得最大值的下标。
缺点:是具有稀疏性
神经网络的重要概念
输入(x)输出(y)、标签(label)
输入是指传入给网络处理的向量,相当于数学函数中的变量。
输出加粗样式是指网络处理后返回的结果,相当于数据函数中的函数值。
标签是指我们期望网络返回的结果。
对于识别mnist图片而言,输入是大小为784(28 * 28)的向量,输出是大小为10的概率向量(概率最大的位置,即预测的数字)。
损失函数(loss function)
损失函数评估网络模型的好坏,值越大,表示模型越差,值越小,表示模型越好。模型的训练目标,就是将损失函数的值降到最小。
常见的损失函数定义:
-
差的平方和 sum((y - label)^2)
[0, 0, 1] 与 [0.1, 0.3, 0.6]的差的平方和为 0.01 + 0.09 + 0.16 = 0.26
[0, 0, 1] 与 [0.2, 0.2, 0.6]的差的平方和为 0.04 + 0.04 + 0.16 = 0.24
[0, 0, 1] 与 [0.1, 0, 0.9]的差的平方和为 0.01 + 0.01 = 0.02 -
交叉熵 -sum(label * log(y))
[0, 0, 1] 与 [0.1, 0.3, 0.6]的交叉熵为 -log(0.6) = 0.51
[0, 0, 1] 与 [0.2, 0.2, 0.6]的交叉熵为 -log(0.6) = 0.51
[0, 0, 1] 与 [0.1, 0, 0.9]的交叉熵为 -log(0.9) = 0.10
当label为0时,交叉熵为0,label为1时,交叉熵为-log(y),交叉熵只关注独热编码中有效位的损失。这样屏蔽了无效位值的变化(无效位的值的变化并不会影响最终结果),并且通过取对数放大了有效位的损失。当有效位的值趋近于0时,交叉熵趋近于正无穷大,说明预测效果很不好。
Softmax Regression算法
Softmax Regression会对每一种类别估算一个概率:若预测是数字3的概率为5%,是数字5的概率为80%,最后取概率最大的那个数字作为模型的输出结果。
输出(Y)= Softmax(Wx+b)
损失(loss)= -label*log(Y)
预测值(P)= argmax(Y)
# -*- coding: utf-8 -*-
"""
Created on Wed Mar 7 09:29:56 2018
@author: wf
"""
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
mnist=input_data.read_data_sets('MNIST_data/',one_hot=True)#load data
#print(mnist.train.images.shape,mnist.train.labels.shape)
#print(mnist.test.images.shape,mnist.test.labels.shape)
#print(mnist.validation.images.shape,mnist.validation.labels.shape)
sess=tf.InteractiveSession()
x=tf.placeholder(tf.float32,[None,784])#设置输入特征
W=tf.Variable(tf.zeros([784,10]))#初始化权重
b=tf.Variable(tf.zeros([10]))#初始化偏差
y=tf.nn.softmax(tf.matmul(x,W)+b)#搭建softmax模型 y=wx+b
y_=tf.placeholder(tf.float32,[None,10])#input real label
#设置损失函数为交叉熵
cross_entropy=tf.reduce_mean(-tf.reduce_sum(y_*tf.log(y),reduction_indices=[1]))
#定义随机梯度下降最小化损失函数,学习率0.5,优化目标设定为cross-entropy
train_step=tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
tf.global_variables_initializer().run()#全局参数初始化
for i in range(1000):
batch_xs,batch_ys=mnist.train.next_batch(100)#获取batch
train_step.run({x:batch_xs,y_:batch_ys}) #开始训练
#tf.argmax(y,1)求各个预测的数字中概率最大的那个
correct_prediction=tf.equal(tf.argmax(y,1),tf.argmax(y_,1)) #判断类别--》 bool值
accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
print(accuracy.eval({x:mnist.test.images,y_:mnist.test.labels}))
#print(accuracy.eval({x:mnist.validation.images,y_:mnist.validation.labels}))
准确率为92%,虽然是一个还不错的数字,但是还达不到实用的程度。手写数字识别的应用场景是识别银行支票,需很高的准确度。后面用多层感知机和卷积网络来解决MNIST手写数字识别问题的方法。