LeNet-5 识别MNIST Tensorflow源码

1、tensorflow中通过共享 **变量作用域(variable_scope)来实现共享变量 ,节约变量存储空间.TensorFlow用于变量管理的函数主要有两个:
(1) tf. get_variable() 用于创建或获取变量的值
(2) tf.variable_scope() 用于生成上下文管理器,创建命名空间,命名空间可以嵌套。
函数
tf.get_variable()**既可以创建变量,也可以获取变量。用函数tf.variable_scope()中的参数reuse来控制,分两种情况进行说明:
(1) 设置reuse=False时,函数get_variable()表示创建变量;

import tensorflow as tf 
with tf.variable_scope("foo"): 
	v=tf.get_variable("v",[1],initializer=tf.constant_initializer(1.0)) 
	v1=tf.get_variable("v",[1])
# ValueError: Variable foo/v already exists, disallowed. 

(2) 设置reuse=True时,函数get_variable()表示获取变量.

import tensorflow as tf
with tf.variable_scope("foo"):
    v=tf.get_variable("v",[1],initializer=tf.constant_initializer(1.0))
    
with tf.variable_scope("foo",reuse=True):
    v1=tf.get_variable("v",[1])
print(v1==v)    #结果为:True

在tf.variable_scope()函数中,设置reuse=True时,在其命名空间"foo"中执行函数get_variable()时,表示获取变量"v"。若在该命名空间中还没有该变量,则在获取时会报错,如下面的例子:

import tensorflow as tf 
with tf.variable_scope("foo",reuse=True):
    v1=tf.get_variable("v",[1])
    # ValueError: Variable foo/v does not exist, or was not created with tf.get_variable()

TensorFlow通过tf. get_variable()和tf.variable_scope()两个函数,可以创建多个并列的或嵌套的命名空间,用于存储神经网络中的各层的权重、偏置、学习率、滑动平均衰减率、正则化系数等参数值,神经网络不同层的参数可放置在不同的命名空间中。同时,变量重用检错和读取不存在变量检错两种机制保证了数据存放的安全性。

#part1:必要模块导入, numpy主要是矩阵变化和运算
import tensorflow as tf
import numpy as np
from tensorflow.examples.tutorials.mnist import input_data

#part2:读数据,预处理
mnist = input_data.read_data_sets("/home/promise/PycharmProjects/LeNet-5", one_hot = True)

#part3:超参数初始化
batch_size = 100
learning_rate = 0.01
learning_rate_decay = 0.99
max_steps = 30000

#part4:设计网络结构
def hidden_layer(input_tensor, regularizer, avg_class, resuse):
    with tf.variable_scope("C1-conv", reuse=resuse):#含有训练参数层(卷积层,全连接层)创建变量空间,variable_scope()常与get_variable()搭配使用
        conv1_weights = tf.get_variable("weight", [5,5,1,32], initializer=tf.truncated_normal_initializer(stddev=0.1))#常用truncated_normal_initializer()初始化含可训练权重层,且stddev长设置为0.1
        con1_biases = tf.get_variable("bias", [32], initializer=tf.constant_initializer(0.0))#卷积层初始化为0.0
        conv1 = tf.nn.conv2d(input_tensor, conv1_weights, strides=[1,1,1,1], padding="SAME")
        relu1 = tf.nn.relu(tf.nn.bias_add(conv1, con1_biases))
    with tf.name_scope("S2-max_pool",):#池化层前用name_scope(,)
        pool1 = tf.nn.max_pool(relu1, ksize=[1,2,2,1], strides=[1,2,2,1],padding="SAME")

    with tf.variable_scope("C3-conv", reuse=resuse):
        conv2_weights = tf.get_variable("weight", [5,5,32,64], initializer=tf.truncated_normal_initializer(stddev=0.1))
        conv2_biases = tf.get_variable("bias", [64], initializer=tf.constant_initializer(0.0))
        conv2 = tf.nn.conv2d(pool1, conv2_weights, strides=[1,1,1,1], padding="SAME")
        relu2 = tf.nn.relu(tf.nn.bias_add(conv2, conv2_biases))
    with tf.name_scope("S4-max_pool",):
        pool2 = tf.nn.max_pool(relu2, ksize=[1,2,2,1], strides=[1,2,2,1], padding="SAME")
        #多维矩阵转化为:batch_size×features的二维矩阵
        shape = pool2.get_shape().as_list()
        nodes = shape[1] * shape[2] * shape[3]
        reshaped = tf.reshape(pool2, [shape[0], nodes])

    with tf.variable_scope("layer5-full1",reuse=resuse):
        Full_connection1_weights = tf.get_variable("weight", [nodes, 512], initializer=tf.truncated_normal_initializer(stddev=0.1))
        tf.add_to_collection("losses", regularizer(Full_connection1_weights))#全连接层权重需要加正则化项(数量多)
        Full_connection1_biasses = tf.get_variable("bias", [512], initializer=tf.constant_initializer(0.1))#全连接层偏置项初始化为0.1
        if avg_class == None:
            Full_1 = tf.nn.relu(tf.matmul(reshaped, Full_connection1_weights) + Full_connection1_biasses)
        else:
            Full_1 = tf.nn.relu(tf.matmul(reshaped, avg_class.average(Full_connection1_weights)) + avg_class.average(Full_connection1_biasses))#只对全连接层进行平滑操作

    with tf.variable_scope("layer6-full2", reuse=resuse):
        Full_connection2_weights = tf.get_variable("weight", [512, 10], initializer=tf.truncated_normal_initializer(stddev=0.1))
        tf.add_to_collection("losses", regularizer(Full_connection2_weights))
        Full_connection2_biasses = tf.get_variable("bias", [10], initializer=tf.constant_initializer(0.1))
        if avg_class == None:
            result = tf.nn.relu(tf.matmul(Full_1, Full_connection2_weights) + Full_connection2_biasses)
        else:
            result = tf.nn.relu(tf.matmul(Full_1, avg_class.average(Full_connection2_weights)) + avg_class.average(Full_connection2_biasses))
    return result

