ValueError:层conv3d_8的输入0与层不兼容::预期最小值ndim=5,发现ndim=4。收到完整形状:[无,4150150]

2024-06-06 03:19:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图在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)

有人能帮忙吗

非常感谢


Tags: theaddtruedatasizelabelsmodeluniform
2条回答

这项任务似乎不需要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
  1. 第一个答案是正确的。正如我所记得的(我有好几年没有使用MRI),每个切片由4个通道表示,通道中的每个体素包含关于相同物理位置的信息。因此,对4通道图像应用二维卷积是正确的方法
  2. 对于2D卷积,我建议使用input_shape=(150150,4),甚至使用input_shape=(None,None,4)来定义您的输入-它更通用。因此,您不需要先使用频道\u频道\u最后使用配置channel_last是默认格式,我记得
  3. 如果您坚持使用Conv3d,您的输入形状应该是:input_shape=(150150,4,1)(无,无,无,1) 列车组应遵循如下形状:np.random.rand(531501504,1)

相关问题 更多 >