TensorFlow北大公开课学习笔记5.3-手写数字识别准确率输出 (只加载数据,不加载图结构)

学习了:

       在mnist数据集上训练模型,输出手写数字识别准确lv,具体就是

       前向(权重函数、偏置函数、前向传播函数,构建网络结构) 

       后向(读入数据、backward(mnist),交叉熵损失函数、正则化、滑动平均、指数下降、实例化saver对象、保存模型)

       test(加载数据,不加载图结构、定义网络结构、实例化带滑动平均的saver对象、 计算准确率)

 

 TensorFlow北大公开课学习笔记5.3-手写数字识别准确率输出 (只加载数据,不加载图结构)

结论:

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中加入下面代码即可实现断点续训

TensorFlow北大公开课学习笔记5.3-手写数字识别准确率输出 (只加载数据,不加载图结构)

TensorFlow北大公开课学习笔记5.3-手写数字识别准确率输出 (只加载数据,不加载图结构)

上面就显示从第6002次迭代接着训练.....


                                                   正   文 

                          TensorFlow北大公开课学习笔记5.3-手写数字识别准确率输出 (只加载数据,不加载图结构)

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文件后:

TensorFlow北大公开课学习笔记5.3-手写数字识别准确率输出 (只加载数据,不加载图结构)

在执行backward这个文件后,动态生成一些文件,一直在更新,最后在model生成了这些文件,什么意思呢? 

TensorFlow北大公开课学习笔记5.3-手写数字识别准确率输出 (只加载数据,不加载图结构)

  •  加载模型
  • 当我们基于checkpoint文件(ckpt)加载参数时,实际上我们使用Saver.restore取代了initializer的初始化
  • checkpoint文件会记录保存信息,通过它可以定位最新保存的模型:

TensorFlow北大公开课学习笔记5.3-手写数字识别准确率输出 (只加载数据,不加载图结构)

checkpoint文件会记录保存信息,通过它可以定位最新保存的模型:

1

2

ckpt = tf.train.get_checkpoint_state('./model/')

print(ckpt.model_checkpoint_path)

 TensorFlow北大公开课学习笔记5.3-手写数字识别准确率输出 (只加载数据,不加载图结构)

.meta文件保存了当前图结构

.index文件保存了当前参数名

.data文件保存了当前参数值

 tf.train.import_meta_graph函数给出model.ckpt-n.meta的路径后会加载图结构,并返回saver对象

1

ckpt = tf.train.get_checkpoint_state('./model/')

 

tf.train.Saver函数会返回加载默认图的saver对象,saver对象初始化时可以指定变量映射方式,根据名字映射变量(『TensorFlow』滑动平均)

1

saver = tf.train.Saver({"v/ExponentialMovingAverage":v}) 

saver.restore函数给出model.ckpt-n的路径后会自动寻找参数名-值文件进行加载

1

2

saver.restore(sess,'./model/model.ckpt-0')

saver.restore(sess,ckpt.model_checkpoint_path)

  • 简化版本   

# 连同图结构一同加载

 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!

TensorFlow北大公开课学习笔记5.3-手写数字识别准确率输出 (只加载数据,不加载图结构)

TensorFlow北大公开课学习笔记5.3-手写数字识别准确率输出 (只加载数据,不加载图结构)

2、探究下b的初始化 

TensorFlow北大公开课学习笔记5.3-手写数字识别准确率输出 (只加载数据,不加载图结构)

做了上面改变,发现初始化为0,效果会好些。甚至常量0.01初始化后既然比用random还效果差。当然可能参数设置的有问题,我试一下0.1、

TensorFlow北大公开课学习笔记5.3-手写数字识别准确率输出 (只加载数据,不加载图结构)TensorFlow北大公开课学习笔记5.3-手写数字识别准确率输出 (只加载数据,不加载图结构)

      给成0.1还是有提升的,这个0.01是借鉴cs231n的课程中的偏置来说的,所以说哈,可能这个是神经网络,还是简单点,哦初始化好了!(不知道正确么,我的猜测)

TensorFlow北大公开课学习笔记5.3-手写数字识别准确率输出 (只加载数据,不加载图结构)

 

TensorFlow北大公开课学习笔记5.3-手写数字识别准确率输出 (只加载数据,不加载图结构)

我想知道,初始化时是0.01,训练后加载参数,到底是用谁的?按理说是用加载的b,但是我怎么打印Variable的值呢?

其实,在成功加载模型后,把变量的值初始化为模型中保存的值,所以就不需要再执行变量的吃实话操作了

init_op = tf.global_variables_initializer() 这句话那你会发现在test中没有,但是在backward中是有的。这便是为什么初始化了0.01,但是还是会用加载模型的值初始化。

完美解决疑惑,感谢书本:tensorflow入门与实战。