【https://blog.csdn.net/u013921430 轉載】
slim是一種輕量級的tensorflow庫,可以使模型的構建,訓練,測試都變得更加簡單。在slim庫中對很多常用的函數進行了定義,slim.arg_scope()是slim庫中經常用到的函數之一。函數的定義如下;
-
@tf_contextlib.contextmanager
-
def arg_scope(list_ops_or_scope, **kwargs):
-
"""Stores the default arguments for the given set of list_ops.
-
-
For usage, please see examples at top of the file.
-
-
Args:
-
list_ops_or_scope: List or tuple of operations to set argument scope for or
-
a dictionary containing the current scope. When list_ops_or_scope is a
-
dict, kwargs must be empty. When list_ops_or_scope is a list or tuple,
-
then every op in it need to be decorated with @add_arg_scope to work.
-
**kwargs: keyword=value that will define the defaults for each op in
-
list_ops. All the ops need to accept the given set of arguments.
-
-
Yields:
-
the current_scope, which is a dictionary of {op: {arg: value}}
-
Raises:
-
TypeError: if list_ops is not a list or a tuple.
-
ValueError: if any op in list_ops has not be decorated with @add_arg_scope.
-
"""
-
if isinstance(list_ops_or_scope, dict):
-
# Assumes that list_ops_or_scope is a scope that is being reused.
-
if kwargs:
-
raise ValueError(
'When attempting to re-use a scope by suppling a'
-
'dictionary, kwargs must be empty.')
-
current_scope = list_ops_or_scope.copy()
-
try:
-
_get_arg_stack().append(current_scope)
-
yield current_scope
-
finally:
-
_get_arg_stack().pop()
-
else:
-
# Assumes that list_ops_or_scope is a list/tuple of ops with kwargs.
-
if
not isinstance(list_ops_or_scope, (list, tuple)):
-
raise TypeError(
'list_ops_or_scope must either be a list/tuple or reused'
-
'scope (i.e. dict)')
-
try:
-
current_scope = current_arg_scope().copy()
-
for op
in list_ops_or_scope:
-
key_op = _key_op(op)
-
if
not has_arg_scope(op):
-
raise ValueError(
'%s is not decorated with @add_arg_scope',
-
_name_op(op))
-
if key_op
in current_scope:
-
current_kwargs = current_scope[key_op].copy()
-
current_kwargs.update(kwargs)
-
current_scope[key_op] = current_kwargs
-
else:
-
current_scope[key_op] = kwargs.copy()
-
_get_arg_stack().append(current_scope)
-
yield current_scope
-
finally:
-
_get_arg_stack().pop()
如注釋中所說,這個函數的作用是給list_ops中的內容設置默認值。但是每個list_ops中的每個成員需要用@add_arg_scope修飾才行。所以使用slim.arg_scope()有兩個步驟:
- 使用@slim.add_arg_scope修飾目標函數
- 用 slim.arg_scope()為目標函數設置默認參數.
例如如下代碼;首先用@slim.add_arg_scope修飾目標函數fun1(),然后利用slim.arg_scope()為它設置默認參數。
-
import tensorflow
as tf
-
slim =tf.contrib.slim
-
-
@slim.add_arg_scope
-
def fun1(a=0,b=0):
-
return (a+b)
-
-
with slim.arg_scope([fun1],a=
10):
-
x=fun1(b=
30)
-
print(x)
運行結果為:
40
平常所用到的slim.conv2d( ),slim.fully_connected( ),slim.max_pool2d( )等函數在他被定義的時候就已經添加了@add_arg_scope。以slim.conv2d( )為例;
-
@
add_arg_scope
-
def 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):
所以,在使用過程中可以直接slim.conv2d( )等函數設置默認參數。例如在下面的代碼中,不做單獨聲明的情況下,slim.conv2d, slim.max_pool2d, slim.avg_pool2d三個函數默認的步長都設為1,padding模式都是'VALID'的。但是也可以在調用時進行單獨聲明。這種參數設置方式在構建網絡模型時,尤其是較深的網絡時,可以節省時間。
-
with slim.arg_scope(
-
[slim.conv2d, slim.max_pool2d, slim.avg_pool2d],stride =
1, padding =
'VALID'):
-
net = slim.conv2d(inputs,
32, [
3,
3], stride =
2, scope =
'Conv2d_1a_3x3')
-
net = slim.conv2d(net,
32, [
3,
3], scope =
'Conv2d_2a_3x3')
-
net = slim.conv2d(net,
64, [
3,
3], padding =
'SAME', scope =
'Conv2d_2b_3x3')
@修飾符
其實這種用法是python中常用到的。在python中@修飾符放在函數定義的上方,它將被修飾的函數作為參數,並返回修飾后的同名函數。形式如下;
-
@fun_a #等價於fun_a(fun_b)
-
def fun_b():
這在本質上講跟直接調用被修飾的函數沒什么區別,但是有時候也有用處,例如在調用被修飾函數前需要輸出時間信息,我們可以在@后方的函數中添加輸出時間信息的語句,這樣每次我們只需要調用@后方的函數即可。
-
def funs(fun,factor=20):
-
x=fun()
-
print(factor*x)
-
-
-
@funs #等價funs(add(),fator=20)
-
def add(a=10,b=20):
-
return(a+b)