MNIST手写数字分类识别二——多层神经网络

手写分类识别二:多层神经网络

一、 全连接但隐藏层全连接神经网络

  1. 载入数据

    import tensorflow as tf
    #导入Tensorfloe提供的读取MNIST的模块
    import tensorflow.examples.tutorials.mnist.input_data as input_data
    
    #读取MNIST数据
    mnist = input_data.read_data_sets("C:/Users/grid/Desktop/MNIST_data/",one_hot=True)#读取数据(数据集缩放的文件目录,标签的数据格式)
    
  2. 构建输入层

    #定义标签数据占位符
    x= tf.placeholder(tf.float32,[None,784],name="X")
    y= tf.placeholder(tf.float32,[None,10],name="Y")
    
  3. 构建隐藏层

    #隐藏层神经元数量
    H1_NN =256
    W1= tf.Variable(tf.random_normal([784,H1_NN]))  #784行 ,H1_NN列
    b1= tf.Variable(tf.zeros([H1_NN])) #赋初值为0
    
    Y1= tf.nn.relu(tf.matmul(x,W1)+b1) #叉乘.  
    
  4. 构建输出层

    W2 = tf.Variable(tf.random_normal([H1_NN,10]))
    b2 = tf.Variable(tf.zeros([10]))
    
    forward = tf.matmul(Y1,W2)+b2
    pred = tf.nn.softmax(forward)  
    
  5. 训练模型

    #* 定义损失函数
    #交叉熵
    loss_function = tf.reduce_mean(-tf.reduce_sum(y*tf.log(pred),reduction_indices=1))
    
    #设置训练参数
    train_epochs=40   #训练轮次
    batch_size=50   #一次要训练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))
    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(epoch+1)%display_step ==0:
    		print("Train Epoch:","%02d" %(epoch+1),
    			"loss=","{:.9f}".format(loss),"Accuracy=","{:.4f}".format(acc))
    #显示运行总时间
    duration = time()-startTime
    print("Train Finished takes:","{:.2f}".format(duration))
    

整个项目代码:

##载入数据
import tensorflow as tf
#导入Tensorfloe提供的读取MNIST的模块
import tensorflow.examples.tutorials.mnist.input_data as input_data

#读取MNIST数据
mnist = input_data.read_data_sets("C:/Users/grid/Desktop/MNIST_data/",one_hot=True)#读取数据(数据集缩放的文件目录,标签的数据格式)

##构建输入层
#定义标签数据占位符
x= tf.placeholder(tf.float32,[None,784],name="X")
y= tf.placeholder(tf.float32,[None,10],name="Y")

##构建隐藏层
#隐藏层神经元数量
H1_NN =256
W1= tf.Variable(tf.random_normal([784,H1_NN]))  #784行 ,H1_NN列
b1= tf.Variable(tf.zeros([H1_NN])) #赋初值为0

Y1= tf.nn.relu(tf.matmul(x,W1)+b1) #叉乘.  

##构建输出层
W2 = tf.Variable(tf.random_normal([H1_NN,10]))
b2 = tf.Variable(tf.zeros([10]))

forward = tf.matmul(Y1,W2)+b2
pred = tf.nn.softmax(forward)  

##训练模型
#* 定义损失函数
#交叉熵
loss_function = tf.reduce_mean(-tf.reduce_sum(y*tf.log(pred),reduction_indices=1))

#设置训练参数
train_epochs=40   #训练轮次
batch_size=50   #一次要训练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))
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(epoch+1)%display_step ==0:
		print("Train Epoch:","%02d" %(epoch+1),
			"loss=","{:.9f}".format(loss),"Accuracy=","{:.4f}".format(acc))
#显示运行总时间
duration = time()-startTime
print("Train Finished takes:","{:.2f}".format(duration))

结果:

Train Epoch :01 Loss=nan Accuracy= 0.0958

Loss的值不对。

原因分析:

#* 定义损失函数
#交叉熵
loss_function = tf.reduce_mean(-tf.reduce_sum(y*tf.log(pred),reduction_indices=1))

中 log(0)引起的数据不稳定

解决:

Tensorflow提供了结合Softmax的交叉熵损失函数定义方法:

#Tensorflow 提供了  softmax_cross_entropy_with_logits 函数
#用于避免因为log(0)值为NaN造成的数据不稳定
loss_function = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=forward,labels=y))

