tensorflow入门项目(一):手写数字识别之DNN模型(超超超详解)

前言

手写数字识别,为了学习的需要,所以记录的超级详细。一看就会,一看就懂。
一开始下载数据可能会花费点时间。
直接复制,即可运行。

也可以跳过正文,直接复制代码,代码里包含了全部的讲解

正文

在 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()

最后

锤爆李庚希老婆的颜值,赏心悦目
tensorflow入门项目(一):手写数字识别之DNN模型(超超超详解)_第1张图片

你可能感兴趣的:(深度学习)