我正在尝试使用keras 模型子类重写a 函数模型,但是在新的模型子类中,摘要生成不起作用。
供参考,这是函数模型及其输出。
filters = 32
# placeholder for inputs
inputs = Input(shape=[16, 16, 16, 12])
# L-hand side of UNet
conv1 = DoubleConv3D(filters*1)(inputs)
pool1 = MaxPooling3D()(conv1)
...
# middle bottleneck
conv5 = DoubleConv3D(filters*5)(pool4)
# R-hand side of UNet
rsdc6 = ConcatConv3D(filters*4)(conv5, conv4)
conv6 = DoubleConv3D(filters*4)(rsdc6)
...
# sigmoid activation
outputs = Conv3D(1, (1, 1, 1), activation='sigmoid')(conv9)
model = Model(inputs=[inputs], outputs=[outputs])
model.summary()
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_29 (InputLayer) (None, 16, 16, 16, 1 0
__________________________________________________________________________________________________
conv3d_111 (Conv3D) (None, 16, 16, 16, 3 10400 input_29[0][0]
__________________________________________________________________________________________________
...
和模型子类看起来像:
class UNet3D(Model):
def __init__(self, **kwargs):
super(UNet3D, self).__init__(name="UNet3D", **kwargs)
self.filters = 32
def __call__(self, inputs):
# L-hand side of UNet
conv1 = DoubleConv3D(self.filters*1)(inputs)
pool1 = MaxPooling3D()(conv1)
...
# middle bottleneck
conv5 = DoubleConv3D(self.filters*5)(pool4)
# R-hand side of UNet
rsdc6 = ConcatConv3D(self.filters*4)(conv5, conv4)
conv6 = DoubleConv3D(self.filters*4)(rsdc6)
...
# sigmoid activation
outputs = Conv3D(1, (1, 1, 1), activation='sigmoid')(conv9)
return outputs
unet3d = UNet3D()
unet3d.build(Input(shape=[None, None, None, 1]))
unet3d.summary()
但是,摘要给出了
,而不是输出参数的层和数量_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
Total params: 0
Trainable params: 0
Non-trainable params: 0
_________________________________________________________________
最初,我认为这是一个错误,在调用摘要之前未调用build
,并尝试在第一个卷积层之前明确调用该功能并在第一个卷积层之前添加InputLayer
,如此相关答案所述。但是,这两个解决方案都没有帮助修复模型子类上的摘要生成。
我通过查看以下示例找到了该模型子分类问题的解决方案。信用应交给该仓库的作者。
创建将keras功能转换为模型子类的一种方法是创建并调用一个复制模型初始化的函数,例如Model(inputs=[inputs], outputs=[outputs])
。在这里,我们使用_build
函数来做到这一点。
class UNet3D(Model):
def __init__(self, **kwargs):
# Initialize model parameters.
self.filters = 32
...
# Initialize model.
self._build(**kwargs)
def __call__(self, inputs):
# L-hand side of UNet
conv1 = DoubleConv3D(self.filters*1)(inputs)
pool1 = MaxPooling3D()(conv1)
...
# middle bottleneck
conv5 = DoubleConv3D(self.filters*5)(pool4)
# R-hand side of UNet
rsdc6 = ConcatConv3D(self.filters*4)(conv5, conv4)
conv6 = DoubleConv3D(self.filters*4)(rsdc6)
...
# sigmoid activation
outputs = Conv3D(1, (1, 1, 1), activation='sigmoid')(conv9)
return outputs
def _build(self, **kwargs):
"""
Replicates Model(inputs=[inputs], outputs=[outputs]) of functional model.
"""
# Replace with shape=[None, None, None, 1] if input_shape is unknown.
inputs = Input(shape=[16, 16, 16, 12])
outputs = self.__call__(inputs)
super(UNet3D, self).__init__(name="UNet3D", inputs=inputs, outputs=outputs, **kwargs)
unet3d = UNet3D()
unet3d.summary()