这个项目改善后的代码:

##载入数据
import tensorflow as tf
#导入Tensorfloe提供的读取MNIST的模块
import tensorflow.examples.tutorials.mnist.input_data as input_data

#读取MNIST数据
mnist = input_data.read_data_sets("C:/Users/grid/Desktop/MNIST_data/",one_hot=True)#读取数据(数据集缩放的文件目录,标签的数据格式)

##构建输入层
#定义标签数据占位符
x= tf.placeholder(tf.float32,[None,784],name="X")
y= tf.placeholder(tf.float32,[None,10],name="Y")

##构建隐藏层
#隐藏层神经元数量
H1_NN =256
W1= tf.Variable(tf.random_normal([784,H1_NN]))  #784行 ,H1_NN列
b1= tf.Variable(tf.zeros([H1_NN])) #赋初值为0

Y1= tf.nn.relu(tf.matmul(x,W1)+b1) #叉乘.  

##构建输出层
W2 = tf.Variable(tf.random_normal([H1_NN,10]))
b2 = tf.Variable(tf.zeros([10]))

forward = tf.matmul(Y1,W2)+b2
pred = tf.nn.softmax(forward)  

##训练模型
#* 定义损失函数
#交叉熵
#Tensorflow 提供了  softmax_cross_entropy_with_logits 函数
#用于避免因为log(0)值为NaN造成的数据不稳定
loss_function = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=forward,labels=y))

#设置训练参数
train_epochs=40   #训练轮次
batch_size=50   #一次要训练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))
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(epoch+1)%display_step ==0:
		print("Train Epoch:","%02d" %(epoch+1),
			"loss=","{:.9f}".format(loss),"Accuracy=","{:.4f}".format(acc))
#显示运行总时间
duration = time()-startTime
print("Train Finished takes:","{:.2f}".format(duration))

进行预测

#由于pred预测结果是one-hot编码格式,所以需要转换为0~9数字
prediction_result=sess.run(tf.argmax(pred,1),feed_dict={x:mnist.test.images})
#查看预测结果中的前十项
prediction_result[0:10]

找出预测错误的样本

import numpy as np
compare_lists =prediction_result==np.argmax(mnist.test.labels,1)
print(compare_lists)

err_list = [i for i in range (len(compare_lists)) if compare_lists[i]==False]
print(err_lists,len(err_lists))

定义一个输出错误分类函数

import numpy as np
def print_predict_errd(labels,    #标签值
						prediction):   #预测值列表
	count = 0
	compare_lists = (prediction==np.argmax(labels,1))
	err_lists=[i for i in range(len(compare_lists)) if compare_lists[i]==False]
	for x in err_lists:
		print("index="+str(x)+"标签值=",np.argmax(labels[x]),"预测值=",prediction[x])
		count= count+1
	print("总计:"+str(count))
	
print_predict_errs(labels=mnist.test.labels,prediction=prediction_result)

定义可视化函数

import matplotlib.pyplot as plt
import numpy as np
def plot_images_labels_prediction(images,  #图像列表
								  labels,   #标签列表
								  prediction, #预测值列表
								  index,  #从第index个开始显示
								  num=10):  #缺省一次显示10幅图
	fig = plt.gcf()  #获取当前图表,Get Current Figure
	fig.set_size_inches(10,12)     #1英寸等于2.54cm
	if num >25:
		num=25  #最多显示25个子图
	for i in range(0,num):
		ax = plt.subplot(5,5,i+1)   #获取当前要处理的子图
		ax.imshow(np.reshape(images[index],(28,28)),  #显示第index个图像
							cmap="binary")
		
		title = "label="+str(np.argmax(labels[index]))  #构建该图上要显示的title信息
		if  len(prediction)>0:
			title+=",prefiction="+str(prediction[index])
			
		ax.set_title(title,fontsize=10) #显示图上的title信息
		ax.set_xticks([]);#不显示坐标轴
		ax.set_yticks([])
		index +=1
	plt.show()

可视化查看预测错误的样本

plot_images_labels_prediction(mnist.test.images,mnist.test.labels,prediction_result,610,20)

二、多层神经网络建模

