假设,需要为ResNet创建一个自定义层,其中包含一捆准备好的tf.keras
层(例如:Conv2D)。让我们查看以下伪资源代码片段,以更好地理解该问题:
# custom layer
class ScBlock(tensorflow.keras.Layer):
def __init__(self, filters, layer_num, kernel=(3, 3), stride=1):
super(ScBlock, self).__init__(name="block_num{}".format(layer_num))
self.layer_name = 'layer_{}_'.format(layer_num)
self.batch_norm_first = BatchNormalization(name=self.layer_name + 'bn')
self.relu_first = Activation('relu', name=self.layer_name + 'relu')
self.conv_first = Conv2D(filters=filters, kernel_size=kernel, strides=stride, name=self.layer_name + 'conv')
# ...
def call(self, inputs):
res = self.batch_norm_first(inputs)
res = self.relu_first(res)
res = self.conv_first(res)
# ...
return res
# custom layer of blocks
class ResLayer(tensorflow.keras.Layer):
def __init__(self, filters, layer_num, kernel=(3, 3), stride=2):
super(ResLayer, self).__init__(name="res_num{}".format(layer_num))
self.block = ScBlock(filters=filters, layer_num=layer_num, kernel=kernel, stride=stride,)
# ...
def call(self, inputs):
res = self.block(inputs)
# ...
return res
这些自定义图层将在resnet主体中进一步使用:
def resnet(input):
inputs = Input(shape=input)
# ...
res = MaxPool2D((3, 3), strides=2)(res)
# ...
res = ResidualLayer(filters=64, layer_num=1, stride=1)(res)
# ...
resnet_mod = training.Model(inputs, res)
resnet_mod.load_weights('imagenet_1000.h5', by_name=True)
return resnet_mod
如您所见,网络已经过预训练-HDF5中的imagenet权重已加载。在imagenet_1000.h5
中,层的名称等于新ScBlock
中的层名称,例如layer1_conv
-这些名称在新的自定义层之前,现在将其封装。因此,在引入新的自定义ScBlock
和ResLayer
层之后,模型摘要(model.summary()
)仅包含预期的内容,例如res_num_1
。
问题是:HDF5权重加载过程如何?他们是否会自动在新的自定义图层中映射图层(例如:layer1_conv),还是需要以某种方式修改自定义图层才能将这些权重直接加载到封装的图层中(例如:layer1_conv)?如果需要修改自定义图层-正确的方法是什么?
提前谢谢