#LeNet-5学习记录
初次接触TensorFlow,通过学习学长的讲课笔记https://blog.csdn.net/LLyj_/article/details/88933773,以及另一个学长的讲解,记录的一点点学习笔记。
1.LeNet-5
1.INPUT层
2.C1层
#创建第一层卷积
#参数个数5 * 5 * 1 * 32 每个5 * 5 * 1的卷积核能得到一个通道,32个5* 5 * 1进行卷积可以得到32个通道
#一共有32个卷积核又因为padding“same”前后尺寸不变,所以得到特征图大小为28 * 28 * 32
#激活函数增加神经网络模型的非线性
with tf.variable_scope("C1-conv",reuse=resuse):
# tf.get_variable共享变量
# [5, 5, 1, 32]卷积核大小为5×5×1,有32个
# stddev正太分布的标准差
conv1_weights = tf.get_variable("weight", [5, 5, 1, 32],
initializer=tf.truncated_normal_initializer(stddev=0.1))
# tf.constant_initializer初始化为常数,这个非常有用,通常偏置项就是用它初始化的
conv1_biases = tf.get_variable("bias", [32], initializer=tf.constant_initializer(0.0))
# strides:卷积时在图像每一维的步长,这是一个一维的向量,长度4
# padding=’SAME’,表示padding后卷积的图与原图尺寸一致,激活函数relu()
conv1 = tf.nn.conv2d(input_tensor, conv1_weights, strides=[1, 1, 1, 1], padding="SAME")
relu1 = tf.nn.relu(tf.nn.bias_add(conv1, conv1_biases))
S2层
#创建第一个池化层
#2 * 2的最大池化,能使图片尺寸缩小一半
#池化后得到14 * 14 * 32
# tf.name_scope的主要目的是为了更加方便地管理参数命名。
# 与 tf.Variable() 结合使用。简化了命名
with tf.name_scope("S2-max_pool",):
# ksize:池化窗口的大小,取一个四维向量,一般是[1, height, width, 1],
# 因为我们不想在batch和channels上做池化,所以这两个维度设为了1
# strides:窗口在每一个维度上滑动的步长,一般也是[1, stride,stride, 1]
pool1 = tf.nn.max_pool(relu1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")
C3层
#创建第二个卷积层
#操作同第一个卷积层
#这里初始化了64个偏置项
#第二次卷积卷积核个数为64
#得到特征图为14 * 14 * 64
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))
S4层
#创建第二个池化层
#再次缩小得到7 * 7 * 64
#nodes=7 * 7 * 64 = 3136
#shape[0]是由自动计算得来,常设为-1
#将矩阵变为线性
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")
# get_shape()函数可以得到这一层维度信息,由于每一层网络的输入输出都是一个batch的矩阵,
# 所以通过get_shape()函数得到的维度信息会包含这个batch中数据的个数信息
# shape[1]是长度方向,shape[2]是宽度方向,shape[3]是深度方向
# shape[0]是一个batch中数据的个数,reshape()函数原型reshape(tensor,shape,name)
shape = pool2.get_shape().as_list()
nodes = shape[1] * shape[2] * shape[3] # nodes=3136
reshaped = tf.reshape(pool2, [shape[0], nodes])
C5层
#创建第一个全连接层
#这里的权重参数是 nodes * 512 ,即3136 * 512
#矩阵相乘得到B * 512,B指batch中的数据数
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))
# if regularizer != None:
tf.add_to_collection("losses", regularizer(Full_connection1_weights))
Full_connection1_biases = tf.get_variable("bias", [512],
initializer=tf.constant_initializer(0.1))
if avg_class ==None:
Full_1 = tf.nn.relu(tf.matmul(reshaped, Full_connection1_weights) + \
Full_connection1_biases)
else:
Full_1 = tf.nn.relu(tf.matmul(reshaped, avg_class.average(Full_connection1_weights))
+ avg_class.average(Full_connection1_biases))
F6层
#创建第二个全连接层
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))
# if regularizer != None:
tf.add_to_collection("losses", regularizer(Full_connection2_weights))
Full_connection2_biases = tf.get_variable("bias", [10],
initializer=tf.constant_initializer(0.1))
if avg_class == None:
result = tf.matmul(Full_1, Full_connection2_weights) + Full_connection2_biases
else:
result = tf.matmul(Full_1, avg_class.average(Full_connection2_weights)) + \
avg_class.average(Full_connection2_biases)
OUTPUT层
2.小结
仅有一点点初步的认识,还需要更多的学习来完善知识体系,对自己第一次学习的记录,体会还不深,有很多概念依旧模糊,记录下来用以日后完善。
3.代码以及代码中的注释来源
https://blog.csdn.net/LLyj_/article/details/88933773