如何解释 CNN 中的 model.summary() 输出?

Posted

技术标签:

【中文标题】如何解释 CNN 中的 model.summary() 输出?【英文标题】:How to interpret model.summary() output in CNN? 【发布时间】:2020-07-18 12:09:21 【问题描述】:

我是深度学习和 CNN 的新手。如果已经创建了一个 CNN,如屏幕截图所示,那么如何解释 model.summary() 描述的输出。我无法理解不同层的输出形状。

模型总结:

Model: "sequential_3"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_14 (Conv2D)           (None, 29, 29, 32)        1568      
_________________________________________________________________
max_pooling2d_6 (MaxPooling2 (None, 14, 14, 32)        0         
_________________________________________________________________
conv2d_15 (Conv2D)           (None, 11, 11, 32)        16416     
_________________________________________________________________
max_pooling2d_7 (MaxPooling2 (None, 5, 5, 32)          0         
_________________________________________________________________
flatten_3 (Flatten)          (None, 800)               0         
_________________________________________________________________
dense_6 (Dense)              (None, 32)                25632     
_________________________________________________________________
dense_7 (Dense)              (None, 10)                330       
=================================================================
Total params: 43,946
Trainable params: 43,946
Non-trainable params: 0

【问题讨论】:

【参考方案1】:

假设每个图像的大小为(32, 32, 3),根据问题。

Keras 然后附加一个额外的维度来处理多个批次,即在单个 epoch 的每个步骤中训练多个图像。由于批量大小可以变化,其大小由无表示。因此,输入形状变为(None, 32, 32, 3)

(32, 32) 图像与(4, 4) 过滤器进行卷积,步幅和膨胀率为1,并使用“有效”填充,得到大小为(32 - 4 + 1, 32 - 4 + 1) = (29, 29) 的输出。由于您有 32 个这样的过滤器,因此输出形状变为 (29, 29, 32)

默认 MaxPooling 内核的形状为 (2, 2),步幅为 (2, 2)。将其应用于(29, 29) 图像会生成形状为(((29 - 2)//2) + 1, ((29 - 2)//2) + 1)) = (14, 14) 的图像。

这种模式可以扩展到所有 Conv2D 和 MaxPooling 层。

Flatten 层沿所有通道获取所有像素并创建一维向量(不考虑批量大小)。因此,(5, 5, 32) 的输入被展平为(5 * 5 * 32) = 800 值。

参数计数

Conv2D 层的参数数量由下式给出:

(kernel_height * kernel_width * input_channels * output_channels) + (output_channels 如果使用偏差)。

所以,对于第一个具有 3 个输入通道、32 个输出通道和内核大小为(4, 4) 的 Conv2D 层,参数数量为(4 * 4 * 3 * 32) + 32 = 1568

【讨论】:

这意味着如果padding被明确定义为“相同”,那么第一个卷积层的输出将是(32,32,32)? 是的,它的形状是(32, 32, 32)【参考方案2】:

你的第一层是一个卷积,它采用未知的输入形状(你知道它,你用input_shape=....在某个地方定义了它。

第一个卷积有一个形状为(None, 29, 29, 32)的输出,其中:

None 是批量大小 29 和 29 是生成图像的大小 32 是这个卷积的滤波器数量,也是其输出中的通道数

然后你有一个最大池化层,它将卷积的输出作为输入。池化的输出形状为(None, 14, 14, 32),因此它将图像的大小除以二,其余部分保持原样。

然后你有另一个卷积,将池化的输出作为输入,这个新卷积的输出形状是(None, 11, 11, 32)。您在这里也使用了 32 个过滤器。

.... .....

....

然后你有一个Flatten 层,它获取图像并将它们转换为单个向量,输出形状为(None, 800),其中None 仍然是未触及的批量大小,800 是你拥有的所有元素输入张量,现在在单个向量中,批次中每个样本一个向量。

然后Dense 层,第一个有 32 个单元,第二个有 10 个单元。

模型的最终输出形状是(None, 10)。它在批次中为每个样本输出 10 个值。


每一层都有许多参数(通常是权重)。可训练的参数将通过反向传播进行更新。不可训练的参数将保持静态或使用不同的方法更新(只有少数层如BatchNormalization 具有使用不同方法更新的参数)

您的模型共有 43946 个权重,全部可训练。

【讨论】:

【参考方案3】:

对于 Conv2d, 如您所见,输出形状为 (None, 10, 10, 64)。第一个维度表示批量大小,目前为 None。因为网络事先并不知道批量大小。拟合数据后,None 将被您在拟合数据时提供的批量大小替换。

Input shape

4D tensor with shape: (batch, channels, rows, cols) if data_format is "channels_first" 
or 4D tensor with shape: (batch, rows, cols, channels) if data_format is 
"channels_last".

Output shape

4D tensor with shape: (batch, filters, new_rows, new_cols) if data_format is 
"channels_first" or 4D tensor with shape: (batch, new_rows, new_cols, filters) if 
data_format is "channels_last". rows and cols values might have changed due to 
padding.

ma​​xpool2d层的值与上面相同,略有变化如下。

**Input**

If data_format='channels_last': 4D tensor with shape: (batch_size, rows, cols, channels)
If data_format='channels_first': 4D tensor with shape: (batch_size, channels, rows, cols)

**Output**

If data_format='channels_last': 4D tensor with shape: (batch_size, pooled_rows, pooled_cols, channels)
If data_format='channels_first': 4D tensor with shape: (batch_size, channels, pooled_rows, pooled_cols)

现在,我们可以简单地在另一个卷积层的顶部添加一个卷积层,因为卷积的输出维度与输入维度相同。 我们通常在卷积层的顶部添加密集层来对图像进行分类。然而,将数据输入到形状(batch_size,单位)的密集层二维数组。而卷积层的输出是一个4D数组。因此,我们必须将从卷积层接收到的输出的维度更改为二维数组。

我们可以通过在卷积层顶部插入一个 Flatten 层来实现。 Flatten layer 将图像的 3 个维度压缩为一个维度。现在我们只有一个形状为(batch_size, squashed_size), 的二维数组,这对于密集层来说是可以接受的。

希望这会对你有所帮助。

【讨论】:

以上是关于如何解释 CNN 中的 model.summary() 输出?的主要内容,如果未能解决你的问题,请参考以下文章

Keras CNN 参数太少

Keras model.summary() 结果 - 了解参数的数量

Keras model.summary() 对象到字符串

model.summary() 在使用子类模型时无法打印输出形状

Tensorflow TextVectorization 在 model.summary() 中带来 None 形状

CNN、RNN、DNN的一般解释