您的位置:首页 > 其它

Tensorflow学习笔记(2):多层隐藏层实现Mnist手写数字识别

2020-06-08 05:09 78 查看

为了深入了解Tensorflow,学习了关于Mnist数据集以及相关操作,我在这里添加了三层隐藏层以及全连接层,应用该模型可以简单识别手写数字。(AI小白一枚,还希望各位能多多指教)
模型来自我一直学习的网课:https://www.icourse163.org/course/ZUCC-1206146808?tid=1450260446&trace_c_p_k2=3ea8b77d799f43a29dd20501a6fe4560

出现的问题
首先分析一个用了三天时间解决的问题:
加载Mnist数据集不成功

from tensorflow.examples.tutorials.mnist import input_data

此时报错:
ImportError: No module named mnist .tutorials.mnist

在stackoverflow上的解决方法是:
import tensorflow.examples.tutorials.mnist.input_data as input_data

如果你的问题没有解决,那么你可能和我掉进了同一个坑:Tensorflow版本过高带来的模块缺失问题,Tensorflow2.0.0版本中删去了tutorials包,你需要在GitHub上找到这个包,然后git clone到Anaconda\Lib\site-packages\tensorflow_core\examples这个路径里去,之后你就可以调用tutorials了,Mnist是一个tutorial哦。

模块加载

import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()
from tensorflow.examples.tutorials.mnist import input_data

之前提到过因为要调用placeholder函数,就要用以上代码代替import tensorflow as tf。

加载Mnist数据集

mnist=input_data.read_data_sets("e:Mnist",one_hot=True)

这是我预先下载好的,里面有四个文件(测试样本和标签,训练样本和标签)

定义全连接层
虽然我只用了三层隐藏层,但是为了活学活用,还是添加了全连接层。全连接层存在大量的神经元,简单来说就是为了增加模型的非线性表达能力,本质上就是很多的隐藏层连接而成。设置四个参数分别为输入数据,输入神经元个数,输出神经元个数以及激活函数,每次调用产生一个隐藏层。
tf.truncated_normal函数的作用是产生截断正态分布随机数,参数(shape,mean,stddev,dtype,seed,name)这里只调用了shape和stddev,shape为输入张量的维度,mean为均值,stddev为标准差,dtype为数据类型,seed为随机数。
tf.zeros函数作用是创建全是0的数组(o゜▽゜)o☆

def fcn_layer(inputs,            #输入数据
input_dim,         #输入神经元数量
output_dim,        #输出神经元数量
activation=None):  #激活函数,缺省时默认不调用激活函数
w=tf.Variable(tf.truncated_normal([input_dim,output_dim],stddev=0.1)) #权值设为正态分布且满足标准差为0.1的随机数
b=tf.Variable(tf.zeros([output_dim]))  #偏置项设置为0
xwb=tf.matmul(inputs,w)+b   #w*x+b
if activation is None:   #判断是否调用激活函数
outputs=xwb
else:
outputs=activation(xwb)

return outputs

创建模型
这里主要是在调用刚才定义的全连接层函数。
tf.nn.softmax函数:参数(logits,axis,name,dim)其中axis默认是-1意味着寻找最后一维空间向量的最大值对用的下标。该函数用于分类问题,所有分类的概率和为1,对于数字识别,就有10个分类,数之最大的值的概率也是最大(权重最大)
pred为前向计算节点,计算分类输出结果。

H1_NN=256   #第一隐藏层神经元的个数
H2_NN=64    #第二隐藏层神经元的个数
H3_NN=32    #第三隐藏层神经元的个数

#输入层输出层占位
x=tf.placeholder(tf.float32,[None,784],name="X")
y=tf.placeholder(tf.float32,[None,10],name="Y")

#构建隐藏层
h1=fcn_layer(inputs=x,
input_dim=784,
output_dim=H1_NN,
activation = tf.nn.relu)
h2=fcn_layer(inputs=h1,
input_dim=H1_NN,
output_dim=H2_NN,
activation=tf.nn.relu)
h3=fcn_layer(inputs=h2,
input_dim=H2_NN,
output_dim=H3_NN,
activation=tf.nn.relu)
forward=fcn_layer(inputs=h3,
input_dim=H3_NN,
output_dim=10,
activation=None)
pred=tf.nn.softmax(forward)

训练模型
训练模型的第一步是定义模型的参数,其次就是选择优化器和损失函数
*tf.nn.softmax_cross_entropy_with_logits(-sentinel,labels,logits,dim,name)*是求交叉熵函数,logits是指发生概率,其作用是计算十个分类的概率并且对标签做交叉熵运算。
tf.reduce_mean函数在计算损失率时将向量降为或者求平均值。

#定义损失函数
loss_function=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=forward, labels=y))
#定义训练参数
train_epochs=100    #训练轮数
batch_size=50      #训练一批的样本数量
total_batch=int(mnist.train.num_examples/batch_size)   #训练总轮数
display_step=1
learning_rate=0.01

#定义优化器
optimizer=tf.train.AdamOptimizer(learning_rate).minimize(loss_function)

#定义准确率
correct_prediction=tf.equal(tf.argmax(y,1),tf.argmax(pred,1))  #argmax参数选择1,找出一维向量的最大值下标
accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))

#记录训练开始时间
from time import time
startTime=time()

sess=tf.Session()
sess.run(tf.global_variables_initializer())

for epoch in range(train_epochs):
for batch in range(total_batch):
xs,ys=mnist.train.next_batch(batch_size)  #读取批次数据
sess.run(optimizer,feed_dict={x:xs,y:ys}) #执行批次数据

#total_batch执行完后,使用验证数据计算误差与准确率
loss,acc=sess.run([loss_function,accuracy],
feed_dict={x:mnist.validation.images,
y:mnist.validation.labels})
if(1+epoch) %display_step ==0:
print("Train_epoch=",'%02d'%(1+epoch),
"Loss=","{:.9f}".format(loss),"Accuracy=","{:.9f}".format(acc))

#显示运行时间
duration=time()-startTime
print("Train finished takes:","{:.2f}".format(duration))

100次迭代之后的结果如下:


写完了o( ̄▽ ̄)o

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: