Separable 卷积层的 layer.get_weights() 是什么意思?
What does layer.get_weights() of a Separable convolutional layer means?
我了解到我们可以使用函数layer.get_weights()
来获取层的权重和偏差。这将 return 一个长度为 2 的列表。层的权重存储在 layer.get_weights()[0]
中,偏差存储在 layer.get_weights()[1]
中(如果在层定义期间未禁用偏差) .对于普通的卷积层也是如此。
我最近在 EfficientDet model
中使用 Separable 卷积层作为我的层之一。
layers.SeparableConv2D(num_channels, kernel_size=kernel_size, strides=strides, padding='same',
use_bias=True, name=str(name)+"/conv")
当我尝试使用相同的 layer.get_weights()
函数时,它 return 给我一个 length 3
的列表,我期望它是 2
是相同的如上所述。
在这里,我对列表中的三个值是什么感到有点困惑。
任何帮助和建议将不胜感激。
SeparableConv2D
层正在计算深度可分离卷积,与普通卷积不同,它需要 2 个内核(2 个权重张量)。无需过多赘述,它使用第一个内核计算深度卷积,应用此操作后,它使用第二个内核计算点向卷积。这背后的主要思想是减少参数的数量,从而减少计算的数量。
这是一个简单的例子。假设我们有 28x28x3(宽度、高度、#channels)的输入图像并且我们应用普通的 2D 卷积(假设 16 个过滤器和 5x5 内核,没有 stride/padding)。
如果我们进行计算,那么我们最终得到 5x5x3x16(5x5 滤波器大小,3 个输入通道和 16 个滤波器)= 1200 个内核参数 + 16 个偏置参数(每个滤波器一个)= 1216。我们可以验证这一点
model = tf.keras.models.Sequential([
tf.keras.layers.Input(shape=(28, 28, 3)),
tf.keras.layers.Conv2D(16, (5, 5)),
])
model.summary()
给我们
Layer (type) Output Shape Param #
=================================================================
conv2d_4 (Conv2D) (None, 24, 24, 16) 1216
如果我们提取内核参数。
print(model.layers[0].get_weights()[0].shape)
这给了我们
(5, 5, 3, 16)
现在,让我们考虑具有 2 个内核的可分离 2D 卷积,深度内核由每个输入通道的单独 5x5x1 权重矩阵组成,在我们的例子中是 5x5x3(5x5x3x1 - 与 4D keras 张量一致)。这给了我们 75 个参数。
逐点内核是一个简单的 1x1 卷积(它对每个输入点进行操作),用于将结果的深度增加到指定过滤器的数量。在我们的例子中 - 1x1x3x16,它给了我们 48 个参数。
总的来说,第一个内核有 75 个参数,第二个内核有 48 个参数,这给了我们 123 个参数加上 16 个偏置参数。即139个参数。
在喀拉斯,
model = tf.keras.models.Sequential([
tf.keras.layers.Input(shape=(28, 28, 3)),
tf.keras.layers.SeparableConv2D(16, (5, 5)),
])
model.summary()
给我们
Layer (type) Output Shape Param #
=================================================================
separable_conv2d_7 (Separabl (None, 24, 24, 16) 139
正如我们所见,该层的输出形状与普通卷积层的输出形状完全相同,但现在我们有 2 个参数更少的内核。同样,我们可以提取这两个内核的参数,
print(model.layers[0].get_weights()[0].shape)
print(model.layers[0].get_weights()[1].shape)
这给了我们
(5, 5, 3, 1)
(1, 1, 3, 16)
如果您想了解有关可分离卷积如何工作的更多详细信息,可以阅读 this article。
我了解到我们可以使用函数layer.get_weights()
来获取层的权重和偏差。这将 return 一个长度为 2 的列表。层的权重存储在 layer.get_weights()[0]
中,偏差存储在 layer.get_weights()[1]
中(如果在层定义期间未禁用偏差) .对于普通的卷积层也是如此。
我最近在 EfficientDet model
中使用 Separable 卷积层作为我的层之一。
layers.SeparableConv2D(num_channels, kernel_size=kernel_size, strides=strides, padding='same',
use_bias=True, name=str(name)+"/conv")
当我尝试使用相同的 layer.get_weights()
函数时,它 return 给我一个 length 3
的列表,我期望它是 2
是相同的如上所述。
在这里,我对列表中的三个值是什么感到有点困惑。
任何帮助和建议将不胜感激。
SeparableConv2D
层正在计算深度可分离卷积,与普通卷积不同,它需要 2 个内核(2 个权重张量)。无需过多赘述,它使用第一个内核计算深度卷积,应用此操作后,它使用第二个内核计算点向卷积。这背后的主要思想是减少参数的数量,从而减少计算的数量。
这是一个简单的例子。假设我们有 28x28x3(宽度、高度、#channels)的输入图像并且我们应用普通的 2D 卷积(假设 16 个过滤器和 5x5 内核,没有 stride/padding)。
如果我们进行计算,那么我们最终得到 5x5x3x16(5x5 滤波器大小,3 个输入通道和 16 个滤波器)= 1200 个内核参数 + 16 个偏置参数(每个滤波器一个)= 1216。我们可以验证这一点
model = tf.keras.models.Sequential([
tf.keras.layers.Input(shape=(28, 28, 3)),
tf.keras.layers.Conv2D(16, (5, 5)),
])
model.summary()
给我们
Layer (type) Output Shape Param #
=================================================================
conv2d_4 (Conv2D) (None, 24, 24, 16) 1216
如果我们提取内核参数。
print(model.layers[0].get_weights()[0].shape)
这给了我们
(5, 5, 3, 16)
现在,让我们考虑具有 2 个内核的可分离 2D 卷积,深度内核由每个输入通道的单独 5x5x1 权重矩阵组成,在我们的例子中是 5x5x3(5x5x3x1 - 与 4D keras 张量一致)。这给了我们 75 个参数。
逐点内核是一个简单的 1x1 卷积(它对每个输入点进行操作),用于将结果的深度增加到指定过滤器的数量。在我们的例子中 - 1x1x3x16,它给了我们 48 个参数。
总的来说,第一个内核有 75 个参数,第二个内核有 48 个参数,这给了我们 123 个参数加上 16 个偏置参数。即139个参数。
在喀拉斯,
model = tf.keras.models.Sequential([
tf.keras.layers.Input(shape=(28, 28, 3)),
tf.keras.layers.SeparableConv2D(16, (5, 5)),
])
model.summary()
给我们
Layer (type) Output Shape Param #
=================================================================
separable_conv2d_7 (Separabl (None, 24, 24, 16) 139
正如我们所见,该层的输出形状与普通卷积层的输出形状完全相同,但现在我们有 2 个参数更少的内核。同样,我们可以提取这两个内核的参数,
print(model.layers[0].get_weights()[0].shape)
print(model.layers[0].get_weights()[1].shape)
这给了我们
(5, 5, 3, 1)
(1, 1, 3, 16)
如果您想了解有关可分离卷积如何工作的更多详细信息,可以阅读 this article。