近期需要学习下tensorflow下的,minist字符识别,利用lenet5结构:
整个设计如下:
基础知识:with tf.variable_scope():和 tf.get_variable()对应:scope定义了 如下 get的作用域,当超过这个作用域后,w和b不起作用,所以下面第二次可以重新定义新的w和b,
注意 这个scope下如果要重复使用w和b这些自定义的变量,需要增加 如下实例:
def
my_image_filter(input_images):
with tf.variable_scope(
"conv1"
):
# Variables created here will be named "conv1/weights", "conv1/biases".
relu1
=
conv_relu(input_images, [
5
,
5
,
32
,
32
], [
32
])
with tf.variable_scope(
"conv2"
):
# Variables created here will be named "conv2/weights", "conv2/biases".
return
conv_relu(relu1, [
5
,
5
,
32
,
32
], [
32
])
with tf.variable_scope('layer——conv1') as scope:
result1
=
my_image_filter(image1)
scope.reuse_variables()
等价于#
with tf.variable_scope('layer——conv1',reuse=True):
result2
=
my_image_filter(image2)
上述,reuse——variables的功能是可以重复利用第一次利用的权重值,
另外try: catch的用法为 try:except:
如下实现: 5*5*64卷积 最大池化 5*5*32 卷积 最大池化 全连接(L2正则化 dropout)128 全连接 10(L2正则化)输出10个类别:
mnist_inference 实现如下:
import tensorflow as tf INPUT_NODE = 784 OUTPUT_NODE = 10 IMAGE_SIZE = 28 NUM_CHANNEL = 1 NUM_LABEL = 10 # LAYER1 CONV1_DEEP = 32 CONV1_SIZE = 5 # LAYER2 CONV2_DEEP = 64 CONV2_SIZE = 5 # 全连接层 FC_SIZE = 512
def inference(input_tensor,train,regularizer):
with tf.variable_scope('layer1-conv'):#注意此处tf.variable_scope表示这个作用域下定义了 w b(使用了get——variable)
w = tf.get_variable('w', [CONV1_SIZE,CONV1_SIZE,NUM_CHANNEL,CONV1_DEEP],
initializer=tf.truncated_normal_initializer(stddev=0.1))#定义权重矩阵为 5*5*单通道*32 初始化为均值0 标准差0.1
b = tf.get_variable('b',shape=[CONV1_DEEP],initializer=tf.constant_initializer(0.0))#初始化偏置为0
# filter shape is :[filter_height, filter_width, in_channels, out_channels]
# input tensor shape is:[batch, in_height, in_width, in_channels]
# `strides = [1, stride, stride, 1].
# return [batch, height, width, channels].
conv1 = tf.nn.conv2d(input_tensor,w,strides=[1,1,1,1],padding='SAME') #此处 input tensor 输入和filter卷积 运算,padding为same 插值为same后走到最后卷积完成,故outsize=(inputsize)/stride
#而 padding为 VALID 为表示只取有效位置,故会体积变小 outputsize = (inputwidth-filtersize+1)/stride
relu1 = tf.nn.relu(tf.nn.bias_add(conv1,b))# 激活函数用relu
with tf.variable_scope('layer2-pool'): pool1 = tf.nn.max_pool(relu1,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')# 利用 2*2 步长 做最大池化
with tf.variable_scope('layer3-conv'): w = tf.get_variable('w', [CONV2_SIZE, CONV2_SIZE, CONV1_DEEP, CONV2_DEEP], initializer=tf.truncated_normal_initializer(stddev=0.1)) b = tf.get_variable('b',shape=[CONV2_DEEP],initializer=tf.constant_initializer(0.0)) conv2 = tf.nn.conv2d(pool1, w, strides=[1, 1, 1, 1], padding='SAME') relu2 = tf.nn.relu(tf.nn.bias_add(conv2, b)) with tf.variable_scope('layer4-pool'): # pool2 size is [batch_size,7,7,64] pool2 = tf.nn.max_pool(relu2,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
# 接下来是全连接层,需要将pool2转换为一维向量,作为后面的输入 pool_shape = pool2.get_shape().as_list()#这里通过获取getshape的tensorshape转化为list,注意此时为3维 list,分别为 nodes = pool_shape[1] * pool_shape[2] * pool_shape[3]# 注意 这个shape 大小转化为list后 是 batch height with channel,故1 2 3 这个三个值表示一个nodes大小 reshaped = tf.reshape(pool2,[-1,nodes]) # reshaped = tf.reshape(pool2,[BATCH_SIZE,-1]) # print(reshaped.get_shape()) with tf.variable_scope('layer5-fc1'): fc1_w = tf.get_variable('w',shape=[nodes,FC_SIZE],initializer=tf.truncated_normal_initializer(stddev=0.1)) try: # 只有全连接层的权重需要加入正则化,因为全连接层 计算量和连接超多,需要加入正则,防止过拟合,注意先加入正则化后再使用 #加入正则化后可以使结构化风险更小,l1正则更容易减到0,L2正则化更平滑 if regularizer != None: tf.add_to_collection('loss',regularizer(fc1_w))#tf.add_to_collection 经过正则化后的数据组成列表 tf.get_collection 获取集合列表,tf.add_n 把列表中的东西都依次加起来 except: pass fc1_b = tf.get_variable('b',shape=[FC_SIZE],initializer=tf.constant_initializer(0.1)) #此处没有conv2d 因为 全连接可以利用 矩阵x fc1 = tf.nn.relu(tf.matmul(reshaped,fc1_w) + fc1_b) # 使用Dropout随机将部分节点的输出改为0,为了防止过拟合的现象,从而使模型在测试数据中表现更好。 # dropout一般只会在全连接层使用。 if train: fc1 = tf.nn.dropout(fc1,0.5) with tf.variable_scope('layer6-fc2'): fc2_w = tf.get_variable('w', shape=[FC_SIZE, NUM_LABEL], initializer=tf.truncated_normal_initializer(stddev=0.1)) try: if regularizer != None: tf.add_to_collection('loss', regularizer(fc2_w)) except: pass fc2_b = tf.get_variable('b', shape=[NUM_LABEL], initializer=tf.constant_initializer(0.1)) # 最后一层的输出,不需要加入激活函数 logit = tf.matmul(fc1, fc2_w) + fc2_b return logit