2层神经网络

  1. 构建模型

    H1_NN = 256 #第一隐藏层神经元为256个
    H2_NN = 64  #第2影藏层神经元为64个
    #输入层-第一隐藏层参数和偏置项
    W1 = tf.Variable(tf.truncated_normal([784,H1_NN],stddev=0.1))
    b1 = tf.Variable(tf.zeros([H1_NN]))
    
    #第1隐藏层-第2隐藏层参数和偏置项
    W2 = tf.Variable(tf.truncated_normal([H1_NN,H2_NN],stddev=0.1))
    b2 = tf.Variable(tf.zeros([H2_NN]))
    
    #第2隐藏层-输出层参数和偏置项
    W3=tf.Variable(tf.truncated_normal([H2_NN,10],stddev=0.1))
    b3 = tf.Variable(tf.zeros([10]))
    
    #计算第1隐藏层结果
    Y1 = tf.nn.relu(tf.matmul(x,W1)+b1)
    #计算第2隐藏层结果
    Y2 = tf.nn.relu(tf.matmul(Y1,W2)+b2)
    
    #计算输出结果
    forward = tf.matmul(Y2,W3)+b3
    pred = tf.nn.softmax(forward)
    

整个项目代码

##载入数据
import tensorflow as tf
#导入Tensorfloe提供的读取MNIST的模块
import tensorflow.examples.tutorials.mnist.input_data as input_data

#读取MNIST数据
mnist = input_data.read_data_sets("C:/Users/grid/Desktop/MNIST_data/",one_hot=True)#读取数据(数据集缩放的文件目录,标签的数据格式)

##构建输入层
#定义标签数据占位符
x= tf.placeholder(tf.float32,[None,784],name="X")
y= tf.placeholder(tf.float32,[None,10],name="Y")

##构建隐藏层
#隐藏层神经元数量
H1_NN = 256 #第一隐藏层神经元为256个
H2_NN = 64  #第2影藏层神经元为64个
#输入层-第一隐藏层参数和偏置项
W1 = tf.Variable(tf.truncated_normal([784,H1_NN],stddev=0.1))
b1 = tf.Variable(tf.zeros([H1_NN]))

#第1隐藏层-第2隐藏层参数和偏置项
W2 = tf.Variable(tf.truncated_normal([H1_NN,H2_NN],stddev=0.1))
b2 = tf.Variable(tf.zeros([H2_NN]))

#第2隐藏层-输出层参数和偏置项
W3=tf.Variable(tf.truncated_normal([H2_NN,10],stddev=0.1))
b3 = tf.Variable(tf.zeros([10]))

#计算第1隐藏层结果
Y1 = tf.nn.relu(tf.matmul(x,W1)+b1)
#计算第2隐藏层结果
Y2 = tf.nn.relu(tf.matmul(Y1,W2)+b2)

#计算输出结果
forward = tf.matmul(Y2,W3)+b3
pred = tf.nn.softmax(forward)

##训练模型
#* 定义损失函数
#交叉熵
#Tensorflow 提供了  softmax_cross_entropy_with_logits 函数
#用于避免因为log(0)值为NaN造成的数据不稳定
loss_function = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=forward,labels=y))

#设置训练参数
train_epochs=40   #训练轮次
batch_size=50   #一次要训练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))
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(epoch+1)%display_step ==0:
		print("Train Epoch:","%02d" %(epoch+1),
			"loss=","{:.9f}".format(loss),"Accuracy=","{:.4f}".format(acc))
#显示运行总时间
duration = time()-startTime
print("Train Finished takes:","{:.2f}".format(duration))


###进行预测
#由于pred预测结果是one-hot编码格式,所以需要转换为0~9数字
prediction_result=sess.run(tf.argmax(pred,1),feed_dict={x:mnist.test.images})
#查看预测结果中的前十项
prediction_result[0:10]

###定义可视化函数预测
import matplotlib.pyplot as plt
import numpy as np
def plot_images_labels_prediction(images,  #图像列表
								  labels,   #标签列表
								  prediction, #预测值列表
								  index,  #从第index个开始显示
								  num=10):  #缺省一次显示10幅图
	fig = plt.gcf()  #获取当前图表,Get Current Figure
	fig.set_size_inches(10,12)     #1英寸等于2.54cm
	if num >25:
		num=25  #最多显示25个子图
	for i in range(0,num):
		ax = plt.subplot(5,5,i+1)   #获取当前要处理的子图
		ax.imshow(np.reshape(images[index],(28,28)),  #显示第index个图像
							cmap="binary")
		
		title = "label="+str(np.argmax(labels[index]))  #构建该图上要显示的title信息
		if  len(prediction)>0:
			title+=",prefiction="+str(prediction[index])
			
		ax.set_title(title,fontsize=10) #显示图上的title信息
		ax.set_xticks([]);#不显示坐标轴
		ax.set_yticks([])
		index +=1
	plt.show()

