3D卷积神经网络的输入形状

7

我在使用Keras和Python来分类3D形状时,遇到了一个问题,无法成功地喂养3D CNN。我有一个包含一些JSON格式模型的文件夹。我将这些模型读入Numpy数组中。这些模型是25*25*25的,表示体素化模型的占用网格(每个位置表示位置(i,j,k)中的体素是否具有点),因此我只有一个输入通道,类似于2D图像中的灰度图像。我现有的代码如下:

import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Convolution3D, MaxPooling3D
from keras.optimizers import SGD
from keras.utils import np_utils
from keras import backend as K

# Number of Classes and Epochs of Training
nb_classes = 3 # cube, cone or sphere
nb_epoch = 100
batch_size = 2

# Input Image Dimensions
img_rows, img_cols, img_depth = 25, 25, 25

# Number of Convolutional Filters to use
nb_filters = 32

# Convolution Kernel Size
kernel_size = [5,5,5]

X_train, Y_train = [], []

# Read from File
import os
import json

i=0
for filename in os.listdir(os.path.join(os.getcwd(), 'models')):
    with open(os.path.join(os.getcwd(), 'models', filename)) as f:
        file = f.readlines()
        json_file = '\n'.join(file)
        content = json.loads(json_file)
        occupancy = content['model']['occupancy']
        form = []
        for value in occupancy:
            form.append(int(value))
        final_model = [ [ [ 0 for i in range(img_rows) ]
                              for j in range(img_cols) ]
                              for k in range(img_depth) ]
        a = 0
        for i in range(img_rows):
            for j in range(img_cols):
                for k in range(img_depth):
                    final_model[i][j][k] = form[a]
                    a = a + 1
        X_train.append(final_model)
        Y_train.append(content['model']['label'])

X_train = np.array(X_train)
Y_train = np.array(Y_train)

# (1 channel, 25 rows, 25 cols, 25 of depth)
input_shape = (1, img_rows, img_cols, img_depth)

# Init
model = Sequential()

# 3D Convolution layer
model.add(Convolution3D(nb_filters, kernel_size[0], kernel_size[1], kernel_size[2],
                        input_shape=input_shape,
                        activation='relu'))

# Fully Connected layer
model.add(Flatten())
model.add(Dense(128,
          init='normal',
          activation='relu'))
model.add(Dropout(0.5))

# Softmax Layer
model.add(Dense(nb_classes,
                init='normal'))
model.add(Activation('softmax'))

# Compile
model.compile(loss='categorical_crossentropy',
              optimizer=SGD())

# Fit network
model.fit(X_train, Y_train, nb_epoch=nb_epoch,
         verbose=1)

在此之后,我得到了以下错误。
使用TensorFlow后端。回溯(最近的调用最先):在“/usr/local/lib/python3.6/site-packages/tensorflow/python/framework/common_shapes.py”中,第670行,“_call_cpp_shape_fn_impl”函数中, status参数有问题,在“/usr/local/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/contextlib.py”中,第89行,“exit”函数中, next(self.gen)参数有问题,在“/usr/local/lib/python3.6/site-packages/tensorflow/python/framework/errors_impl.py”中,第469行,“raise_exception_on_not_ok_status”函数中, pywrap_tensorflow.TF_GetCode(status))参数有问题,导致“Conv3D”(op: 'Conv3D')的输入形状为[?,1,25,25,25],[5,5,5,25,32],从1减去5导致负数维度大小。 在处理上述异常期间,发生另一个异常:在“CNN_3D.py”的第76行, activation='relu')),在“/usr/local/lib/python3.6/site-packages/keras/models.py”中,第299行,“add”函数中,layer.create_input_layer(batch_input_shape, input_dtype)参数有问题,在“/usr/local/lib/python3.6/site-packages/keras/engine/topology.py”中, 第401行,“create_input_layer”函数中,self(x)参数有问题,在“/usr/local/lib/python3.6/site-packages/keras/engine/topology.py”中, 第572行,“call”函数中,self.add_inbound_node(inbound_layers, node_indices, tensor_indices)参数有问题,在“/usr/local/lib/python3.6/site-packages/keras/engine/topology.py”中, 第635行,“add_inbound_node”函数中,Node.create_node(self, inbound_layers, node_indices, tensor_indices)参数有问题,在“/usr/local/lib/python3.6/site-packages/keras/engine/topology.py”中, 第166行,“create_node”函数中,output_tensors = to_list(outbound_layer.call(input_tensors[0], mask=input_masks[0]))参数有问题,在“/usr/local/lib/python3.6/site-packages/keras/layers/convolutional.py”中, 第1234行,“call”函数中,filter_shape=self.W_shape)参数有问题,在“/usr/local/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py”中, 第2831行,“conv3d”函数中,x = tf.nn.conv3d(x, kernel, strides, padding)参数有问题,在“/usr/local/lib/python3.6/site-packages/tensorflow/python/ops/gen_nn_ops.py”中, 第522行,“conv3d”函数中,strides=strides, padding=padding, name=name参数有问题,在“/usr/local/lib/python3.6/site-packages/tensorflow/python/framework/op_def_library.py”中, 第763行,“apply_op”函数中,op_def=op_def参数有问题,在“/usr/local/lib/python3.6/site-packages/tensorflow/python/framework/ops.py”中, 第2397行,“create_op”函数中,set_shapes_for_outputs(ret)参数有问题,在“/usr/local/lib/python3.6/site-packages/tensorflow/python/framework/ops.py”中, 第1757行,“set_shapes_for_outputs”函数中,shapes = shape_func(op)参数有问题,在“/usr/local/lib/python3.6/site-packages/tensorflow/python/framework/ops.py”中, 第1707行,“call_with_requiring”函数中,return call_cpp_shape_fn(op, require_shape_fn=True)参数有问题,在“/usr/local/lib/python3.6/site-packages/tensorflow/python/framework/common_shapes.py”中, 第610行,“call_cpp_shape_fn”函数中,debug_python_shape_fn, require_shape_fn参数有问题,在“/usr/local/lib/python3.6/site-packages/tensorflow/python/framework/common_shapes.py”中, 第675行,“_call_cpp_shape_fn_impl”函数中,err.message参数有问题,导致“Conv3D”(op: 'Conv3D')的输入形状为[?,1,25,25,25],[5,5,5,25,32],从1减去5导致负数维度大小。
我做错了什么导致出现这个错误?

