手写数字识别,为了学习的需要,所以记录的超级详细。一看就会,一看就懂。
一开始下载数据可能会花费点时间。
直接复制,即可运行。
也可以跳过正文,直接复制代码,代码里包含了全部的讲解。
在 MNIST 数据集中的每张图片由 28 x 28 个像素点构成, 每个像素点用一个灰度值表示.
在这里, 我们将 28 x 28 的像素展开为一个一维的行向量, 这些行向量就是图片数组里的行(每行 784 个值, 或者说每行就是代表了一张图片).
mnist 函数返回的第二个数组(labels) 包含了相应的目标变量, 也就是手写数字的类标签(整数 0-9).
tf.placeholder(dtype, shape=None, name=None)
TensorFlow中的占位符,用于feed_dict传入外部数据。
dtype:数据类型。
shape:数据的维度。默认为None,表示没有限制
name:名称
返回类型:Tensor
tf.Variable(initializer,name),
参数initializer是初始化参数,
name是可自定义的变量名称
tf.random_normal(形状,平均值= 0.0,stddev = 1.0,dtype = tf.float32,种子=无,名称=无)
shape:输出张量的形状,必选
平均:正态分布的均值,默认为0
stddev:正态分布的标准差,交替为1.0
dtype:输出的类型,默认为tf.float32
seed:随机数种子,是一个整数,当设置之后,每次生成的随机数都一样
名称:操作的名称
tf.matmul(a, b, transpose_a=False, transpose_b=False, adjoint_a=False, adjoint_b=False, a_is_sparse=False, b_is_sparse=False, name=None)
a: 一个类型为 float16, float32, float64, int32, complex64, complex128 且张量秩 > 1 的张量。
b: 一个类型跟张量a相同的张量。
其他的参数没用上就不一一介绍了
返回值: 一个跟张量a和张量b类型一样的张量且最内部矩阵是a和b中的相应矩阵的乘积。
tf.nn.softmax(logits,axis=None,name=None,dim=None)
logits:一个非空的Tensor。必须是下列类型之一:half, float32,float64
axis:将在其上执行维度softmax。默认值为-1,表示最后一个维度
name:操作的名称(可选)
dim:axis的已弃用的别名
返回:一个Tensor,与logits具有相同的类型和shape
通过Softmax回归,将logistic的预测二分类的概率的问题推广到了n分类的概率的问题
softmax的输出向量是概率,该样本属于各个类的概率,这里是十个类别0-9。输出的向量的每个值的大小范围为0到1。
当一个样本经过softmax层并输出一个向量,会取这个向量中值最大的那个数的index作为这个样本的预测标签,
下文中的tf.argmax(pred , 1)就是取最大值操作
tf.log函数,这个函数完成了对张量所有元素依次求对数的功能
tf.reduce_sum(input_tensor,axis=None,keepdims=None,name=None,reduction_indices=None,keep_dims=None)
input_tensor:待求和的tensor;
reduction_indices:在以前版本中用来指定轴,已弃用;
有两个取值分别为0和1,通常用reduction_indices=[0]或reduction_indices=[1]来传递参数。
从上图可以看出,当等于0时,是纵向对矩阵求和,原来矩阵有几列就得到几个值;
相似地,当等于1时,是横向对矩阵求和;当省略参数时,默认对矩阵所有元素进行求和。
reduce_sum应该理解为压缩求和,用于降维,不懂指路:https://blog.csdn.net/lxg0807/article/details/74625861
tf.reduce_mean(input_tensor, axis=None, keep_dims=False, name=None, reduction_indices=None)
input_tensor: 输入的待降维的tensor
axis: 指定的轴,如果不指定,则计算所有元素的均值
keep_dims:是否降维度,默认False。设置为True,输出的结果保持输入tensor的形状,设置为False,输出结果会降低维度
name: 操作的名称
reduction_indices:在以前版本中用来指定轴,已弃用
tf.reduce_mean()函数用于计算张量tensor沿着指定的数轴(tensor的某一维度)上的平均值,
主要用作降维或者计算tensor(图像)的平均值。
指路:https://blog.csdn.net/qq_42847843/article/details/103515505
tf.train.GradientDescentOptimizer(learning_rate, use_locking=False,name=’GradientDescent’)
name:优化器名字
learning_rate: 学习率,控制参数的更新速度。过大过小都会影响算法的运算时间和结果,过大容易发散,过小运算时间太长。
use_locking: 默认False。变量允许并发读写操作,若为true则防止对变量的并发更新。
优化器实现的是梯度下降算法
minimize(loss,global_step=None, var_list=None,gate_gradients=GATE_OP,
aggregation_method=None,colocate_gradients_with_ops=False,name=None,
grad_loss=None)
主要的两个参数:
loss:构造优化的损失函数,类型Tensor
global_step:通常于学习率变化一起使用,可选变量,在变量更新后增加1。
minimize() 函数处理了梯度计算和参数更新两个操作
tf.argmax(input, axis=None, name=None, dimension=None)
此函数是对矩阵按行或列计算最大值,输出最大值的下标
input:输入Tensor
axis:0表示按列,1表示按行
name:名称
dimension:和axis功能一样,默认axis取值优先。新加的字段
返回:Tensor 一般是行或列的最大值下标向量
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
作用:输出正确的预测结果.利用tf.argmax()按行求出真实值y_、预测值y最大值的下标,
用tf.equal()求出真实值和预测值相等的数量,也就是预测结果正确的数量,tf.argmax()和tf.equal()一般是结合着用
'''
在 MNIST 数据集中的每张图片由 28 x 28 个像素点构成, 每个像素点用一个灰度值表示.
在这里, 我们将 28 x 28 的像素展开为一个一维的行向量, 这些行向量就是图片数组里的行(每行 784 个值, 或者说每行就是代表了一张图片).
mnist 函数返回的第二个数组(labels) 包含了相应的目标变量, 也就是手写数字的类标签(整数 0-9).
'''
import tensorflow as tf
# 下载tensorflow数据
from tensorflow.examples.tutorials.mnist import input_data
#pylab 模块是一款由python提供的可以绘制二维,三维数据的工具模块,其中包括了绘图软件包 matplotlib,其可以生成matab绘图库的图像。
import pylab
# 下载数据到当前路径,改换自己的路径
# one_hot参数代表lable的表达形式是否是one_hot形式,这里使用one_hot对标签编码
mnist=input_data.read_data_sets("mnist/",one_hot=True)
print('train image shape输入数据:',mnist.train.images.shape,'trian label shape:', mnist.train.labels.shape)
print('val image shape:', mnist.validation.images.shape)
print('test image shape:', mnist.test.images.shape)
im = mnist.train.images[1]
im = im.reshape(-1,28)
pylab.imshow(im)
pylab.show()
# tf.reset_default_graph函数用于清除默认图形堆栈并重置全局默认图形。
tf.reset_default_graph()
x = tf.placeholder(tf.float32,[None,784])
'''
tf.placeholder(dtype, shape=None, name=None)
TensorFlow中的占位符,用于feed_dict传入外部数据。
这里None是随便传入几个样本,784是每一个样本有784列,这是确定的,每行代表一张图,用None代表你可以指定传入多少图。
下面的y也是这样,10代表10个类别(因为用来训练的数据集为[55000,784])
dtype:数据类型。
shape:数据的维度。默认为None,表示没有限制
name:名称
返回类型:Tensor
'''
y = tf.placeholder(tf.float32,[None,10])
w = tf.Variable(tf.random_normal([784,10]))
b = tf.Variable(tf.zeros([10]))
'''
tf.Variable(initializer,name),
参数initializer是初始化参数,
name是可自定义的变量名称
tf.random_normal(形状,平均值= 0.0,stddev = 1.0,dtype = tf.float32,种子=无,名称=无)
shape:输出张量的形状,必选
平均:正态分布的均值,默认为0
stddev:正态分布的标准差,交替为1.0
dtype:输出的类型,默认为tf.float32
seed:随机数种子,是一个整数,当设置之后,每次生成的随机数都一样
名称:操作的名称
'''
pred = tf.nn.softmax(tf.matmul(x,w)+b)
'''
tf.matmul(a, b, transpose_a=False, transpose_b=False, adjoint_a=False, adjoint_b=False, a_is_sparse=False, b_is_sparse=False, name=None)
a: 一个类型为 float16, float32, float64, int32, complex64, complex128 且张量秩 > 1 的张量。
b: 一个类型跟张量a相同的张量。
其他的参数没用上就不一一介绍了
返回值: 一个跟张量a和张量b类型一样的张量且最内部矩阵是a和b中的相应矩阵的乘积。
tf.nn.softmax(logits,axis=None,name=None,dim=None)
logits:一个非空的Tensor。必须是下列类型之一:half, float32,float64
axis:将在其上执行维度softmax。默认值为-1,表示最后一个维度
name:操作的名称(可选)
dim:axis的已弃用的别名
返回:一个Tensor,与logits具有相同的类型和shape
通过Softmax回归,将logistic的预测二分类的概率的问题推广到了n分类的概率的问题
softmax的输出向量是概率,该样本属于各个类的概率,这里是十个类别0-9。输出的向量的每个值的大小范围为0到1。
当一个样本经过softmax层并输出一个向量,会取这个向量中值最大的那个数的index作为这个样本的预测标签,
下文中的tf.argmax(pred , 1)就是取最大值操作
'''
# # 交叉熵评估代价
cost = tf.reduce_mean(-tf.reduce_sum(y*tf.log(pred),reduction_indices=1))
'''
tf.log函数,这个函数完成了对张量所有元素依次求对数的功能
乘以y后,得到了一个n×m的二维矩阵,其中n为一个batch中样例的数量,m为分类的类别数量根据交叉熵公式,
应该将每行中的m个结果相加得到的所有样例的交叉熵,然后在取平均值,得到一个batch的平均交叉熵。
tf.reduce_sum(input_tensor,axis=None,keepdims=None,name=None,reduction_indices=None,keep_dims=None)
input_tensor:待求和的tensor;
reduction_indices:在以前版本中用来指定轴,已弃用;
有两个取值分别为0和1,通常用reduction_indices=[0]或reduction_indices=[1]来传递参数。
从上图可以看出,当等于0时,是纵向对矩阵求和,原来矩阵有几列就得到几个值;
相似地,当等于1时,是横向对矩阵求和;当省略参数时,默认对矩阵所有元素进行求和。
reduce_sum应该理解为压缩求和,用于降维,不懂指路:https://blog.csdn.net/lxg0807/article/details/74625861
tf.reduce_mean(input_tensor, axis=None, keep_dims=False, name=None, reduction_indices=None)
input_tensor: 输入的待降维的tensor
axis: 指定的轴,如果不指定,则计算所有元素的均值
keep_dims:是否降维度,默认False。设置为True,输出的结果保持输入tensor的形状,设置为False,输出结果会降低维度
name: 操作的名称
reduction_indices:在以前版本中用来指定轴,已弃用
tf.reduce_mean()函数用于计算张量tensor沿着指定的数轴(tensor的某一维度)上的平均值,
主要用作降维或者计算tensor(图像)的平均值。
指路:https://blog.csdn.net/qq_42847843/article/details/103515505
'''
#定义学习率
learning_rate= 0.01
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)
'''
tf.train.GradientDescentOptimizer(learning_rate, use_locking=False,name=’GradientDescent’)
name:优化器名字
learning_rate: 学习率,控制参数的更新速度。过大过小都会影响算法的运算时间和结果,过大容易发散,过小运算时间太长。
use_locking: 默认False。变量允许并发读写操作,若为true则防止对变量的并发更新。
优化器实现的是梯度下降算法
minimize(loss,global_step=None, var_list=None,gate_gradients=GATE_OP,
aggregation_method=None,colocate_gradients_with_ops=False,name=None,
grad_loss=None)
主要的两个参数:
loss:构造优化的损失函数,类型Tensor
global_step:通常于学习率变化一起使用,可选变量,在变量更新后增加1。
minimize() 函数处理了梯度计算和参数更新两个操作
'''
training_epochs = 25
batch_size = 100
'''
batch,iterations,epochs概念理解:https://blog.csdn.net/qq_42847843/article/details/103516485
'''
# display_step是每多少次迭代显示当前的计算结果
display_step = 1
# 创建一个Saver对象
saver = tf.train.Saver()
# Session 是 Tensorflow 为了控制,和输出文件的执行的语句. 运行 session.run() 可以获得你要得知的运算结果, 或者是你所要运算的部分.
with tf.Session() as sess:
# 初始化变量
sess.run(tf.global_variables_initializer())
# # 启动循环开始训练
for epoch in range(training_epochs):
avg_cost = 0.
total_batch = int(mnist.train.num_examples/batch_size)
# 循环所有的数据集
for i in range(total_batch):
batch_xs,batch_ys = mnist.train.next_batch(batch_size)
'''
mnist.train.next_batch是专门用于由tensorflow提供的MNIST教程的函数。
它的工作原理是在开始时将训练图像和标签对随机化,并在每次调用该函数时选择每个随后的batch_size张图像。
一旦到达末尾,图像标签对将再次随机分配,并重复该过程。仅在使用所有可用对后,才重新组合和重复整个数据集。
'''
# 运行优化器
_,c = sess.run([optimizer,cost],feed_dict={x:batch_xs,y:batch_ys})
# 计算平均loss值
avg_cost+=c/total_batch
if (epoch + 1) % display_step == 0:
print("Epoch:", '%04d' % (epoch + 1), "cost:", "{:.9f}".format(avg_cost))
print(sess.run(w))
print("=====================")
print(sess.run(b))
print("学习结束!!!!")
# 保存模型
saver.save(sess,"E:/program/tensorflow_learning/example/mnist_program/model.cpkt")
correct_prediction = tf.equal(tf.argmax(pred,1),tf.argmax(y,1))
'''
tf.argmax(input, axis=None, name=None, dimension=None)
此函数是对矩阵按行或列计算最大值,输出最大值的下标
input:输入Tensor
axis:0表示按列,1表示按行
name:名称
dimension:和axis功能一样,默认axis取值优先。新加的字段
返回:Tensor 一般是行或列的最大值下标向量
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
作用:输出正确的预测结果.利用tf.argmax()按行求出真实值y_、预测值y最大值的下标,
用tf.equal()求出真实值和预测值相等的数量,也就是预测结果正确的数量,tf.argmax()和tf.equal()一般是结合着用
'''
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
'''
cast(x,dtype,name=None)将x的数据格式转化成dtype数据类型
'''
print("Accuracy: ",accuracy.eval({x:mnist.test.images,y:mnist.test.labels}))
print('/n/n/n===========================================================================/n')
print("用模型来预测!!!")
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
# Restore的用法是将训练好的参数提取出来。
saver.restore(sess, "E:/program/tensorflow_learning/example/mnist_program/model.cpkt")
correct_prediction = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
print("Accuracy:", accuracy.eval({x: mnist.test.images, y: mnist.test.labels}))
# 输出预测值最大值下标
output = tf.argmax(pred,1)
batch_xs,batch_ys = mnist.train.next_batch(2)
# 预测,只传入x值。计算输出和预测!
outputval, predv = sess.run([output, pred], feed_dict={x: batch_xs})
print(outputval, predv, batch_ys)
# 测试
im = batch_xs[0]
im = im.reshape(-1, 28)
pylab.imshow(im)
pylab.show()
im = batch_xs[1]
im = im.reshape(-1, 28)
pylab.imshow(im)
pylab.show()