还是使用MNIST手写数字识别的案例。
1、训练模型的保存:
# -*- coding: utf-8 -*-
"""
Created on Tue May 12 19:23:06 2020
@author: DELL
mnist数字识别,多隐层神经网络。
"""
# 1、载入数据
# MNIST 数据集可在 http://yann.lecun.com/exdb/mnist/ 获取
import tensorflow as tf
import tensorflow.examples.tutorials.mnist.input_data as input_data
mnist = input_data.read_data_sets("MNST_data/",one_hot=True)
# 该站点上有四个文件:
# train-images-idx3-ubyte.gz:训练集图像(9912422字节)
# train-labels-idx1-ubyte.gz:训练集标签(28881 字节)
# t10k-images-idx3-ubyte.gz:测试集图像(1648877字节)
# t10k-labels-idx1-ubyte.gz:测试集标签(4542字节)
# 2、构建模型
# 定义全连接层函数
def fcn_layer(inputs, # 输入数据
input_dim, # 输入神经元数量
output_dim, # 输出神经元数量
activation=None): # 激活函数
W = tf.Variable(tf.random.truncated_normal([input_dim,output_dim], stddev=-.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") # mnist中每张图片共有28*28=784个像素点
y = tf.placeholder(tf.float32,[None, 10], name="Y") # 0-9一共10个数字->10个类别
# 1) 单隐层
# 构建隐藏层
h1=fcn_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) # 结果分类
# # 2) 双隐层
# # 构建隐藏层
# H1_NN=256 # 第1隐藏层神经元256个
# H2_NN=64 # 第2隐藏层神经元64个
# 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)
# # 构建输出层
# forward = fcn_layer(inputs=h2, input_dim=H2_NN, output_dim=10,activation=None)
# pred = tf.nn.softmax(forward) # 结果分类
# # 3) 三隐层
# # 构建隐藏层
# H1_NN=256 # 第1隐藏层神经元256个
# H2_NN=64 # 第2隐藏层神经元64个
# H3_NN=32 # 第3隐藏层神经元32个
# 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) # 结果分类
# 3、训练模型
# 设置训练参数
train_epochs = 40 # 训练轮数
batch_size = 50 # 单次训练样本数(批次大小)
total_batch = int(mnist.train.num_examples/batch_size) # 一轮训练有多少批次
display_step = 2 # 显示粒度
learning_rate = 0.01 # 学习率
# 定义损失函数
# loss_function = tf.reduce_mean(-tf.reduce_sum(y*tf.log(pred),reduction_indices=1)) # 交叉熵
loss_function = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels=y,logits=forward)) # tensorflow提供带softmax的交叉熵函数
# 用于避免因为log(0)值为NaN造成的数据不稳定
# 选择优化器
# optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss_function) # 梯度下降优化器
optimizer = tf.compat.v1.train.AdamOptimizer(learning_rate).minimize(loss_function)
# 定义准确率
correct_prediction = tf.equal(tf.argmax(pred,1),tf.argmax(y,1)) # 检查预测类别与实际类别的匹配情况
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) # 将布尔值转化为浮点数,并计算平均值
# 存储模型的粒度
save_step = 5
# 创建保存模型文件的目录
import os
ckpt_dir="./ckpt_dir"
if not os.path.exists(ckpt_dir):
os.makedirs(ckpt_dir)
# 声明完所有变量后,调用tf.train.Saver
saver = tf.compat.v1.train.Saver()
# 记录训练开始时间
from time import time
startTime=time()
sess = tf.compat.v1.Session() # 声明会话
init = tf.compat.v1.global_variables_initializer() # 变量初始化
sess.run(init)
# 开始训练
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))
if (epoch+1) % save_step ==0:
saver.save(sess,os.path.join(ckpt_dir,'mnist_h256_model_{:06d}.ckpt'.format(epoch+1))) # 存储模型
print('mnist_h256_model_{:06d}.ckpt saved'.format(epoch+1))
saver.save(sess,os.path.join(ckpt_dir,'mnist_h256_model.ckpt'))
print("Model Saved!")
print("Train Finished!")
# 显示运行总时间
duration = time()-startTime
print("Train Finished takes:","{:.2f}".format(duration))
# 4、评估模型
# 完成训练后,在验证集上评估模型的准确率
accu_validation = sess.run(accuracy,feed_dict={x:mnist.validation.images,y:mnist.validation.labels})
print("Test Accuracy:",accu_validation)
# Test Accuracy: 0.9058
# 完成训练后,在测试集上评估模型的准确率
accu_test = sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels})
print("Test Accuracy:",accu_test)
# Test Accuracy: 0.9056
# 5、可视化
# 在建立模型并进行训练后,若认为准确率可以接受,则可以使用此模型进行预测
# 由于pred预测结果是One-hot编码格式,所以需要转换为0-9数字
prediction_result = sess.run(tf.argmax(pred,1),
feed_dict={x:mnist.test.images})
# 定义可视化函数
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)),cmap='binary') # 显示第index个图像
title = "label=" + str(np.argmax(labels[index])) # 构建该图上要显示的title信息
if len(prediction)>0:
title += ", predict=" + str(prediction[index])
ax.set_title(title,fontsize=10)
ax.set_xticks([]) # 不显示坐标轴
ax.set_yticks([])
index+=1
plt.show()
# 6、找出预测错误
compare_lists = prediction_result==np.argmax(mnist.test.labels,1)
print(compare_lists)
err_lists =[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_errs(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+=1
print("总计:"+str(count))
print_predict_errs(labels=mnist.test.labels,
prediction=prediction_result)
plot_images_labels_prediction(mnist.test.images,mnist.test.labels,prediction_result,9745,20)
默认只保留5份文件。
2、模型的读取:
# -*- coding: utf-8 -*-
"""
Created on Tue May 12 20:20:36 2020
@author: DELL
读取模型
"""
# 1、载入数据
# MNIST 数据集可在 http://yann.lecun.com/exdb/mnist/ 获取
import tensorflow as tf
import tensorflow.examples.tutorials.mnist.input_data as input_data
mnist = input_data.read_data_sets("MNST_data/",one_hot=True)
# 该站点上有四个文件:
# train-images-idx3-ubyte.gz:训练集图像(9912422字节)
# train-labels-idx1-ubyte.gz:训练集标签(28881 字节)
# t10k-images-idx3-ubyte.gz:测试集图像(1648877字节)
# t10k-labels-idx1-ubyte.gz:测试集标签(4542字节)
# 2、构建模型
# 定义全连接层函数
def fcn_layer(inputs, # 输入数据
input_dim, # 输入神经元数量
output_dim, # 输出神经元数量
activation=None): # 激活函数
W = tf.Variable(tf.random.truncated_normal([input_dim,output_dim], stddev=-.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") # mnist中每张图片共有28*28=784个像素点
y = tf.placeholder(tf.float32,[None, 10], name="Y") # 0-9一共10个数字->10个类别
# 1) 单隐层
# 构建隐藏层
h1=fcn_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) # 结果分类
# # 2) 双隐层
# # 构建隐藏层
# H1_NN=256 # 第1隐藏层神经元256个
# H2_NN=64 # 第2隐藏层神经元64个
# 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)
# # 构建输出层
# forward = fcn_layer(inputs=h2, input_dim=H2_NN, output_dim=10,activation=None)
# pred = tf.nn.softmax(forward) # 结果分类
# # 3) 三隐层
# # 构建隐藏层
# H1_NN=256 # 第1隐藏层神经元256个
# H2_NN=64 # 第2隐藏层神经元64个
# H3_NN=32 # 第3隐藏层神经元32个
# 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) # 结果分类
# 3、训练模型
# 设置训练参数
train_epochs = 40 # 训练轮数
batch_size = 50 # 单次训练样本数(批次大小)
total_batch = int(mnist.train.num_examples/batch_size) # 一轮训练有多少批次
display_step = 2 # 显示粒度
learning_rate = 0.01 # 学习率
# 定义损失函数
# loss_function = tf.reduce_mean(-tf.reduce_sum(y*tf.log(pred),reduction_indices=1)) # 交叉熵
loss_function = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels=y,logits=forward)) # tensorflow提供带softmax的交叉熵函数
# 用于避免因为log(0)值为NaN造成的数据不稳定
# 选择优化器
# optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss_function) # 梯度下降优化器
optimizer = tf.compat.v1.train.AdamOptimizer(learning_rate).minimize(loss_function)
# 定义准确率
correct_prediction = tf.equal(tf.argmax(pred,1),tf.argmax(y,1)) # 检查预测类别与实际类别的匹配情况
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) # 将布尔值转化为浮点数,并计算平均值
# 存储模型的粒度
save_step = 5
# 创建保存模型文件的目录
import os
ckpt_dir="./ckpt_dir"
if not os.path.exists(ckpt_dir):
os.makedirs(ckpt_dir)
# 声明完所有变量后,调用tf.train.Saver
saver = tf.compat.v1.train.Saver()
sess = tf.compat.v1.Session() # 声明会话
init = tf.compat.v1.global_variables_initializer() # 变量初始化
sess.run(init)
ckpt = tf.train.get_checkpoint_state(ckpt_dir)
if ckpt and ckpt.model_checkpoint_path:
saver.restore(sess,ckpt.model_checkpoint_path) # 从已保存的模型中读取参数
print("Restore model from"+ckpt.model_checkpoint_path)
# 输出模型准确率
print("Accuracy:",accuracy.eval(session=sess,
feed_dict={x:mnist.test.images,
y:mnist.test.labels}))
accu_test = sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels})
print("Accuracy:",accu_test)
p.s. 如果读取模型报错,Restart Kernel一下,再读取,就可以了。
3、加入TensorBoard
修改代码:
# -*- coding: utf-8 -*-
"""
Created on Tue May 12 21:59:58 2020
@author: DELL
mnist数字识别,加入TensorBoard
"""
# 1、载入数据
# MNIST 数据集可在 http://yann.lecun.com/exdb/mnist/ 获取
import tensorflow as tf
import tensorflow.examples.tutorials.mnist.input_data as input_data
mnist = input_data.read_data_sets("MNST_data/",one_hot=True)
# 该站点上有四个文件:
# train-images-idx3-ubyte.gz:训练集图像(9912422字节)
# train-labels-idx1-ubyte.gz:训练集标签(28881 字节)
# t10k-images-idx3-ubyte.gz:测试集图像(1648877字节)
# t10k-labels-idx1-ubyte.gz:测试集标签(4542字节)
# 2、构建模型
# 定义全连接层函数
def fcn_layer(inputs, # 输入数据
input_dim, # 输入神经元数量
output_dim, # 输出神经元数量
activation=None): # 激活函数
W = tf.Variable(tf.random.truncated_normal([input_dim,output_dim], stddev=-.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.compat.v1.placeholder(tf.float32, [None, 784], name ="X") # mnist中每张图片共有28*28=784个像素点
image_shaped_input = tf.reshape(x,[-1,28,28,1])
tf.compat.v1.summary.image('input',image_shaped_input,10)
# <tf.Tensor 'input:0' shape=() dtype=string>
y = tf.compat.v1.placeholder(tf.float32,[None, 10], name="Y") # 0-9一共10个数字->10个类别
# # 1) 单隐层
# # 构建隐藏层
# h1=fcn_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) # 结果分类
# # 2) 双隐层
# # 构建隐藏层
# H1_NN=256 # 第1隐藏层神经元256个
# H2_NN=64 # 第2隐藏层神经元64个
# 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)
# # 构建输出层
# forward = fcn_layer(inputs=h2, input_dim=H2_NN, output_dim=10,activation=None)
# pred = tf.nn.softmax(forward) # 结果分类
# 3) 三隐层
# 构建隐藏层
H1_NN=256 # 第1隐藏层神经元256个
H2_NN=64 # 第2隐藏层神经元64个
H3_NN=32 # 第3隐藏层神经元32个
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.compat.v1.summary.histogram('forward', forward)
# <tf.Tensor 'forward:0' shape=() dtype=string>
# 3、训练模型
# 设置训练参数
train_epochs = 10 # 训练轮数
batch_size = 50 # 单次训练样本数(批次大小)
total_batch = int(mnist.train.num_examples/batch_size) # 一轮训练有多少批次
display_step = 2 # 显示粒度
learning_rate = 0.01 # 学习率
# 定义损失函数
# loss_function = tf.reduce_mean(-tf.reduce_sum(y*tf.log(pred),reduction_indices=1)) # 交叉熵
loss_function = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels=y,logits=forward)) # tensorflow提供带softmax的交叉熵函数
# 用于避免因为log(0)值为NaN造成的数据不稳定
tf.compat.v1.summary.scalar('loss', loss_function)
# <tf.Tensor 'loss:0' shape=() dtype=string>
# 选择优化器
# optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss_function) # 梯度下降优化器
optimizer = tf.compat.v1.train.AdamOptimizer(learning_rate).minimize(loss_function)
# 定义准确率
correct_prediction = tf.equal(tf.argmax(pred,1),tf.argmax(y,1)) # 检查预测类别与实际类别的匹配情况
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) # 将布尔值转化为浮点数,并计算平均值
tf.compat.v1.summary.scalar('accuracy', accuracy)
# <tf.Tensor 'accuracy:0' shape=() dtype=string>
# 记录训练开始时间
from time import time
startTime=time()
sess = tf.compat.v1.Session() # 声明会话
init = tf.compat.v1.global_variables_initializer() # 变量初始化
sess.run(init)
# TensorBoard: 合并所有summary
merged_summary_op = tf.compat.v1.summary.merge_all()
writer = tf.compat.v1.summary.FileWriter('E:/python_learning',sess.graph) # 创建写入符
# 开始训练
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}) # 执行批次训练
# 生成summary
summary_str = sess.run(merged_summary_op,feed_dict={x:xs,y:ys})
writer.add_summary(summary_str,epoch) # 将summary写入文件
# 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))
print("Train Finished!")
# 显示运行总时间
duration = time()-startTime
print("Train Finished takes:","{:.2f}".format(duration))
# 4、评估模型
# 完成训练后,在验证集上评估模型的准确率
accu_validation = sess.run(accuracy,feed_dict={x:mnist.validation.images,y:mnist.validation.labels})
print("Test Accuracy:",accu_validation)
# Test Accuracy: 0.9058
# 完成训练后,在测试集上评估模型的准确率
accu_test = sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels})
print("Test Accuracy:",accu_test)
# Test Accuracy: 0.9056
# 5、可视化
# 在建立模型并进行训练后,若认为准确率可以接受,则可以使用此模型进行预测
# 由于pred预测结果是One-hot编码格式,所以需要转换为0-9数字
prediction_result = sess.run(tf.argmax(pred,1),
feed_dict={x:mnist.test.images})
# 定义可视化函数
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)),cmap='binary') # 显示第index个图像
title = "label=" + str(np.argmax(labels[index])) # 构建该图上要显示的title信息
if len(prediction)>0:
title += ", predict=" + str(prediction[index])
ax.set_title(title,fontsize=10)
ax.set_xticks([]) # 不显示坐标轴
ax.set_yticks([])
index+=1
plt.show()
# 6、找出预测错误
compare_lists = prediction_result==np.argmax(mnist.test.labels,1)
print(compare_lists)
err_lists =[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_errs(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+=1
print("总计:"+str(count))
print_predict_errs(labels=mnist.test.labels,
prediction=prediction_result)
plot_images_labels_prediction(mnist.test.images,mnist.test.labels,prediction_result,9745,20)
接着,打开Anaconda Prompt,详见 tensorflow入门(3):关于TensorBoard 中的 Step 2 和 Step 3。
以上。参考Mooc课程吴明晖老师的《深度学习应用开发-TensorFlow实践》。