1. 程式人生 > >『TensorFlow』slim模組常用API

『TensorFlow』slim模組常用API

 

 

輔助函式

slim.arg_scope()

slim.arg_scope可以定義一些函式的預設引數值,在scope內,我們重複用到這些函式時可以不用把所有引數都寫一遍,注意它沒有tf.variable_scope()劃分圖結構的功能,

?

1

2

3

4

5

6

7

8

9

10

11

12

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.arg_scope的用法基本都體現在上面了。一個slim.arg_scope內可以用list來同時定義多個函式的預設引數(前提是這些函式都有這些引數),另外,slim.arg_scope也允許相互巢狀。在其中呼叫的函式,可以不用重複寫一些引數(例如kernel_size=[3, 3]),但也允許覆蓋(例如最後一行,卷積核大小為[5,5])。
另外,還可以把這麼多scope封裝成函式:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

def new_arg_sc():

    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) as sc:

            return sc

 

def main():

    ......

    with slim.arg_scope(new_arg_sc()):

        ......

 

slim.utils.collect_named_outputs()

將變數取個別名,並收集到collection中

?

1

net = slim.utils.collect_named_outputs(outputs_collections,sc.name,net)

 引數意義如下,

return:這個方法會返回本次新增的tensor物件,
引數二:意義是為tensor新增一個別名,並收集進collections中
檢視原始碼可見實現如下

if collections:
    append_tensor_alias(outputs,alias)
    ops.add_to_collections(collections,outputs)
return outputs

據說本方法位置已經被轉移到這裡了,
from tensorflow.contrib.layers.python.layers import utils
utils.collect_named_outputs()

slim.utils.convert_collection_to_dict()

?

1

2

3

4

5

6

#集合轉換為字典,{節點名:輸出張量值}

end_points = slim.utils.convert_collection_to_dict(end_points_collection)

  

# 收集 & 釋放 集合值

tf.add_to_collection("loss",mse_loss)

tf.add_n(tf.get_collection("loss"))

 

回到頂部

層函式

batch_norm處理

slim.batch_norm()函式,以及slim的各個層函式的normalizer_fn=slim.batch_norm呼叫都會用到,

其引數很多,需要以字典的形式傳入,

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

batch_norm_params = # 定義batch normalization(標準化)的引數字典

        'is_training': is_training,

        # 是否是在訓練模式,如果是在訓練階段,將會使用指數衰減函式(衰減係數為指定的decay),

        # 對moving_mean和moving_variance進行統計特性的動量更新,也就是進行使用指數衰減函式對均值和方

        # 差進行更新,而如果是在測試階段,均值和方差就是固定不變的,是在訓練階段就求好的,在訓練階段,

        # 每個批的均值和方差的更新是加上了一個指數衰減函式,而最後求得的整個訓練樣本的均值和方差就是所

        # 有批的均值的均值,和所有批的方差的無偏估計

 

        'zero_debias_moving_mean': True,

        # 如果為True,將會建立一個新的變數對 'moving_mean/biased' and 'moving_mean/local_step',

        # 預設設定為False,將其設為True可以增加穩定性

 

        'decay': batch_norm_decay,             # Decay for the moving averages.

        # 該引數能夠衡量使用指數衰減函式更新均值方差時,更新的速度,取值通常在0.999-0.99-0.9之間,值

        # 越小,代表更新速度越快,而值太大的話,有可能會導致均值方差更新太慢,而最後變成一個常量1,而

        # 這個值會導致模型效能較低很多.另外,如果出現過擬合時,也可以考慮增加均值和方差的更新速度,也

        # 就是減小decay

 

        'epsilon': batch_norm_epsilon,         # 就是在歸一化時,除以方差時,防止方差為0而加上的一個數

        'scale': batch_norm_scale,

        'updates_collections': tf.GraphKeys.UPDATE_OPS,    

        # force in-place updates of mean and variance estimates

        # 該引數有一個預設值,ops.GraphKeys.UPDATE_OPS,當取預設值時,slim會在當前批訓練完成後再更新均

        # 值和方差,這樣會存在一個問題,就是當前批資料使用的均值和方差總是慢一拍,最後導致訓練出來的模

        # 型效能較差。所以,一般需要將該值設為None,這樣slim進行批處理時,會對均值和方差進行即時更新,

        # 批處理使用的就是最新的均值和方差。

        #

        # 另外,不論是即使更新還是一步訓練後再對所有均值方差一起更新,對測試資料是沒有影響的,即測試數

        # 據使用的都是儲存的模型中的均值方差資料,但是如果你在訓練中需要測試,而忘了將is_training這個值

        # 改成false,那麼這批測試資料將會綜合當前批資料的均值方差和訓練資料的均值方差。而這樣做應該是不

        # 正確的。

    }

在以其他層引數的形式呼叫時如下,

?

1

2

normalizer_fn=slim.batch_norm,                               # 標準化器設定為BN

normalizer_params=batch_norm_params

注意一但使用batch_norm層,在訓練節點定義時需要新增一些語句,slim.batch_norm裡有moving_mean和moving_variance兩個量,分別表示每個批次的均值和方差。在訓練時還好理解,但在測試時,moving_mean和moving_variance的含義變了,在訓練時,

?

1

2

3

4

5

update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS) 

    with tf.control_dependencies(update_ops): 

        train_step = tf.train.GradientDescentOptimizer(0.01).minimize(total_loss) 

# 注意並tf本體的batch_normal操作也需要這步操作

# 其中,tf.control_dependencies(update_ops)表示with段中的操作是在update_ops操作執行之後 再執行的

tf.contrib.slim.conv2d()

convolution(inputs,
          num_outputs,
          kernel_size,
          stride=1,
          padding='SAME',
          data_format=None,
          rate=1,
          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)

inputs                        是指需要做卷積的輸入影象
num_outputs             指定卷積核的個數(就是filter的個數)
kernel_size               用於指定卷積核的維度(卷積核的寬度,卷積核的高度)
stride                         為卷積時在影象每一維的步長
padding                     為padding的方式選擇,VALID或者SAME
data_format              是用於指定輸入的input的格式
rate                           這個引數不是太理解,而且tf.nn.conv2d中也沒有,對於使用atrous convolution的膨脹率(不是太懂這個atrous convolution)
activation_fn             用於啟用函式的指定,預設的為ReLU函式
normalizer_fn           用於指定正則化函式
normalizer_params  用於指定正則化函式的引數
weights_initializer     用於指定權重的初始化程式
weights_regularizer  為權重可選的正則化程式
biases_initializer       用於指定biase的初始化程式
biases_regularizer    biases可選的正則化程式
reuse                        指定是否共享層或者和變數
variable_collections  指定所有變數的集合列表或者字典
outputs_collections   指定輸出被新增的集合
trainable                    卷積層的引數是否可被訓練
scope                        共享變數所指的variable_scope

slim.conv2d是基於tf.conv2d的進一步封裝,省去了很多引數,一般呼叫方法如下:

?

1

net = slim.conv2d(inputs, 256, [3, 3], stride=1, scope='conv1_1')

slim.max_pool2d

這個函式更簡單了,用法如下:

?

1

net = slim.max_pool2d(net, [2, 2], scope='pool1')<a name="t4" target="_blank"></a>

slim.fully_connected

?

1

slim.fully_connected(x, 128, scope='fc1')

前兩個引數分別為網路輸入、輸出的神經元數量。