TensorFlow 层:使用自定义(化)初始化函数?
TensorFlow layers: using custom(ized) initialization function?
为什么使用 partial
获取新的初始化函数会报错,而 lambda
不会?
所有这些功能:
f_init = partial(tf.random_normal, mean=0.0, stddev=0.01, partition_info=None)
f_init = partial(tf.contrib.layers.xavier_initializer, partition_info=None)
f_init = partial(tf.random_normal, mean=0.0, stddev=0.01)
f_init = tf.contrib.layers.xavier_initializer
抛出以下异常:
TypeError: ... got an unexpected keyword argument 'partition_info'
(而 ...
代表 xavier_initializer
和其他功能,当然)
应用于简单的 conv2d
图层时:
conv1 = tf.layers.conv2d(x, 32, [5, 5],
strides=[1, 1],
padding="same",
activation=tf.nn.relu,
kernel_initializer=f_init,
name="conv1")
但是,如果我使用 lambda
来获取自定义初始化函数:
f_init = lambda shape, dtype, partition_info=None:\
tf.random_normal(shape, mean=0.0, stddev=0.01, dtype=dtype)
...它没有任何问题。
不应该 partial
也 return 一个新的匿名函数,例如 tf.random_normal
与 mean=0.0
和 stddev=0.01
一起提供,就像 lambda 语句那样?
错误说函数 tf.random_normal
和 tf.contrib.layers.xavier_initializer
没有名称为 partition_info
的参数,事实确实如此。没有这样的参数(参见here and here)。
你的 lambda 有效,因为它没有将 partition_info
传递给 tf.random_normal
,这是正确的。
还要确保不要与返回初始化值的函数(如 tf.random_normal
)和相应的初始化程序(如 tf.random_normal_initializer
)混淆。第一个 returns 浮动,后者创建一个可调用对象,需要 shape
、dtype
和 partition_info
。调用时,此可调用 returns 正态分布值。
您的 lambda 确实符合此签名,因此可以正常工作。但是,当使用 partial
时,生成的可调用对象的签名只是尚未被调用 partial:
冻结的参数列表
f_init = partial(tf.random_normal, mean=0.0, stddev=0.01)
因为tf.random_normal
有签名:
def random_normal(shape, mean=0.0, stddev=1.0, dtype=dtypes.float32,
seed=None, name=None):
# ...
您可以像这样定义部分一样使用它:
def f_init(shape, dtype=dtypes.float32, seed=None, name=None):
# ...
请注意,没有名为 partition_info
的参数,但 TensorFlow 会在调用 f_init
时尝试传递它,导致出现错误。
要自定义 mean 和 stddev 之类的东西,您不需要创建自定义初始化程序。例如,这会创建一个初始值设定项,即 returns 均值 0.0
和标准差 0.01
:
的正态分布值
f_init = tf.random_normal_initializer(mean=0.0, stddev=0.01)
但是如果你需要一个自定义的初始化器,例如要实现自定义初始化逻辑,您可以遵循以下模式(参见 here):
class RandomNormal(Initializer):
def __init__(self, mean=0.0, stddev=1.0, seed=None, dtype=dtypes.float32):
self.mean = mean
self.stddev = stddev
self.seed = seed
self.dtype = _assert_float_dtype(dtypes.as_dtype(dtype))
def __call__(self, shape, dtype=None, partition_info=None):
if dtype is None:
dtype = self.dtype
normal = random_ops.random_normal(shape, self.mean, self.stddev,
dtype, seed=self.seed)
# do what you want with normal here
return normal
def get_config(self):
return {"mean": self.mean,
"stddev": self.stddev,
"seed": self.seed,
"dtype": self.dtype.name}
# Alias to lower_case, 'function-style' name
random_normal = RandomNormal
为什么使用 partial
获取新的初始化函数会报错,而 lambda
不会?
所有这些功能:
f_init = partial(tf.random_normal, mean=0.0, stddev=0.01, partition_info=None)
f_init = partial(tf.contrib.layers.xavier_initializer, partition_info=None)
f_init = partial(tf.random_normal, mean=0.0, stddev=0.01)
f_init = tf.contrib.layers.xavier_initializer
抛出以下异常:
TypeError: ... got an unexpected keyword argument 'partition_info'
(而 ...
代表 xavier_initializer
和其他功能,当然)
应用于简单的 conv2d
图层时:
conv1 = tf.layers.conv2d(x, 32, [5, 5],
strides=[1, 1],
padding="same",
activation=tf.nn.relu,
kernel_initializer=f_init,
name="conv1")
但是,如果我使用 lambda
来获取自定义初始化函数:
f_init = lambda shape, dtype, partition_info=None:\
tf.random_normal(shape, mean=0.0, stddev=0.01, dtype=dtype)
...它没有任何问题。
不应该 partial
也 return 一个新的匿名函数,例如 tf.random_normal
与 mean=0.0
和 stddev=0.01
一起提供,就像 lambda 语句那样?
错误说函数 tf.random_normal
和 tf.contrib.layers.xavier_initializer
没有名称为 partition_info
的参数,事实确实如此。没有这样的参数(参见here and here)。
你的 lambda 有效,因为它没有将 partition_info
传递给 tf.random_normal
,这是正确的。
还要确保不要与返回初始化值的函数(如 tf.random_normal
)和相应的初始化程序(如 tf.random_normal_initializer
)混淆。第一个 returns 浮动,后者创建一个可调用对象,需要 shape
、dtype
和 partition_info
。调用时,此可调用 returns 正态分布值。
您的 lambda 确实符合此签名,因此可以正常工作。但是,当使用 partial
时,生成的可调用对象的签名只是尚未被调用 partial:
f_init = partial(tf.random_normal, mean=0.0, stddev=0.01)
因为tf.random_normal
有签名:
def random_normal(shape, mean=0.0, stddev=1.0, dtype=dtypes.float32,
seed=None, name=None):
# ...
您可以像这样定义部分一样使用它:
def f_init(shape, dtype=dtypes.float32, seed=None, name=None):
# ...
请注意,没有名为 partition_info
的参数,但 TensorFlow 会在调用 f_init
时尝试传递它,导致出现错误。
要自定义 mean 和 stddev 之类的东西,您不需要创建自定义初始化程序。例如,这会创建一个初始值设定项,即 returns 均值 0.0
和标准差 0.01
:
f_init = tf.random_normal_initializer(mean=0.0, stddev=0.01)
但是如果你需要一个自定义的初始化器,例如要实现自定义初始化逻辑,您可以遵循以下模式(参见 here):
class RandomNormal(Initializer):
def __init__(self, mean=0.0, stddev=1.0, seed=None, dtype=dtypes.float32):
self.mean = mean
self.stddev = stddev
self.seed = seed
self.dtype = _assert_float_dtype(dtypes.as_dtype(dtype))
def __call__(self, shape, dtype=None, partition_info=None):
if dtype is None:
dtype = self.dtype
normal = random_ops.random_normal(shape, self.mean, self.stddev,
dtype, seed=self.seed)
# do what you want with normal here
return normal
def get_config(self):
return {"mean": self.mean,
"stddev": self.stddev,
"seed": self.seed,
"dtype": self.dtype.name}
# Alias to lower_case, 'function-style' name
random_normal = RandomNormal