我认为你的训练数据形状有误。Tensorflow期望数据以(sample, dim1, dim2, ..., channel)的形式呈现。如果给定一组常规的二维图像,可以这样重塑:X_train.reshape((-1, WIDTH, HEIGHT, 1))。将其适应到你的情况,你可以尝试 X_train = X_train.reshape((-1, img_rows, img_cols, img_depth, 1))。而input_shape应该是(img_rows, img_cols, img_depth, 1) - Matt
我仍然得到相同的错误。当我添加更多通道(input_shape =(5,img_rows,img_cols,img_depth))以克服或等于卷积滤波器的大小时,我可以通过创建层。但是我只有一个输入通道。我认为问题在Conv3D层的定义中。 - João Pedro Fontes
我想做跟你一样的事情,但是我不知道如何将一个3D模型文件转换成占用格网。你是怎么做到的呢?谢谢! - Braelyn B
2个回答

7

我认为问题在于你正在使用Theano顺序设置输入形状,但是你正在使用Tensorflow后端和Tensorflow img顺序的Keras。此外,y_train数组必须转换为分类标签。

更新后的代码:

from keras.utils import np_utils
from keras import backend as K

if K.image_dim_ordering() == 'th':
    X_train = X_train.reshape(X_train.shape[0], 1, img_rows, img_cols, img_depth)
    input_shape = (1, img_rows, img_cols, img_depth)
else:
    X_train = X_train.reshape(X_train.shape[0], img_rows, img_cols, img_depth, 1)
    input_shape = (img_rows, img_cols, img_depth, 1)

Y_train = np_utils.to_categorical(Y_train, nb_classes)

添加这些代码行应该可以解决它。

使用这两个代码几乎就可以了。但是现在我遇到了一个新的错误:Using TensorFlow backend. Traceback (most recent call last): File "CNN_3D_2.py", line 86, in <module> verbose=1) ... ValueError: Error when checking model input: expected convolution3d_input_1 to have shape (None, 25, 25, 25, 1) but got array with shape (1, 25, 25, 25, 2) - João Pedro Fontes
David,它报错了:“ValueError: Input 0 is incompatible with layer convolution3d_1: expected ndim=5, found ndim=4”。你给我的例子不是针对2D的吗?在输入形状中,你只给出了行和列。我尝试添加img_depths,但它报错了:“ValueError: Error when checking model target: expected activation_1 to have shape (None, 3) but got array with shape (2, 1)”。 - João Pedro Fontes
@JoãoPedroFontes 是的。那是个打字错误。现在已经更新了。我猜你现在遇到的新错误与 y_train 数组有关。你能告诉我你的 y_train.shape 吗? - David de la Iglesia
好的 @JoãoPedroFontes,你需要转换你的 y_train 数组。 - David de la Iglesia
这是我的一个文件示例链接 - João Pedro Fontes
显示剩余6条评论

