TensorFlow北大公开课学习笔记5.3-手写数字识别准确率输出 (只加载数据,不加载图结构)
学习了:
在mnist数据集上训练模型,输出手写数字识别准确lv,具体就是
前向(权重函数、偏置函数、前向传播函数,构建网络结构)
后向(读入数据、backward(mnist),交叉熵损失函数、正则化、滑动平均、指数下降、实例化saver对象、保存模型)
test(加载数据,不加载图结构、定义网络结构、实例化带滑动平均的saver对象、 计算准确率)
结论:
1、w
将 # truncated_normal初始化权重,去掉过大偏离点的正态分布
w = tf.Variable(tf.truncated_normal(shape, stddev=0.1))
改成:w = tf.Variable(tf.random_normal(shape, mean=0, stddev=0.1))
借鉴的是vgg的初始化方法。明显提高了准确lv!
2、b
给成0.1还是有提升的,这个0.01是借鉴cs231n的课程中的偏置来说的,所以说哈,可能这个是神经网络,还是简单点,哦初始化好了!(不知道正确么,我的猜测)
3、在backward中加入下面代码即可实现断点续训
上面就显示从第6002次迭代接着训练.....
正 文
minist-forward.py
import tensorflow as tf
INPUT_NODE = 784 #输入神经元个数(28*28)
OUTPUT_NODE = 10 #输出神经元个数(10类,0-9)
LAYER1_NODE = 500 #隐藏层的node
# 权重函数
def get_weight(shape, regularizer):
# truncated_normal初始化权重,去掉过大偏离点的正态分布
w = tf.Variable(tf.truncated_normal(shape, stddev=0.1))
# 判断是否正则化,regularizer为空则不正则化
if regularizer != None: tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(regularizer)(w))
# 返回w
return w
# 偏置函数
def get_bias(shape):
# 使用tf.zeros初始化权重,全0
b = tf.Variable(tf.zeros(shape))
# 返回b
return b
# 前向传播函数,构建网络结构
def forward(x, regularizer):
#第一层
# 调用权重函数
w1 = get_weight([INPUT_NODE, LAYER1_NODE], regularizer)
# 调用偏置函数
b1 = get_bias([LAYER1_NODE])
# relu函数非线性化
y1 = tf.nn.relu(tf.matmul(x, w1) + b1)
#第二层
w2 = get_weight([LAYER1_NODE, OUTPUT_NODE], regularizer)
b2 = get_bias([OUTPUT_NODE])
# 因为后面用到softmax函数,为了使得满足概率分布,从而不用relu函数
y = tf.matmul(y1, w2) + b2
# 返回预测的y
return y
mnist_backward.py
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import mnist_forward
import os
BATCH_SIZE = 200
LEARNING_RATE_BASE = 0.1 #最初学习率
LEARNING_RATE_DECAY = 0.99 #学习率衰减率
REGULARIZER = 0.0001 #正则化系数
STEPS = 50000 #训练多少轮
MOVING_AVERAGE_DECAY = 0.99 #滑动平均衰减率
MODEL_SAVE_PATH="./model/" #模型保存路径
MODEL_NAME="mnist_model" #模型名称
def backward(mnist):
x = tf.placeholder(tf.float32, [None, mnist_forward.INPUT_NODE])
y_ = tf.placeholder(tf.float32, [None, mnist_forward.OUTPUT_NODE])
y = mnist_forward.forward(x, REGULARIZER)
# 运行了几轮BATCH_SIZE的计数器,初值给0,设为不被训练
global_step = tf.Variable(0, trainable=False)
# 定义损失函数
ce = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1))
cem = tf.reduce_mean(ce)
loss = cem + tf.add_n(tf.get_collection('losses'))
# 定义指数下降学习率
learning_rate = tf.train.exponential_decay(
LEARNING_RATE_BASE,
global_step,
mnist.train.num_examples / BATCH_SIZE,
LEARNING_RATE_DECAY,
staircase=True)
# 定义反向传播方法;含正则化
train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)
# 滑动平均(之前不会使用,现在要好好记住这些呀)
ema = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)
ema_op = ema.apply(tf.trainable_variables())
with tf.control_dependencies([train_step, ema_op]):
train_op = tf.no_op(name='train')
# 实例化saver对象
saver = tf.train.Saver()
with tf.Session() as sess:
init_op = tf.global_variables_initializer()
sess.run(init_op)
for i in range(STEPS):
# mnist.train.next_batch()函数将数据输入神经网络
xs, ys = mnist.train.next_batch(BATCH_SIZE)
# sess.run计算图节点运算。将数据xs和ys用feed_dict喂给train,loss,global_step ,得到_,loss_value,step.
_, loss_value, step = sess.run([train_op, loss, global_step], feed_dict={x: xs, y_: ys})
# 从1开始每隔1000输出,loss_value ,保存到对应路径下MODEL_SAVE_PATH/MODEL_NAME,且加在sess会话中
if i % 1000 == 0:
print("After %d training step(s), loss on training batch is %g." % (step, loss_value))
saver.save(sess, os.path.join(MODEL_SAVE_PATH, MODEL_NAME), global_step=global_step)
def main():
# 读入数据
mnist = input_data.read_data_sets("./data/", one_hot=True)
# 参数mnist,且调用backward函数
backward(mnist)
if __name__ == '__main__':
main()
minist_test.py
#coding:utf-8
import time #为了延迟
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import mnist_forward
import mnist_backward
TEST_INTERVAL_SECS = 5 #定义程序循环的间隔时间是5m
def Test(mnist):#读入mnist数据集
with tf.Graph().as_default() as g: #复现计算图
# 初始化 占位符
x = tf.placeholder(tf.float32, [None, mnist_forward.INPUT_NODE])
y_ = tf.placeholder(tf.float32, [None, mnist_forward.OUTPUT_NODE])
# 前向传播计算y的值
y = mnist_forward.forward(x, None)
# 实例化带滑动平均的saver对象,这样所有参数被加载时,都会被赋值为各自的滑动平均值
ema = tf.train.ExponentialMovingAverage(mnist_backward.MOVING_AVERAGE_DECAY)
ema_restore = ema.variables_to_restore()
saver = tf.train.Saver(ema_restore)
# 计算准确率
# tf.equal函数表示对比两个矩阵或者向量的元素,若对应元素相等,则返回True,若对应元素不相等,则返回False
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
# tf.cast函数将参数x转换为指定数据类型,correct_prediction是布尔值
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
while True:
with tf.Session() as sess:
# 加载ckpt,即将滑动平均值赋值给各个参数 通过get_checkpoint_state可以定位最新保存的模型
ckpt = tf.train.get_checkpoint_state(mnist_backward.MODEL_SAVE_PATH)
# 判断有没有模型,如果有,先恢复模型到当前会话
if ckpt and ckpt.model_checkpoint_path:
# 先恢复模型到当前会话
saver.restore(sess, ckpt.model_checkpoint_path)
# 恢复global_step值
global_step = ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1]
# 执行准确率计算
accuracy_score = sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels})
print("After %s training step(s), test accuracy = %g" % (global_step, accuracy_score))
else:
print('No checkpoint file found') #未找到模型
return
time.sleep(TEST_INTERVAL_SECS)
def main():
mnist = input_data.read_data_sets("./data/", one_hot=True)
Test(mnist)
if __name__ == '__main__':
main()
test这个py文件后:
在执行backward这个文件后,动态生成一些文件,一直在更新,最后在model生成了这些文件,什么意思呢?
- 加载模型
- 当我们基于checkpoint文件(ckpt)加载参数时,实际上我们使用Saver.restore取代了initializer的初始化
- checkpoint文件会记录保存信息,通过它可以定位最新保存的模型:
checkpoint文件会记录保存信息,通过它可以定位最新保存的模型:
1 2 |
|
.meta文件保存了当前图结构
.index文件保存了当前参数名
.data文件保存了当前参数值
tf.train.import_meta_graph函数给出model.ckpt-n.meta的路径后会加载图结构,并返回saver对象
1 |
|
tf.train.Saver函数会返回加载默认图的saver对象,saver对象初始化时可以指定变量映射方式,根据名字映射变量(『TensorFlow』滑动平均)
1 |
|
saver.restore函数给出model.ckpt-n的路径后会自动寻找参数名-值文件进行加载
1 2 |
|
- 简化版本
# 连同图结构一同加载
ckpt =
tf.train.get_checkpoint_state(
'./model/')
saver =
tf.train.import_meta_graph(ckpt.model_checkpoint_path
+
'.meta')
with tf.Session() as sess:
saver.restore(sess,ckpt.model_checkpoint_path)
# 只加载数据,不加载图结构,可以在新图中改变batch_size等的值
# 不过需要注意,Saver对象实例化之前需要定义好新的图结构,否则会报错
saver
=
tf.train.Saver()
with tf.Session() as sess:
ckpt
=
tf.train.get_checkpoint_state(
'./model/'
)
saver.restore(sess,ckpt.model_checkpoint_path)
我们直接给的代码是输入只加载数据,不加载图结构哦。你发现了吗?
链接:https://www.cnblogs.com/hellcat/p/6925757.html#_label0_1『TensorFlow』模型载入方法汇总讲的很清楚
1、修改w初始化:
将
# truncated_normal初始化权重,去掉过大偏离点的正态分布
w = tf.Variable(tf.truncated_normal(shape, stddev=0.1))
改成:
w = tf.Variable(tf.random_normal(shape, mean=0, stddev=0.1))
借鉴的是vgg的初始化方法。明显提高了准确lv!
2、探究下b的初始化
做了上面改变,发现初始化为0,效果会好些。甚至常量0.01初始化后既然比用random还效果差。当然可能参数设置的有问题,我试一下0.1、
给成0.1还是有提升的,这个0.01是借鉴cs231n的课程中的偏置来说的,所以说哈,可能这个是神经网络,还是简单点,哦初始化好了!(不知道正确么,我的猜测)
我想知道,初始化时是0.01,训练后加载参数,到底是用谁的?按理说是用加载的b,但是我怎么打印Variable的值呢?
其实,在成功加载模型后,把变量的值初始化为模型中保存的值,所以就不需要再执行变量的吃实话操作了
init_op = tf.global_variables_initializer() 这句话那你会发现在test中没有,但是在backward中是有的。这便是为什么初始化了0.01,但是还是会用加载模型的值初始化。
完美解决疑惑,感谢书本:tensorflow入门与实战。