Tensorflow学习指导笔记(一)

题记

深度神经网络学习不容易,尤其是我自学的人。
我根据书本的例子对这个例子进行简化剖析,与有志人士同勉。
本例子是使用全连接神经网络,与MNIST手写数据集进行分类。

前向传播逻辑

什么是前向传播?请看(日后补上)。

函数(get_weight_variable):计算权重weight

输入:shape, regularizer
流程:

  1. 获取一个或创建一个weights变量(tf.get_variable)。
    1. initializer为tf.truncated_normal_initializer()
  2. 如果有regularizer,将权重正则化后存储名为‘losses’的集合(tf.add_to_collection)。
  3. 返回权重值。
  • 注1:(权重值请看(日后补上))

函数(inference):前向传播过程

输入:input_tensor, regularizer
流程:

  1. 使用上下文管理第一层神经网络‘layer1’(tf.variable_scope)。
    1. 定义权重的变量(get_weiht_variable)
    2. 定义偏置量biases的变量(tf.get_variable)。
      1. initializer为tf.constant_initialzer。
    3. 计算前向传播的公式,输入 * 权重 + 偏置。
      1. 如果这是隐藏层,可以加入去线性化的激活函数,如tf.nn.relu或sigmoid
  2. 使用上下文管理第二层神经网络‘layer2’(同上), 这层结果可能是输出。
    1. 定义权重的变量(get_weiht_variable)
    2. 定义偏置量biases的变量(tf.get_variable)。
      1. initializer为tf.constant_initialzer。
    3. 计算前向传播的公式,输入 * 权重 + 偏置。是输出层就不加入激活函数了。
  3. 如何还有n层如上。
  4. 返回最终的传播结果。
  • 注2:(上下文管理请看(日后补上))
  • 注3:(激活函数请看(日后补上))
  • 注3:(前向传播请看(日后补上))

前向传播过程代码部分

# -*- coding: utf-8 -*-
# Created by Administrator on 2020/1/17
# Copyright (c) 2020 Administrator. All rights reserved.
# @Auther   :   Dish
# @Project  :   MNIST_Pro
# @FileName :   mnist_inference.py
# @Software :   PyCharm
# @Blog     :   https://blog.csdn.net/AlexDish
# 定义了前向传播的过程以及神经网络中的参数
import tensorflow as tf

# 定义神经网络结构相关的参数
INPUT_NODE = 784  # 图片为28*28分辨率的
OUTPUT_NODE = 10  # 输出为0~9共10个数据
LAYER1_NODE = 500  # 隐藏层500个点

def get_weight_variable(shape, regularizer):
    # 通过get_variable函数来获取变量。在训练神经网络时会创建这些变量;
    # 在测试时会通过保存的模型加载这些变量的取值。也将正则化损失加入损失集合。
    weights = tf.get_variable('weights', shape, initializer=tf.truncated_normal_initializer(stddev=0.1))
    if regularizer != None:
        tf.add_to_collection('losses', regularizer(weights))
    return weights

# 定义神经网络的前向传播过程
def infernce(input_tensor, regularizer):
    # 声明第一层神经网络的变量并完成前向传播过程
    with tf.variable_scope('layer1'):
        # 如果在同一个程序中多次调用,在第一次调用之后需要将reuse参数设置为Ture
        weights = get_weight_variable([INPUT_NODE, LAYER1_NODE], regularizer)
        biases = tf.get_variable('biases', [LAYER1_NODE], initializer=tf.constant_initializer(0.0))
        layer1 = tf.nn.relu(tf.matmul(input_tensor, weights) + biases)
    # 声明第二层神经网络的变量并完成前向传播过程
    with tf.variable_scope('layer2'):
        weights = get_weight_variable([LAYER1_NODE, OUTPUT_NODE], regularizer)
        biases = tf.get_variable('biases', [OUTPUT_NODE], initializer=tf.constant_initializer(0.0))
        layer2 = tf.matmul(layer1, weights) + biases
    
    # 返回最后前向传播的结果
    return layer2

前向传播训练的过程