1
如果您使用3D CNN进行帧预测,则必须使用以下输入: input=(帧数,高度,宽度,通道数) 我的代码 def cnn_network(): model = Sequential()
# # Layer 1
# model.add(
# Conv3D(512, kernel_size=(3, 3, 3), strides=(1, 1, 1), input_shape=(6, 14, 14, 512), use_bias=512, padding='SAME',
#            activation='relu',
#            name='conv3D_1_1'))

# model.add(Conv3D(512, kernel_size=(3, 3, 3), strides=(1, 1, 1),use_bias=512, padding='SAME',
#        activation='relu',name='conv3D_1_5'))

# model.add(MaxPooling3D(pool_size=(4, 2, 2), strides=(1, 2, 2)))
# model.add(BatchNormalization())

# # Layer 2
# model.add(
#     Conv3DTranspose(512, kernel_size=(1, 3, 3), strides=(1, 2, 2), use_bias=512, padding='SAME', activation='relu',
#                     name='Deconv3D_16'))

# model.add(Conv3D(512, kernel_size=(3, 3, 3), strides=(1, 1, 1), use_bias=512,
#                  padding='SAME', activation='relu', name='conv3D_2__19'))

# #model.add(Conv3D(512, kernel_size=(3, 3, 3), strides=(1, 1, 1), use_bias=512,
#  #                padding='SAME', activation='relu', name='conv3D_2__77'))

# model.add(
# Conv3DTranspose(256, kernel_size=(3, 3, 3), strides=(1, 2, 2), use_bias=256, padding='SAME', activation='relu',
#                     name='Deconv3D_1'))

# model.add(Conv3D(256, kernel_size=(3, 3, 3), strides=(1, 1, 1), use_bias=256,
#                  padding='SAME', activation='relu', name='conv3D_2__1'))

# model.add(Conv3D(256, kernel_size=(3, 3, 3), strides=(1, 1, 1), use_bias=256, padding='SAME', activation='relu',
#                  name='conv3D_2__2'))
# model.add(MaxPooling3D(pool_size=(3, 1, 1), strides=(1, 1, 1)))
# #model.add(Conv3D(256, kernel_size=(1, 3, 3), strides=(1, 1, 1), use_bias=256, padding='SAME', activation='relu',
#                  #name='conv3D_18'))
# #model.add(MaxPooling3D(pool_size=(2, 1, 1), strides=(2, 1, 1)))
# model.add(BatchNormalization())
# # Layer 3

# model.add(
#     Conv3DTranspose(128, kernel_size=(1, 3, 3), strides=(1, 2, 2), use_bias=128, padding='SAME', activation='relu',
#                     name='Deconv3D_2'))

# model.add(Conv3D(128, kernel_size=(1, 3, 3), strides=(1, 1, 1), use_bias=128, padding='SAME', activation='relu',
#                  name='conv3D__3__1'))

# model.add(Conv3D(128, kernel_size=(1, 3, 3), strides=(1, 1, 1), use_bias=128, padding='SAME', activation='relu',
#                  name='conv3D__3__2'))
# model.add(BatchNormalization())

# # Layer4

# model.add(
#     Conv3DTranspose(64, kernel_size=(1, 3, 3), strides=(1, 2, 2), use_bias=64, padding='SAME', activation='relu',
#                     name='Deconv3D_3'))

# model.add(Conv3D(64, kernel_size=(1, 3, 3), strides=(1, 1, 1), use_bias=64, padding='SAME', activation='relu',
#                  name='conv3D__4__1'))

# model.add(Conv3D(64, kernel_size=(1, 3, 3), strides=(1, 1, 1), use_bias=64, padding='SAME', activation='relu',
#                      name='conv3D__4__2'))


# model.add(BatchNormalization())
# # Layer 5

# model.add(
#     Conv3DTranspose(32, kernel_size=(1, 3, 3), strides=(1, 2, 2), use_bias=32, padding='SAME', activation='relu',
#                     name='Deconv3D_4'))

# model.add(Conv3D(32, kernel_size=(1, 3, 3), strides=(1, 1, 1), use_bias=32, padding='SAME', activation='relu',
#                  name='conv3D__5__1'))

# model.add(Conv3D(16, kernel_size=(1, 3, 3), strides=(1, 1, 1), use_bias=16, padding='SAME', activation='relu',
#                  name='conv3D__5__2'))

# #model.add(Conv3D(8, kernel_size=(1, 3, 3), strides=(1, 1, 1), use_bias=8, padding='SAME', activation='relu',
#                  #name='conv3D2_23'))

# model.add(Conv3D(1, kernel_size=(1, 3, 3), strides=(1, 1, 1), use_bias=1, padding='SAME', activation='sigmoid',
#                                      name='conv3D__5__3'))
# #model.add(BatchNormalization())

1
目前你的回答不够清晰,请编辑并添加更多细节,以帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何撰写好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接