欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【2】LeNet_5模型手写数字识别

程序员文章站 2022-07-14 11:41:46
...

1 搭建LeNet_5模型

定义前向传播过程文件为mnist_inference.py

# -*- coding: utf-8 -*-
#此文件定义了LeNet_5的前向传播过程
import tensorflow as tf

#配置神经网络的参数
#输入节点
INPUT_NODE=784
#输出节点
OUTPUT_NODE=10
#图像大小
IMAGE_SIZE=28
#图像通道
NUM_CHANNELS=1
#标签数目
NUM_LABELS=10

#定义第一层卷积层的尺寸和深度
CONV1_DEEP=32
CONV1_SIZE=5
#定义第二层卷积层的尺寸和深度
CONV2_DEEP=64
CONV2_SIZE=5
#全连接层的节点个数
FC_SIZE=512

#定义前向传播过程
def inference(input_tensor,regularizer):
    #第一层卷积层计算
    with tf.variable_scope('layel-conv1'):
        #获取第一层的权重
        con1_weight=tf.get_variable("weight",[CONV1_SIZE,CONV1_SIZE,NUM_CHANNELS,CONV1_DEEP],initializer=tf.truncated_normal_initializer(stddev=0.1))
        #获取第一层的偏值
        con1_biases=tf.get_variable("biases",[CONV1_DEEP],initializer=tf.constant_initializer(0.0))
        #计算第一层的卷积
        conv1=tf.nn.conv2d(input_tensor,con1_weight,strides=[1,1,1,1],padding='SAME')
        #添加第一层的偏值
        relu1=tf.nn.relu(tf.nn.bias_add(conv1,con1_biases))

    #第二层池化层计算 选取最大池化层
    with tf.name_scope('layer2-pool'):
        pool1=tf.nn.max_pool(relu1,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')

    #第三层卷积层的计算
    with tf.variable_scope('layer3-conv2'):
        #获取第三层的权重
        conv2_weight=tf.get_variable("weight",[CONV2_SIZE,CONV2_SIZE,CONV1_DEEP,CONV2_DEEP],initializer=tf.truncated_normal_initializer(stddev=0.1))
        #获取第三层的偏值
        conv2_biases=tf.get_variable("bias",[CONV2_DEEP],initializer=tf.constant_initializer(0.0))
        #计算第三层的卷积
        conv2=tf.nn.conv2d(pool1,conv2_weight,strides=[1,1,1,1],padding='SAME')
        #获取第三层的**函数
        relu2=tf.nn.relu(tf.nn.bias_add(conv2,conv2_biases))

    #第四层池化层计算
    with tf.name_scope('layer4_pool2'):
        pool2=tf.nn.max_pool(relu2,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
        #计算输出矩阵的维度
        pool_shape=pool2.get_shape().as_list()
        #计算矩阵变为向量后的长度
        nodes=pool_shape[1]*pool_shape[2]*pool_shape[3]
        #将第四层的输出变成一个batch的输出向量
        #pool_shape[0]表示一个batch的个数(即为行数)
        reshaped=tf.reshape(pool2,[pool_shape[0],nodes])
    #定义第五层的全连接传播过程
    with tf.variable_scope('layer5-fc1'):
        #获取第五层的权重
        fcl_weights=tf.get_variable("weight",[nodes,FC_SIZE],initializer=tf.truncated_normal_initializer(stddev=0.1))
        #全连接层需要添加正则化
        if regularizer !=None:
            tf.add_to_collection('losses',regularizer(fcl_weights))
        #获取添加了正则化的偏值
        fc1_biases=tf.get_variable("biases",[FC_SIZE],initializer=tf.constant_initializer(0.1))
        #**函数的计算
        fc1=tf.nn.relu(tf.matmul(reshaped,fcl_weights)+fc1_biases)
        #dropout函数避免过拟合问题
        #if train: fc1=tf.nn.dropout(fc1,0.5)


    #第六层全连接层
    with tf.variable_scope('layer6-fc2'):
        #获取第六层全连接层的权重
        fc2_weights=tf.get_variable("weight",[FC_SIZE,NUM_LABELS],initializer=tf.truncated_normal_initializer(stddev=0.1))
         #加入正则化
        if regularizer !=None:
            tf.add_to_collection('losses',regularizer(fc2_weights))
        #计算第六层的偏值
        fc2_biases=tf.get_variable("bias",[NUM_LABELS],initializer=tf.constant_initializer(0.1))
        #计算最后的输出
        logit=tf.matmul(fc1,fc2_weights)+fc2_biases

    return  logit

2 定义训练文件

定义模型训练文件mnist_train.py

# -*- coding: utf-8 -*-
#此文件定义了LeNet_5的训练过程
import  os
import tensorflow as tf
import  numpy as np
from tensorflow.examples.tutorials.mnist import input_data
#加载前向传播函数
import  mnist_inference
#配置神经网络参数
BATCH_SIZE=100
LEARNING_RATE_BASE=0.01
LEARNING_RATE_DECAY=0.99
REGULARAZTION_RATE=0.0001
TRAINGING_STEPS=30000
MOVING_AVERAGE_DECAY=0.99

#模型文件的保存路径
MODEL_SAVE_PATH="data//"
MODEL_NAME="model.ckpt"

def train(mnist):
    #准备输入数据
    x=tf.placeholder(tf.float32,[BATCH_SIZE,mnist_inference.IMAGE_SIZE,mnist_inference.IMAGE_SIZE,mnist_inference.NUM_CHANNELS],name='x-input')
    y_=tf.placeholder(tf.float32,[None,mnist_inference.OUTPUT_NODE],name='y-input')
    #定义正则化的方法L2
    regularizer=tf.contrib.layers.l2_regularizer(REGULARAZTION_RATE)
    #前向传播求出y
    y=mnist_inference.inference(x,regularizer)
    # 定义训练的轮数,需要用trainable=False参数指定不训练这个变量,
    # 这样同时也可以避免这个变量被计算滑动平均值??????????
    global_step=tf.Variable(0,trainable=False)
    #定义损失函数、学习率、滑动平均
    #滑动平均
    # 给定滑动平均衰减速率和训练轮数,初始化滑动平均类
    # 定训练轮数的变量可以加快训练前期的迭代速度
    variable_averages=tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY,global_step)
    # 用tf.trainable_variable()获取所有可以训练的变量列表,全部使用滑动平均
    variable_averages_op=variable_averages.apply(tf.trainable_variables())
    #交叉熵
    #softmax函数获取分类的概率分布
    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)
    #损失函数
    # 给损失加上正则化的损失
    # 使用get_collection获取losses集合的全部值的列表,然后用add_n求列表的所有值的和
    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)
    #训练方法 随机梯度下降法
    # 优化损失函数
    # global_step初始值为0,在loss更新后会+1,用来记录更新的次数
    # 返回值是训练之后的梯度,会随着global_step递增
    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")

    saver=tf.train.Saver()
    with tf.Session() as sess:
        tf.global_variables_initializer().run()
        for i in range(TRAINGING_STEPS):
            xs,ys=mnist.train.next_batch(BATCH_SIZE)
            #喂入数据
            reshaped_xs=np.reshape(xs,(BATCH_SIZE,mnist_inference.IMAGE_SIZE,mnist_inference.IMAGE_SIZE,mnist_inference.NUM_CHANNELS))
            _,loss_value,step=sess.run([train_op,loss,global_step],feed_dict={x:reshaped_xs,y_:ys})
            #打印结果
            if i %100 ==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(argv=None):
    mnist=input_data.read_data_sets("",one_hot=True)
    train(mnist)

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

3 模型训练结果(部分)

【2】LeNet_5模型手写数字识别