函数(train):训练

  1. 定义输入的张量占位符(x)
  2. 定义输出的张量占位符(y_)真实结果
  3. 定义正则化对象(可用L1或L2,tf.contrib.layers.l1_regularizer, tf.contrib.layers.l2_regularizer, tf.contrib.layers.l1_l2_regularizer)
    1. 这里有一个可调参数(REGULARIZTION_RATE)通常0.0001
  4. 写出由前向传播和正则产生的输出(y)
  5. 定义训练步数的变量(tf.Variable), 注意是不可训练的。
  6. 滑动平均操作
    1. 创建滑动平均对象(tf.train.ExponentialMovingAverage)
      1. 参数一,衰减值(MOVING_AVERAGE_DECAY)通常0.99
      2. 参数二,训练步数值, 就是更新次数
    2. 创建滑动平均的操作(对象.apply)
      1. 参数一,所有可以训练的变量(tf.trainable_variables)
  7. 损失的计算
    1. 损失函数的公式,带sotfmax的交叉熵(tf.nn.sparse_softmax_cross_entropy_with_logits)
      1. 参数logits,训练前向传播的值
      2. 参数labels,真实的数据值(tf.argmax,将array中最大的值取出index)
    2. 损伤函数的计算平均值(tf.reduce_mean)。
      1. 参数,计算出的损失函数
    3. 最终的损失值,刚才算出来的损失与之前算出来全部相加的损失的相加。
      1. 之前算出来的(tf.get_collection(‘losses’))
      2. 全部相加tf.add_n
  8. 学习率的计算(tf.train.exponential_decay)
    1. 参数一,基础学习率(LEARNING_RATE_BASE)通常0.8
    2. 参数二,训练步数
    3. 参数三,衰减步数,每一批训练为一次衰减,即总数 / BATCH_SIZE 通常100
    4. 参数四,衰减率(LEARNING_RATGE_DECAY)通常0.99非常接近1但不到
  9. 使用梯度下降算法进行优化学习率(tf.train.GradientDescentOptimizer),即训练步率
    1. 参数,就针对学习率
    2. 与损失值与步数,加操作取最小
  10. 训练步率进行滑动平均计算
    1. 使用tf.control_dependencies的with块
      1. 参数,训练步率与滑动平均的操作的列表
      2. 得出训练操作,使用tf.no_op对齐(name=‘train’)
  11. 持久类对象 tf.train.Saver()
  12. 定义Session进行训练
    1. 初始化全部变量 tf.global_variables_initialzer().run()
    2. 轮询TRAIN_STEPS次
      1. 从next_batch中获取xs, ys
      2. 将{x:xs, y_:ys}去运行出(使用列表)训练操作,损失值, 训练步数
      3. 每1000次打印一次
      4. 每1000次将sess 保存到指定地方,还有步数
  • 注4:(正则化请看(日后补上))
  • 注5:(滑动平均请看(日后补上))
  • 注6:(损失值、交叉熵请看(日后补上))
  • 注7:(学习率请看(日后补上))
  • 注7:(梯度下降算法请看(日后补上))

前向传播训练的过程代码部分

# -*- coding: utf-8 -*-
# Created by Administrator on 2020/1/17
# Copyright (c) 2020 Administrator. All rights reserved.
# @Auther   :   Dish
# @Project  :   MNIST_Pro
# @FileName :   mnist_train.py
# @Software :   PyCharm
# @Blog     :   https://blog.csdn.net/AlexDish
# 定义了前向传播的过程以及神经网络中的参数
import os
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
from mnist_inference import *

# 配置神经网络的参数
BATCH_SIZE = 100
LEARNING_RATE_BASE = 0.8
LEARNING_RATE_DECAY = 0.99
REGULARIZATION_RATE = 0.0001
TRAING_STEPS = 30000
MOVING_AVERAGE_DECAY = 0.99
# 模型保存的路径和文件名
MODEL_SAVE_PATH = './model/'
MODEL_NAME = 'model.ckpt'

def train(mnist):
    x = tf.placeholder(tf.float32, [None, INPUT_NODE], name='x-input')
    y_ = tf.placeholder(tf.float32, [None, OUTPUT_NODE], name='y-input')
    # 使用L2正则化
    regularizer = tf.contrib.layers.l2_regularizer(REGULARIZATION_RATE)
    # 计算前向传播过程的值
    y = infernce(x, regularizer)
    global_step = tf.Variable(0, trainable=False)
    # 滑动平均对象
    variable_averages = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)
    # 滑动平均操作
    variable_averages_op = variable_averages.apply(tf.trainable_variables())
    # 损失函数的计算公式
    cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1))
    # 损失函数的计算平均值
    cross_entropy_mean = tf.reduce_mean(cross_entropy)
    # 最终损失值
    loss = cross_entropy_mean + 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
    )
    # 使用梯度下降算法进行优化
    train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)
    # 将梯度下降算法的步值进行滑动平均计算
    with tf.control_dependencies([train_step, variable_averages_op]):
        train_op = tf.no_op(name='train')
    
    # 初始化TensorFlow持久化类
    saver = tf.train.Saver()
    with tf.Session() as sess:
        tf.global_variables_initializer().run()
        for i in range(TRAING_STEPS):
            xs, ys = mnist.train.next_batch(BATCH_SIZE)
            _, loss_value, step = sess.run([train_op, loss, global_step], feed_dict={x: xs, y_: ys})
            # 每1000轮保存一次模型
            if i % 1000 == 0:
                print('After {} training step(s), loss on training batch is {}'.format(step, loss_value))
                saver.save(sess, os.path.join(MODEL_SAVE_PATH, MODEL_NAME), global_step=global_step)
                
