【问题标题】:ValueError: Input 0 of layer conv3d_8 is incompatible with the layer: : expected min_ndim=5, found ndim=4. Full shape received: [None, 4, 150, 150]ValueError:conv3d_8 层的输入 0 与层不兼容::预期 min_ndim=5,发现 ndim=4。收到的完整形状:[None, 4, 150, 150]
【发布时间】:2020-08-12 23:52:16
【问题描述】:

我正在尝试在 Keras 中训练 3D CNN 模型,但在执行单元格时出现此错误:

ValueError: Input 0 of layer conv3d_8 is incompatible with the layer: : expected min_ndim=5, found ndim=4. Full shape received: [None, 4, 150, 150]

我的输入数据是一个带有图像数据的 numpy 数组。以下是形状(我知道53太少了,但只是为了学习目的):

Training data shape:  (53, 4, 150, 150)
Training labels shape:  (53, 1)
Validation data shape:  (14, 4, 150, 150)
Validation labels shape:  (14, 1)

我尝试使用的模型是:

# Create the model
model = Sequential()
model.add(Conv3D(32, kernel_size=(3, 3, 3), activation='relu', kernel_initializer='he_uniform', input_shape=(4,150,150)))
model.add(MaxPooling3D(pool_size=(2, 2, 2)))
model.add(BatchNormalization(center=True, scale=True))
model.add(Dropout(0.5))
model.add(Conv3D(64, kernel_size=(3, 3, 3), activation='relu', kernel_initializer='he_uniform'))
model.add(MaxPooling3D(pool_size=(2, 2, 2)))
model.add(BatchNormalization(center=True, scale=True))
model.add(Dropout(0.5))
model.add(Flatten())
model.add(Dense(256, activation='relu', kernel_initializer='he_uniform'))
model.add(Dense(256, activation='relu', kernel_initializer='he_uniform'))
model.add(Dense(4, activation='softmax'))

# Compile the model
model.compile(loss='categorical_crossentropy',
              optimizer=keras.optimizers.Adam(lr=0.001),
              metrics=['accuracy'])
model.summary()
# Fit data to model
history = model.fit(treino3d, treino3d_labels,
            epochs=40)

有人可以帮忙吗?

非常感谢!

【问题讨论】:

    标签: python tensorflow keras conv-neural-network


    【解决方案1】:

    您似乎不需要Conv3D 层来执行此任务。请改用Conv2D,并在kernel_sizepool_size 中仅使用1 或2 个值。

    model = Sequential()
    model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', 
                     kernel_initializer='he_uniform', 
                     input_shape=(4,150,150)))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(BatchNormalization(center=True, scale=True))
    model.add(Dropout(0.5))
    model.add(Conv2D(64, kernel_size=(3, 3), activation='relu', 
                     kernel_initializer='he_uniform'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(BatchNormalization(center=True, scale=True))
    model.add(Dropout(0.5))
    model.add(Flatten())
    model.add(Dense(256, activation='relu', kernel_initializer='he_uniform'))
    model.add(Dense(256, activation='relu', kernel_initializer='he_uniform'))
    model.add(Dense(4, activation='softmax'))
    

    您的频道维度是第一位的,因此您需要告诉 Keras。使用这一行:

    tf.keras.backend.set_image_data_format('channels_first')
    

    或者在每个Conv2DMaxPooling2D层设置这个参数:

    data_format='channels_first'
    

    或者将输入张量的维度置换为(54, 150, 150, 4)

    np.transpose(x, (0, 2, 3, 1))
    

    功能完整,已更正示例:

    import os
    os.environ['CUDA_VISIBLE_DEVICES'] = '-1'
    from tensorflow.keras.layers import *
    import numpy as np
    from tensorflow.keras.models import Sequential
    
    xtrain = np.random.rand(53, 4, 150, 150)
    ytrain = np.random.randint(0, 4, (53, 1))
    
    xtrain = np.transpose(xtrain, (0, 2, 3, 1))
    
    model = Sequential()
    model.add(Conv2D(8, kernel_size=(3, 3), activation='relu',
                     kernel_initializer='he_uniform', input_shape=xtrain.shape[1:]))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(BatchNormalization(center=True, scale=True))
    model.add(Dropout(0.5))
    model.add(Conv2D(8, kernel_size=(3, 3), activation='relu',
              kernel_initializer='he_uniform'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(BatchNormalization(center=True, scale=True))
    model.add(Dropout(0.5))
    model.add(Flatten())
    model.add(Dense(32, activation='relu', kernel_initializer='he_uniform'))
    model.add(Dense(32, activation='relu', kernel_initializer='he_uniform'))
    model.add(Dense(4, activation='softmax'))
    
    model.compile(loss='sparse_categorical_crossentropy',
                  optimizer='adam',
                  metrics=['accuracy'])
    model.summary()
    
    history = model.fit(xtrain, ytrain, epochs=1)
    
    32/53 [=================>............] - ETA: 2s - loss: 1.8215 - acc: 0.2812
    53/53 [==============================] - 5s 91ms/sample - loss: 1.9651 - acc: 0.2264
    

    【讨论】:

    • 尼古拉斯,非常感谢您的回答。这些数据实际上是医学图像,因此 4 个通道中的每一个都代表一个检查片段。无论如何,我尝试使用 keras 后端选项运行您的建议,收到以下错误:ValueError: Shapes (None, 1) and (None, 4) are incompatible
    • 您需要另一个维度才能使用Conv3D。如果您的数据只有 4 个,Conv3D 不是您要查找的内容
    • 您可能在某个地方出错了。请参考我上面的例子。它有效。
    • 很抱歉打扰您...尝试了您的示例,继续导致同样的错误。问题可能是标签数组:array([3, 0, 1, 0, 0, 1, 2, 3, 2, 3, 2, 2, 1, 1, 0, 0, 0, 2, 0, 1 , 1, 3, 1, 0, 1, 2, 0, 0, 2, 1, 0, 2, 1, 2, 0, 1, 1, 0, 2, 3, 3, 1, 1, 0, 1 , 2, 0, 3, 3, 3, 3, 0, 2])
    • 啊,我的错。您的标签不是一次性编码的。它现在应该可以工作了,我编辑了代码。
    【解决方案2】:
    1. 第一个答案是正确的。我记得(我有几年没有使用 MRI),每个切片由 4 个通道表示,通道中的每个体素包含有关相同物理位置的信息。因此,对 4 通道的图像应用 2D 卷积是正确的方法。
    2. 对于 2D 卷积,我建议使用 input_shape=(150,150,4) 定义您的输入,或者甚至使用 input_shape=(None, None, 4) - 它更通用。所以你不需要玩 channel_firstchannel_last 配置。 channel_last 是我记得的默认格式
    3. 如果你坚持使用 Conv3d,你的输入形状应该是:input_shape=(150,150,4,1)(None, None, None, 1) 并且 trainset 应该遵循如下形状:np.random.rand(53, 150, 150, 4, 1)

    【讨论】:

    • 尤里,非常感谢您的回答和解释!我设法使 Nicolas 的解决方案发挥作用!谢谢!
    猜你喜欢
    • 1970-01-01
    • 2022-12-10
    • 1970-01-01
    • 1970-01-01
    • 2021-08-10
    • 2020-11-15
    • 2021-11-13
    • 1970-01-01
    • 2020-09-01
    相关资源
    最近更新 更多