##可视化查看错群的版本
plot_images_labels_prediction(mnist.test.images,mnist.test.labels,prediction_result,610,20)

评估 Test Accuracy: 0.969

多层效果不一定就比单层网络好

三层神经网络的构建

构建模型

H1_NN = 256 # 第一隐藏层神经元为256个
H2_NN = 64 # 第2隐藏层神经元为64个
H3_NN = 32 #第3隐藏层神经元为32个

#输入层 -第1隐藏层参数和偏置项
W1= tf.Variable(tf.truncated_normal([784,H1_NN],stddev=0.1))
b1 = tf.variable(tf.zeros([H1_NN]))

#第1隐藏层-第2隐藏层参数和偏置项
W2= tf.Variable(tf.truncated_normal([H1_NN,H2_NN],stddev=0.1))
b2 = tf.variable(tf.zeros([H2_NN]))
#第2隐藏层-第3隐藏层参数和偏置项
W3= tf.Variable(tf.truncated_normal([H2_NN,H3_NN],stddev=0.1))
b3 = tf.variable(tf.zeros([H3_NN]))
#第3隐藏层-输出层参数和偏置项
W4= tf.Variable(tf.truncated_normal([H3_NN,10],stddev=0.1))
b4 = tf.variable(tf.zeros([10]))

三、定义全连接层函数

#定义全连接层函数
def fcn_layer(inputs,  #输入数据
			  input_dim,  #输入神经元数量
			  output_dim,  #输出神经元数量
			  activation = None):   #激活函数
	W = tf.Variable(tf.truncated_normal([input_dim,output_dim],stddev=0.1))
				#以截断正态分布的随机数初始化W
	b= tf.Variable(tf.zeros([output_dim]))  #以0初始化b
	
	XWb = tf.matmul(inputs,W)+b  #建立表达式:inputs*W +b
	if activation is None:   #默认不使用激活函数
		outputs=XWb
	else:  #若传入激活函数,则用其对输出结果进行变换
		outputs= activation(XWb)
	return outputs

构建模型的改变

  • 单隐层模型
#单隐层模型
#构建输入层
x= tf.placeholder(tf.float32,[None,784],name="X")
#构建隐藏层
#隐藏层包含256个神经元
h1=fnc_layer(inputs=x,input_dim=784,output_dim=256,activation=tf.nn.relu)
#构建输出层
forward = fcn_layer(inputs=h1,input_dim=256,output_dim=10,activation=None)
pred = tf.nn.softmax(forward)
  • 双隐层模型
#构建输入层
x= tf.placeholder(tf.float32,[None,784],name="X")
#构建隐藏层
H1_NN =256  #第1隐藏层神经元为256
H2_NN=64    #第2隐藏层神经元为64

#构建隐藏层1
h1=fnc_layer(inputs=x,input_dim=784,output_dim=H1_NN,activation=tf.nn.relu)
#构建隐藏层2
h2=fnc_layer(inputs=x,input_dim=H1_NN,output_dim=H2_NN,activation=tf.nn.relu)
#构建输出层
forward = fcn_layer(inputs=h2,input_dim=H2_NN,output_dim=10,activation=None)
pred = tf.nn.softmax(forward)
  • 三隐藏层模型
#构建输入层
x= tf.placeholder(tf.float32,[None,784],name="X")
#构建隐藏层
H1_NN =256  #第1隐藏层神经元为256
H2_NN=64    #第2隐藏层神经元为64
H3_NN = 32 #第2隐藏层神经元为32个

#构建隐藏层1
h1=fnc_layer(inputs=x,input_dim=784,output_dim=H1_NN,activation=tf.nn.relu)
#构建隐藏层2
h2=fnc_layer(inputs=x,input_dim=H1_NN,output_dim=H2_NN,activation=tf.nn.relu)
#构建隐藏层2
h3=fnc_layer(inputs=x,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)

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