def main(argv=None):
    mnist = input_data.read_data_sets('./tensorflow-tutorial-master/Deep_Learning_with_TensorFlow/datasets/MNIST_data', one_hot=True)
    train(mnist)

if __name__ == '__main__':
    tf.app.run()

验证的过程

函数(evaluate):验证

  1. 定义一个图作为默认图
  2. 定义输入的张量占位符(x)
  3. 定义输出的张量占位符(y_)真实结果
  4. 通过前向传播计算输出(y)
  5. 定义验证的x与y数据
  6. 计算正确率
    1. 使用y与y_的index对比,是否相等(tf.equal)
    2. 正确率就是上面相等的平均值,求之前需要转为tf.float32(tf.cast)
  7. 滑动平均的对象加载模型
    1. 创建滑动平均对象(tf.train.ExponentialMovingAverage), 输入滑动衰减率
    2. 获取变量列表,滑动平均对象的variables_to_restore方法。
    3. 持久化对象,从刚获取来的变量列表中来(tf.train.Saver)
  8. 重复下面步骤
  9. 创建Session
  10. 从路径获取ckpt(tf.train.get_checkpoint_state)
  11. 如果获取的模型和路径非空去测试
    1. 持久化对象调用restore方法,sess与获取的模型路径
    2. 截取文件名中的训练步数(split)
    3. 将正确率的张量和数据进行run一下得出分数
    4. 打印结果
  12. 如果获取的模型和路径有空就说没有模型。

验证的过程代码部分

# -*- coding: utf-8 -*-
# Created by Administrator on 2020/1/17
# Copyright (c) 2020 Administrator. All rights reserved.
# @Auther   :   Dish
# @Project  :   MNIST_Pro
# @FileName :   mnist_eval.py
# @Software :   PyCharm
# @Blog     :   https://blog.csdn.net/AlexDish
# 定义了测试过程
import time
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
from mnist_inference import *
from mnist_train import *

EVAL_INTERVAL_SECS = 10

def evaluate(mnist):
    with tf.Graph().as_default() as g:
        x = tf.placeholder(tf.float32, [None, INPUT_NODE], name='x-input')
        y_ = tf.placeholder(tf.float32, [None, OUTPUT_NODE], name='y-input')
        validate_feed = {x: mnist.validation.images, 
                         y_: mnist.validation.labels}
        # 主要是测试结果,不关注正则化损失的值
        y = infernce(x, None)
        # 计算前向传播的结果计算正确率
        correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
        
        # 通过变量重命名的方式来加载模型,这样在前向传播的过程中就不需要调用求滑动平均的函数来获取平均值。
        variable_averages = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY)
        variables_to_restore = variable_averages.variables_to_restore()
        saver = tf.train.Saver(variables_to_restore)
        
        while True:
            with tf.Session() as sess:
                ckpt = tf.train.get_checkpoint_state(MODEL_SAVE_PATH)
                if ckpt and ckpt.model_checkpoint_path:
                    saver.restore(sess, ckpt.model_checkpoint_path)
                    global_step = ckpt.model_checkpoint_path.split('/'[-1].split('-')[-1])
                    accuracy_score = sess.run(accuracy, feed_dict=validate_feed)
                    print('After {} training step(s), validation accuracy = {}'.format(global_step, accuracy_score))
                else:
                    print('No checkpoint file found')
            time.sleep(EVAL_INTERVAL_SECS)

def main(argv=None):
    mnist = input_data.read_data_sets('./tensorflow-tutorial-master/Deep_Learning_with_TensorFlow/datasets/MNIST_data', one_hot=True)
    evaluate(mnist)

if __name__ == '__main__':
    tf.app.run()
发布了4 篇原创文章 · 获赞 0 · 访问量 251

猜你喜欢

转载自blog.csdn.net/AlexDish/article/details/104025669