x = tf.placeholder(tf.float32, [batch_size, 28,28,1], name="x-input")#x第一维为batch_size
y_ = tf.placeholder(tf.float32, [None, 10], name="y-input")#y的最后一维是classes

#part5:正则化,损失函数,优化方法(定义训练方法)
regularizer = tf.contrib.layers.l2_regularizer(0.0001)#l2范数
y = hidden_layer(x, regularizer, avg_class=None, resuse=False)#无平滑训练,所以变量空间不需要复用
training_step = tf.Variable(0, trainable=False)
variable_averages = tf.train.ExponentialMovingAverage(0.99, training_step)
variable_averages_op = variable_averages.apply(tf.trainable_variables())#对可训练变量实行平滑训练
average_y = hidden_layer(x, regularizer, variable_averages, resuse=True)#平滑训练变量空间需要复用

cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.arg_max(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,training_step,mnist.train.num_examples/batch_size, learning_rate_decay,staircase=True)
train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=training_step)
with tf.control_dependencies([train_step, variable_averages_op]):#train_step写成training_step造成准确率下降
    train_op = tf.no_op(name='train')#反向传播过程中同步更新影子变量

#part6:模型评价
crorent_prediction = tf.equal(tf.arg_max(average_y, 1), tf.arg_max(y_, 1))#用平滑处理预测结果进行评价
accuracy = tf.reduce_mean(tf.cast(crorent_prediction, tf.float32))
'''
with tf.Session() as sess:
    tf.global_variables_initializer().run()
    for i in range(max_steps):
        if i % 1000 == 0:
            x_val, y_val = mnist.validation.next_batch(batch_size)
            reshaped_x2 = np.reshape(x_val, (batch_size, 28, 28, 1))
            validate_feed = {x:reshaped_x2, y_:y_val}
            validate_accuracy = sess.run(accuracy, feed_dict=validate_feed)
            print("After %d training steps, validation accuracy using average model is %g%%" % (i, validate_accuracy * 100))
        x_train, y_train = mnist.train.next_batch(batch_size)
        reshaped_xs = np.reshape(x_train, (batch_size, 28, 28, 1))
        sess.run(train_op, feed_dict={x:reshaped_xs, y_:y_train})
'''
#part7:执行训练
with tf.Session() as sess:
    tf.global_variables_initializer().run()
    for i in range(max_steps):
        if i %1000==0:
            x_val, y_val = mnist.validation.next_batch(batch_size)
            reshaped_x2 = np.reshape(x_val, (batch_size,28,28, 1))#测试和训练数据都得变化为标准输入格式
            validate_feed = {x: reshaped_x2, y_: y_val}

            validate_accuracy = sess.run(accuracy, feed_dict=validate_feed)
            print("After %d trainging step(s) ,validation accuracy"
                  "using average model is %g%%" % (i, validate_accuracy * 100))

        x_train, y_train = mnist.train.next_batch(batch_size)

        reshaped_xs = np.reshape(x_train, (batch_size ,28,28,1))
        sess.run(train_op, feed_dict={x: reshaped_xs, y_: y_train})
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LeNet-5神经网络 C源代码,这个写的比较好,可以用gcc编译去跑,结合理论可以对深度学习有更深刻的了解 介绍 根据YANN LECUN的论文《Gradient-based Learning Applied To Document Recognition》设计的LeNet-5神经网络,C语言写成,不依赖任何第三方库。 MNIST手写字符集初代训练识别率97%,多代训练识别率98%。 DEMO main.c文件为MNIST数据集的识别DEMO,直接编译即可运行,训练集60000张,测试集10000张。 项目环境 该项目为VISUAL STUDIO 2015项目,用VISUAL STUDIO 2015 UPDATE1及以上直接打开即可编译。采用ANSI C编写,因此源码无须修改即可在其它平台上编译。 如果因缺少openmp无法编译,请将lenet.c中的#include和#pragma omp parallel for删除掉即可。 API #####批量训练 lenet: LeNet5的权值的指针,LeNet5神经网络的核心 inputs: 要训练的多个图片对应unsigned char二维数组的数组,指向的二维数组的batchSize倍大小内存空间指针。在MNIST测试DEMO中二维数组为28x28,每个二维数组数值分别为对应位置图像像素灰度值 resMat:结果向量矩阵 labels:要训练的多个图片分别对应的标签数组。大小为batchSize batchSize:批量训练输入图像(二维数组)的数量 void TrainBatch(LeNet5 *lenet, image *inputs, const char(*resMat)[OUTPUT],uint8 *labels, int batchSize); #####单个训练 lenet: LeNet5的权值的指针,LeNet5神经网络的核心 input: 要训练的图片对应二维数组 resMat:结果向量矩阵 label: 要训练的图片对应的标签 void Train(LeNet5 *lenet, image input, const char(*resMat)[OUTPUT],uint8 label); #####预测 lenet: LeNet5的权值的指针,LeNet5神经网络的核心 input: 输入的图像的数据 labels: 结果向量矩阵指针 count: 结果向量个数 return 返回值为预测的结果 int Predict(LeNet5 *lenet, image input, const char(*labels)[LAYER6], int count); #####初始化 lenet: LeNet5的权值的指针,LeNet5神经网络的核心
【为什么要学习这门课程】深度学习框架如TensorFlow和Pytorch掩盖了深度学习底层实现方法,那能否能用Python代码从零实现来学习深度学习原理呢?本课程就为大家提供了这个可能,有助于深刻理解深度学习原理。左手原理、右手代码,双管齐下!本课程详细讲解深度学习原理并进行Python代码实现深度学习网络。课程内容涵盖感知机、多层感知机、卷积神经网络、循环神经网络,并使用Python 3及Numpy、Matplotlib从零实现上述神经网络。本课程还讲述了神经网络的训练方法与实践技巧,且开展了代码实践演示。课程对于核心内容讲解深入细致,如基于计算图理解反向传播算法,并用数学公式推导反向传播算法;另外还讲述了卷积加速方法im2col。【课程收获】本课程力求使学员通过深度学习原理、算法公式及Python代码的对照学习,摆脱框架而掌握深度学习底层实现原理与方法。本课程将给学员分享深度学习的Python实现代码。课程代码通过Jupyter Notebook演示,可在Windows、ubuntu等系统上运行,且不需GPU支持。【优惠说明】 课程正在优惠中!  备注:购课后可加入白勇老师课程学习交流QQ群:957519975【相关课程】学习本课程的前提是会使用Python语言以及Numpy和Matplotlib库。相关课程链接如下:《Python编程的术与道:Python语言入门》https://edu.csdn.net/course/detail/27845《玩转Numpy计算库》https://edu.csdn.net/lecturer/board/28656《玩转Matplotlib数据绘图库》https://edu.csdn.net/lecturer/board/28720【课程内容导图及特色】
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值