【问题标题】:Difference between the input shape for a 1D CNN, 2D CNN and 3D CNN1D CNN、2D CNN 和 3D CNN 的输入形状之间的差异
【发布时间】:2021-05-19 02:12:35
【问题描述】:

我是第一次构建用于图像分类的 CNN 模型,我对每种类型(1D CNN、2D CNN、3D CNN)的输入形状以及如何固定数量有点困惑卷积层中的过滤器。我的数据是 100x100x30,其中 30 个是特征。 这是我使用功能 API Keras 为 1D CNN 编写的文章:

def create_CNN1D_model(pool_type='max',conv_activation='relu'):
    input_layer = (30,1)
    conv_layer1 = Conv1D(filters=16, kernel_size=3, activation=conv_activation)(input_layer)
    max_pooling_layer1 = MaxPooling1D(pool_size=2)(conv_layer1)

    conv_layer2 = Conv1D(filters=32, kernel_size=3, activation=conv_activation)(max_pooling_layer1)
    max_pooling_layer2 = MaxPooling1D(pool_size=2)(conv_layer2)

    flatten_layer = Flatten()(max_pooling_layer2)
    dense_layer = Dense(units=64, activation='relu')(flatten_layer)

    output_layer = Dense(units=10, activation='softmax')(dense_layer)
    CNN_model = Model(inputs=input_layer, outputs=output_layer)
    return CNN_model
CNN1D = create_CNN1D_model()
CNN1D.compile(loss = 'categorical_crossentropy', optimizer = "adam",metrics = ['accuracy'])
Trace = CNN1D.fit(X, y, epochs=50, batch_size=100)

但是,在尝试通过将 Conv1D、Maxpooling1D 更改为 Conv2D 和 Maxpooling2D 来尝试 2D CNN 模型时,我收到以下错误:

ValueError: Input 0 of layer conv2d_1 is incompatible with the layer: : expected min_ndim=4, found ndim=3. Full shape received: (None, 30, 1)

谁能告诉我 2D CNN 和 3D CNN 的输入形状如何?输入数据预处理可以做什么?

【问题讨论】:

  • 我觉得你应该看看this的回答。所选的答案对我来说至少是不完整的(或者最坏的情况是错误的)。
  • 输入维度应该至少是您想要的卷积维度,即对于 |一维输入(W,) 你只执行一维卷积||对于 2D 输入(H, W),您可以执行 1D 或 2D 卷积 ||对于 3D 输入 (H, W, D),您可以执行 1D、2D 或 3D 卷积 ||。再次查看this 答案以获取更多详细信息。

标签: keras conv-neural-network convolution max-pooling functional-api


【解决方案1】:

TLDR;您的X_train 可以被视为(批次、空间暗淡...、频道)。内核并行应用于所有通道的空间维度。因此,一个 2D CNN 将需要两个空间维度 (batch, dim 1, dim 2, channels)

因此,对于(100,100,3) 形状的图像,您将需要一个 2D CNN,在所有 3 个通道上卷积超过 100 个高度和 100 个宽度。

让我们理解一下上面的说法。


首先,您需要了解 CNN(通常)在做什么。

内核在执行简单的矩阵运算(如 dot product) 到相应的值。

内核在空间维度上移动

现在,假设您有 100 张图像(称为批次)。每张图像为 28 x 28 像素,具有 3 个通道 R、G、B(在 CNN 的上下文中也称为 特征图)。如果我将此数据存储为张量,则形状将为(100,28,28,3)

但是,我可以只拥有一个没有任何高度的图像(可能像一个信号),或者我可以拥有具有额外空间维度的数据,例如视频(高度、宽度和时间)。

一般来说,这是基于 CNN 的神经网络的输入的样子。

同一个内核,所有通道

您需要知道的第二个关键点是,2D 内核将在 2 个空间维度上进行卷积,但相同的内核将在所有特征图/通道上执行此操作。所以,如果我有一个(3,3) 内核。相同的内核将应用于 R、G、B 通道(并行)并在图像的 HeightWidth 上移动。

