我想使用tf.keras
'功能性API构建模型。我的模型很大,因此我想通过继承tf.keras.layers.Layer
来创建自定义图层。以下是我受TensorFlow's documentation启发的尝试。
import tensorflow as tf
class Conv2D(tf.keras.layers.Layer):
def __init__(self):
super().__init__()
input_layer = tf.keras.layers.Input(
shape=(256, 256, 3)
)
self.conv = tf.keras.layers.Conv2D(
filters=16,
kernel_size=3,
strides=(1, 1),
padding="same"
)(input_layer)
def call(self, inputs):
return self.conv(inputs)
outer_input_layer = tf.keras.layers.Input(
shape=(256, 256, 3)
)
x = Conv2D()(outer_input_layer)
此代码因以下错误而崩溃。
Traceback (most recent call last):
File "c:\Users\user\.vscode\extensions\ms-python.python-2020.2.64397\pythonFiles\ptvsd_launcher.py", line 48, in <module>
main(ptvsdArgs)
File "c:\Users\user\.vscode\extensions\ms-python.python-2020.2.64397\pythonFiles\lib\python\old_ptvsd\ptvsd\__main__.py", line 432, in main
run()
File "c:\Users\user\.vscode\extensions\ms-python.python-2020.2.64397\pythonFiles\lib\python\old_ptvsd\ptvsd\__main__.py", line 316, in run_file
runpy.run_path(target, run_name='__main__')
File "C:\Users\user\code\.env\lib\runpy.py", line 263, in run_path
pkg_name=pkg_name, script_name=fname)
File "C:\Users\user\code\.env\lib\runpy.py", line 96, in _run_module_code
mod_name, mod_spec, pkg_name, script_name)
File "C:\Users\user\code\.env\lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
File "c:\Users\user\code\tests.py", line 23, in <module>
x = Conv2D()(outer_input_layer)
File "C:\Users\user\code\.env\lib\site-packages\tensorflow_core\python\keras\engine\base_layer.py", line 773, in __call__
outputs = call_fn(cast_inputs, *args, **kwargs)
File "C:\Users\user\code\.env\lib\site-packages\tensorflow_core\python\autograph\impl\api.py", line 237, in wrapper
raise e.ag_error_metadata.to_exception(e)
TypeError: in converted code:
c:\Users\user\code\tests.py:18 call *
return self.conv(inputs)
C:\Users\user\code\.env\lib\site-packages\tensorflow_core\python\autograph\impl\api.py:447 converted_call
f in m.__dict__.values() for m in (collections, pdb, copy, inspect, re)):
C:\Users\user\code\.env\lib\site-packages\tensorflow_core\python\autograph\impl\api.py:447 <genexpr>
f in m.__dict__.values() for m in (collections, pdb, copy, inspect, re)):
C:\Users\user\code\.env\lib\site-packages\tensorflow_core\python\ops\math_ops.py:1351 tensor_equals
return gen_math_ops.equal(self, other, incompatible_shape_error=False)
C:\Users\user\code\.env\lib\site-packages\tensorflow_core\python\ops\gen_math_ops.py:3240 equal
name=name)
C:\Users\user\code\.env\lib\site-packages\tensorflow_core\python\framework\op_def_library.py:477 _apply_op_helper
repr(values), type(values).__name__, err))
TypeError: Expected float32 passed to parameter 'y' of op 'Equal', got 'collections' of type 'str' instead. Error: Expected float32, got 'collections'
of type 'str' instead.
我的方法有什么问题?
答案 0 :(得分:1)
自定义层没有“输入”层。那没有多大意义。输入是调用时传递给图层的内容。
所以:
import tensorflow as tf
class ConvBN(tf.keras.layers.Layer):
def __init__(self, activation, name):
super().__init__()
#here you just "store" the layers, you don't use them
#you also store any other property you find necessary for the call
self.conv = tf.keras.layers.Conv2D(
filters=16,
kernel_size=3,
strides=(1, 1),
padding="same",
name = name+'_conv'
)
self.bn = tf.keras.layers.BatchNormalization(name = name + "_bn")
self.activation = tf.keras.layers.Activation(activation, name = name + "_act")
def call(self, inputs):
#here you "use" the layers with the given input to produce an output
out = self.conv(inputs)
out = self.bn(out)
out = self.activation(out)
return out
如果您不打算多次使用“同一层”,也可以创建更简单的对象:
def convGroup(input_tensor, activation, name):
out = tf.keras.layers.Conv2D(
filters=16,
kernel_size=3,
strides=(1, 1),
padding="same",
name = name+'_conv'
)(input_tensor)
out = tf.keras.layers.BatchNormalization(name = name + "_bn")(out)
out = tf.keras.layers.Activation(activation, name = name + "_act")(out)
return out