用于模型创建的 Tensorflow 子类化中层的可重用性

问题描述 投票:0回答:1

所以我目前正在学习如何使用子类化在 Tensorflow 中创建模型。根据教程,以下代码片段应该可以完美运行:

#Defining the class
class FeatureExtractor(Layer):
    def __init__(self):
        super().__init__()

        self.conv_1 = Conv2D(filters = 6, kernel_size = 4, padding = "valid", activation = "relu")
        self.batchnorm_1 = BatchNormalization()
        self.maxpool_1 = MaxPool2D(pool_size = 2, strides=2)

        self.conv_2 = Conv2D(filters = 16, kernel_size = 4, padding = "valid", activation = "relu")
        self.batchnorm_2 = BatchNormalization()
        self.maxpool_2 = MaxPool2D(pool_size = 2, strides=2)


    def call(self, x):
        x = self.conv_1(x)
        x = self.batchnorm_1(x)
        x = self.maxpool_1(x)

        x = self.conv_2(x)
        x = self.batchnorm_2(x)
        x = self.maxpool_2(x)

        return x

#Calling and using the class
feature_extractor = FeatureExtractor()

func_input = Input(shape=(IMG_SIZE, IMG_SIZE, 3), name="Input_Image")

x = feature_extractor(func_input)

它确实运行完美。但后来我意识到,在

__init__()
中,
BatchNormalization()
MaxPool2D()
看起来相同,但被定义了两次而不是被重用,所以我做了一些研究并在 Stackoverflow 上询问,并得出结论: 当层在
call()
中被调用,它们会适应输入的维度,然后保留该维度以供以后调用
,这会阻止这些层被重用。

但正如 Fynn 在我的上一个问题中指出的那样,

maxpool
成员实际上可以重用,而
batchnorm
则不能。那么有些层适应输入的维度(如
batchnorm
)而有些则不适应(如
maxpool
)?或者这些层的属性是否会导致这种行为? (我可以在文档中查找)

python tensorflow oop tf.keras
1个回答
0
投票

一般来说,某些层具有参数,并且这些参数不能重复使用,除了在某些边缘情况下,但它们可能不应该。在这个具体示例中,批量归一化具有可学习的

beta
gamma
参数,以及用于推理的不可训练参数(如果这对您来说没有任何意义,我建议您查看批量归一化如何在详细)。

现在,一个图层对象只有一组参数,如果您要重复使用该对象,相同的参数将应用于多个位置。考虑一下:

self.conv_1 = Conv2D(filters = 6, kernel_size = 4, padding = "valid", activation = "relu")
self.batchnorm = BatchNormalization()
self.maxpool_1 = MaxPool2D(pool_size = 2, strides=2)

self.conv_2 = Conv2D(filters = 16, kernel_size = 4, padding = "valid", activation = "relu")
self.maxpool_2 = MaxPool2D(pool_size = 2, strides=2)

并假设

batchnorm
将在both卷积之后使用。在此示例中,
batchnorm
将被构建为具有 6 个 beta/gamma,因为这是第一层中的滤波器数量;尝试将其重新用于第二层是行不通的,因为第二层有 16 个过滤器,需要 16 个 beta/gamma。这就是为什么只创建一个批归一化层不起作用的原因。

以下内容应该实际运行:

self.conv_1 = Conv2D(filters = 16, kernel_size = 4, padding = "valid", activation = "relu")
self.batchnorm = BatchNormalization()
self.maxpool_1 = MaxPool2D(pool_size = 2, strides=2)

self.conv_2 = Conv2D(filters = 16, kernel_size = 4, padding = "valid", activation = "relu")
self.maxpool_2 = MaxPool2D(pool_size = 2, strides=2)

我对其进行了更改,使两个卷积都使用 16 个滤波器。然而,这会在两层之后重新使用相同的beta/gamma(因为我们使用相同的batchnorm对象),这可能是一个坏主意。

对于 maxpool 来说,这不是问题,因为它没有任何参数。对于任何输入,具有相同窗口大小和步长的池化效果都是相同的。

© www.soinside.com 2019 - 2024. All rights reserved.