MNIST手写字识别
流程:
1、将要识别的图片转为灰度图,并且转化为784矩阵(单通道,每个像素范围0-255,0为黑色,255为白色,这一点与MNIST中的正好相反)
2、将28*28的矩阵转换成1维矩阵[[784]](也就是把第2,3,4,5....行矩阵纷纷接入到第一行的后面)
3、用一个1*10的向量代表标签,也就是这个数字到底是几,举个例子e数字1对应的矩阵就是[0,1,0,0,0,0,0,0,0,0]
4、softmax回归预测图片是哪个数字的概率
5、用交叉熵和梯度下降法训练参数
注意:这里我建立的是单层神经网络
(1)softmax激活函数详解:
softmax直白来说就是将原来输出是3,1,-3通过softmax函数一作用,就映射成为(0,1)的值,而这些值的累和为1(满足概率的性质),那么我们就可以将它理解成概率,在最后选取输出结点的时候,我们就可以选取概率最大(也就是值对应最大的)结点,作为我们的预测目标!
像这里的MNIST要把它分成10类,就必须用softmax来进行分类了。
P(y=0)=p0,P(y=1)=p1,p(y=2)=p2......P(y=9)=p9.这些表示预测为数字i的概率,(跟上面标签的格式正好对应起来了),它们的和为1,即 ∑(pi)=1。
tensorflow实现了这个函数,我们直接调用这个softmax函数即可,原理图:
(2)交叉熵刻画了两个概率分布之间的距离,它是分类问题中使用比较广的一种损失函数。给定两个概率分布p和q,通过q来表示p的交叉熵为:
)
其中y_代表正确结果,y代表预测结果,tf.clip_by_value函数可以将一个张量中的数值限制在一个范围之内,tf.log完成对张量中所有元素依次求对数
,* 实现两个矩阵元素之间直接相乘(矩阵乘法需要使用tf.matmul函数来完成)。
注意:
交叉熵和最大似然估计的联系与区别
引用https://blog.csdn.net/diligent_321/article/details/53115369该文章的解释
在利用深度学习模型解决有监督问题时,比如分类、回归、去噪等,我们一般的思路如下:
(1)最大似然误差是从概率的角度,求解出能完美拟合训练样例的模型参数theta,使得概率p(y | x, theta)最大化;
(2)交叉熵损失函数,衡量的是两个分布p、q的相似性。在给定集合上两个分布p和q的cross entropy定义如下:
- 记带标签的样例为(x, y), 其中x表示输入特征向量,y=[y1, y2, ..., yc]表示真实标签的one-hot表示,y_=[y_1, y_2, ..., y_c]表示模型输出的分布,c表示样例输出的类别数,那么,
""" author:jiancgehng 2018.05.04 """ import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data import matplotlib.pyplot as plt#导入plt绘图模块 # number 1 to 10 data提前下下来了再“MNIST”文件夹下 mnist = input_data.read_data_sets('MNIST_data', one_hot=True)#one_hot一种编码格式0000000100(0-9数字)
建立网络层函数:
def add_layer(inputs, in_size, out_size, activation_function=None,): # #biases和Weights并不是纯随机数,一定的初始值跟有利于寻找到最优解 Weights = tf.Variable(tf.random_normal([in_size, out_size])) biases = tf.Variable(tf.zeros([1, out_size]) + 0.1,) Wx_plus_b = tf.matmul(inputs, Weights) + biases if activation_function is None: outputs = Wx_plus_b else: outputs = activation_function(Wx_plus_b,) return outputs
建立评估模型准确率公式:
""" tf.argmax(y_pre,1),tf.argmax(vector, 1):返回的是vector中的最大值的索引号,如果vector是一个向量,那就返回一个值, 如果是一个矩阵,那就返回一个向量,这个向量的每一个维度都是相对应矩阵行的最大值元素的索引号。 [[100000000]]输入,输出最大数的索引0 tf.equal(A, B)是对比这两个矩阵或者向量的相等的元素,如果是相等的那就返回True,反正返回False,返回的值的矩阵维度和A是一样的 将实际值和预测值进行比较,返回Bool数据类型 tf.cast(x, dtype, name=None) 将x的数据格式转化成dtype.例如,原来x的数据格式是bool, 那么将其转化成float以后,就能够将其转化成0和1的序列。 """ def compute_accuracy(v_xs, v_ys): global prediction#全局变量 y_pre = sess.run(prediction, feed_dict={xs: v_xs})#预测值 correct_prediction = tf.equal(tf.argmax(y_pre,1), tf.argmax(v_ys,1))#100个样本,就是1*100的向量 accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))#将上面的bool类型转为float,求得矩阵中所有元素的平均值 如:98/100=.98 result = sess.run(accuracy, feed_dict={xs: v_xs, ys: v_ys})#run()运行才能有结果 return result
以palceholder传入样本X值:
""" define placeholder for inputs to network 相当于一个容器,feed_dict()就是调用容器的方法 placeholder一共两个参数:1.数据类型,tf.float32或者“FLOAT32” 2.出入参数(矩阵)的形状,第一维None:不限制样本个数(X),第二维:特征个数 """ xs = tf.placeholder(tf.float32, [None, 784]) # 28x28,输入特征784个 ys = tf.placeholder(tf.float32, [None, 10])#输出10个数字
输出预测值:
# add output layer单层神经网络 #数字1对应的矩阵就是[0,1,0,0,0,0,0,0,0,0],输出结果为10个矩阵 prediction = add_layer(xs, 784, 10, activation_function=tf.nn.softmax)#错误:其实就是二分类问题,输出的10个数{0,1};多分类:tf.nn.softmax
计算损失值(准备反向传播):
""" the error between prediction and real data,损失值 tf.reduce_mean(input_tensor, reduction_indices=None, keep_dims=False, name=None) 计算一个张量的维数的平均值。如果还原指数没有条目,则所有维度都被还原,一个带有单个元素的张量被返回。 input_tensor: 张量减少。应该有数字类型。 reduction_indices: 尺寸减少。如果没有(默认),则减少所有维度。 keep_dims: 如果是真的,则保留长度为1的维度。 name: 操作的名称 -tf.reduce_sum(ys * tf.log(prediction),reduction_indices=[1]) """ cross_entropy = tf.reduce_mean(-tf.reduce_sum(ys * tf.log(prediction), reduction_indices=[1])) # loss
选择优化器(梯度下降)一次训练:
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)#一次正向传播+反向传播,得到模型
打开会话开始训练:
sess = tf.Session() # important step sess.run(tf.initialize_all_variables()) #plot_images_labels_prediction(mnist.train.images, # mnist.train.labels,prediction,0) for i in range(1000): #读取批次数据,为了更快的收敛 #每次读取1001项批次训练数据,读取的训练数据存放在 batch_xs, batch_ys ,准备训练使用 batch_xs, batch_ys = mnist.train.next_batch(100) sess.run(train_step, feed_dict={xs: batch_xs, ys: batch_ys})#训练模型 if i % 50 == 0: print(compute_accuracy( mnist.test.images, mnist.test.labels))
训练结果: