https://blog.csdn.net/Cyiano/article/details/75006883python
https://blog.csdn.net/transMaple/article/details/78273560git
slim庫是tensorflow中的一個高層封裝,它將原來不少tf中複雜的函數進一步封裝,省去了不少重複的參數,以及平時不會考慮到的參數。能夠理解爲tensorflow的升級版。網絡
import tensorflow as tf import tensorflow.contrib.slim as slim
參數:ide
# 全部的參數以下 @add_arg_scope def convolution2d_in_plane( inputs, kernel_size, stride=1, padding='SAME', activation_fn=nn.relu, normalizer_fn=None, normalizer_params=None, weights_initializer=initializers.xavier_initializer(), weights_regularizer=None, biases_initializer=init_ops.zeros_initializer(), biases_regularizer=None, reuse=None, variables_collections=None, outputs_collections=None, trainable=True, scope=None):
input = ... net = slim.conv2d(input, 128, [3, 3], scope='conv1_1') net = slim.max_pool2d(net, kernel_size=[2,2], stride=2, scope='pool1') # 通常爲 (inputs=?, kernel_size=?, stride=?, padding=?, ....) net = slim.repeat(net, 3, slim.conv2d, 256, [3, 3], scope='conv3') # repeat操做即爲重複建立某個layer
slim.conv2d是基於tf.conv2d的進一步封裝,省去了不少參數,通常調用方法以下:函數
net = slim.conv2d(inputs, 256, [3, 3], stride=1, scope='conv1_1')
前三個參數依次爲網絡的輸入,輸出的通道,卷積核大小,stride是作卷積時的步長。除此以外,還有幾個常常被用到的參數:測試
padding : 補零的方式,例如'SAME'
activation_fn : 激活函數,默認是nn.relu
normalizer_fn : 正則化函數,默認爲None,這裏能夠設置爲batch normalization,函數用slim.batch_norm
normalizer_params : slim.batch_norm中的參數,以字典形式表示
weights_initializer : 權重的初始化器,initializers.xavier_initializer()
weights_regularizer : 權重的正則化器,通常不怎麼用到
biases_initializer : 若是以前有batch norm,那麼這個及下面一個就不用管了
biases_regularizer :
trainable : 參數是否可訓練,默認爲Truespa
這個函數更簡單了,用法以下:.net
net = slim.max_pool2d(net, [2, 2], scope='pool1')
slim.fully_connected(x, 128, scope='fc1')
slim.arg_scope能夠定義一些函數的默認參數值,在scope內,咱們重複用到這些函數時能夠不用把全部參數都寫一遍。3d
with slim.arg_scope([slim.conv2d, slim.fully_connected], trainable=True, activation_fn=tf.nn.relu, weights_initializer=tf.truncated_normal_initializer(stddev=0.01), weights_regularizer=slim.l2_regularizer(0.0001)): with slim.arg_scope([slim.conv2d], kernel_size=[3, 3], padding='SAME', normalizer_fn=slim.batch_norm): net = slim.conv2d(net, 64, scope='conv1')) net = slim.conv2d(net, 128, scope='conv2')) net = slim.conv2d(net, 256, [5, 5], scope='conv3'))
接下來講我在用slim.batch_norm時踩到的坑。slim.batch_norm裏有moving_mean和moving_variance兩個量,分別表示每一個批次的均值和方差。在訓練時還好理解,但在測試時,moving_mean和moving_variance的含義變了。在訓練時,有一些語句是必不可少的:code
# 定義佔位符,X表示網絡的輸入,Y表示真實值label X = tf.placeholder("float", [None, 224, 224, 3]) Y = tf.placeholder("float", [None, 100]) #調用含batch_norm的resnet網絡,其中記得is_training=True logits = model.resnet(X, 100, is_training=True) cross_entropy = -tf.reduce_sum(Y*tf.log(logits)) #訓練的op必定要用slim的slim.learning.create_train_op,只用tf.train.MomentumOptimizer.minimize()是不行的 opt = tf.train.MomentumOptimizer(lr_rate, 0.9) train_op = slim.learning.create_train_op(cross_entropy, opt, global_step=global_step) #更新操做,具體含義不是很明白,直接套用便可 update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS) if update_ops: updates = tf.group(*update_ops) cross_entropy = control_flow_ops.with_dependencies([updates], cross_entropy)
以後的訓練都和往常同樣了,導出模型後,在測試階段調用相同的網絡,參數is_training必定要設置成False。
logits = model.resnet(X, 100, is_training=False)
不然,可能會出現這種狀況:全部的單個圖像分類,最後幾乎全被歸爲同一類。這可能就是訓練模式設置反了的問題。