运算是一个点积

最后,操作(对于单个特征图/通道和单个卷积窗口)可以如下所示进行可视化。

因此,简而言之-

  1. 内核被应用于数据的空间维度
  2. 内核形状等于空间维度数
  3. 内核一次应用于所有特征图/通道
  4. 操作是内核和窗口之间的简单点积

让我们以具有单个特征图/通道的张量为例(因此,对于图像,它将是灰度的)-

因此,凭直觉,我们看到如果我想使用 1D CNN,您的数据必须具有 1 个空间维度,这意味着每个样本都需要是 2D(空间维度和通道) ,这意味着X_train必须是一个3D张量(batch, spatial dimensions, channels)

同样,对于 2D CNN,您将有 2 个空间维度(例如 H、W)并且是 3D 样本 (H, W, Channels)X_train 将是 (Samples, H, W, Channels)

让我们用代码试试这个 -

import tensorflow as tf
from tensorflow.keras import layers

X_2D = tf.random.normal((100,7,3))   #Samples, width/time, channels (feature maps)
X_3D = tf.random.normal((100,5,7,3)) #Samples, height, width, channels (feature maps)
X_4D = tf.random.normal((100,6,6,2,3))   #Samples, height, width, time, channels (feature maps)

用于应用 1D CNN -

#With padding = same, the edge pixels are padded to not skip a few

#Out featuremaps = 10, kernel (3,)
cnn1d = layers.Conv1D(10, 3, padding='same')(X_2D) 
print(X_2D.shape,'->',cnn1d.shape)

#(100, 7, 3) -> (100, 7, 10)

用于应用 2D CNN -

#Out featuremaps = 10, kernel (3,3)
cnn2d = layers.Conv2D(10, (3,3), padding='same')(X_3D) 
print(X_3D.shape,'->',cnn2d.shape)

#(100, 5, 7, 3) -> (100, 5, 7, 10)

对于 3D CNN -

#Out featuremaps = 10, kernel (3,3)
cnn3d = layers.Conv3D(10, (3,3,2), padding='same')(X_4D) 
print(X_4D.shape,'->',cnn3d.shape)

#(100, 6, 6, 2, 3) -> (100, 6, 6, 2, 10)

【讨论】:

  • 解释卷积层概念的真正好答案。添加到您的错误:...expected min_ndim=4, found ndim=3. Full shape received: (None, 30, 1)conv2D 层预期形状为(batch size, 100, 100, 3) 的数据,但您为其提供了一些不同的维度。如果您打算使用 Conv2D 层,我认为您必须修改数据形状。
  • 谢谢你的回复和你相当透彻的解释,我真的理解你给我的例子,除了把这个应用到我的数据上,我觉得和你说的有点不同,因为图像形状 = 100x100x30,这意味着 10000x30,其中 10000 覆盖像素。所以,我真的很想知道如何获得 (batch-size, 100,100,30) 的格式
  • 您要应用 1D CNN 还是 2D cnn?如果要使用 1D CNN,则将其重塑为 (10000,3),1 个空间维度....如果您要使用 2D CNN,则将其重塑为 (100,100,3)
  • 另外,在你的代码中,我不确定你为什么有input_layer = (30,1)
  • 我在某处遵循了一个示例并将其应用于我的数据。如有不妥之处,请帮我改正
【解决方案2】:

通过 100x100x30 的输入形状,您是说批量大小为 100?还是每个数据的形状都是 100x100x30?在第二种情况下,您必须改用Conv2D 层。每一层的输入形状应该是:

Conv1D: (size1, channel_number), Conv2D: (size1, size2, channel_number), Conv3D: (size1, size2, size3, channel_number)

1DCNN2DCNN3DCNN表示卷积层每个内核和通道的维度。

【讨论】:

  • 感谢克雷纳德的关注。是的,正如你所说,每个数据的形状都是 100x100x30
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-20
  • 2018-08-23
  • 2019-08-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多