Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

3D Convolutional Neural Network input shape

I'm having a problem feeding a 3D CNN using Keras and Python to classify 3D shapes. I have a folder with some models in JSON format. I read those models into a Numpy Array. The models are 25*25*25 and represent the occupancy grid of the voxelized model (each position represents if the voxel in position (i,j,k) has points in it or no), so I only have 1 channel of input, like grayscale images in 2D images. The code that I have is the following:

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)

After this, I get the following error

Using TensorFlow backend. Traceback (most recent call last): File "/usr/local/lib/python3.6/site-packages/tensorflow/python/framework/common_shapes.py", line 670, in _call_cpp_shape_fn_impl status) File "/usr/local/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/contextlib.py", line 89, in exit next(self.gen) File "/usr/local/lib/python3.6/site-packages/tensorflow/python/framework/errors_impl.py", line 469, in raise_exception_on_not_ok_status pywrap_tensorflow.TF_GetCode(status)) tensorflow.python.framework.errors_impl.InvalidArgumentError: Negative dimension size caused by subtracting 5 from 1 for 'Conv3D' (op: 'Conv3D') with input shapes: [?,1,25,25,25], [5,5,5,25,32].

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "CNN_3D.py", line 76, in activation='relu')) File "/usr/local/lib/python3.6/site-packages/keras/models.py", line 299, in add layer.create_input_layer(batch_input_shape, input_dtype) File "/usr/local/lib/python3.6/site-packages/keras/engine/topology.py", line 401, in create_input_layer self(x) File "/usr/local/lib/python3.6/site-packages/keras/engine/topology.py", line 572, in call self.add_inbound_node(inbound_layers, node_indices, tensor_indices) File "/usr/local/lib/python3.6/site-packages/keras/engine/topology.py", line 635, in add_inbound_node Node.create_node(self, inbound_layers, node_indices, tensor_indices) File "/usr/local/lib/python3.6/site-packages/keras/engine/topology.py", line 166, in create_node output_tensors = to_list(outbound_layer.call(input_tensors[0], mask=input_masks[0])) File "/usr/local/lib/python3.6/site-packages/keras/layers/convolutional.py", line 1234, in call filter_shape=self.W_shape) File "/usr/local/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py", line 2831, in conv3d x = tf.nn.conv3d(x, kernel, strides, padding) File "/usr/local/lib/python3.6/site-packages/tensorflow/python/ops/gen_nn_ops.py", line 522, in conv3d strides=strides, padding=padding, name=name) File "/usr/local/lib/python3.6/site-packages/tensorflow/python/framework/op_def_library.py", line 763, in apply_op op_def=op_def) File "/usr/local/lib/python3.6/site-packages/tensorflow/python/framework/ops.py", line 2397, in create_op set_shapes_for_outputs(ret) File "/usr/local/lib/python3.6/site-packages/tensorflow/python/framework/ops.py", line 1757, in set_shapes_for_outputs shapes = shape_func(op) File "/usr/local/lib/python3.6/site-packages/tensorflow/python/framework/ops.py", line 1707, in call_with_requiring return call_cpp_shape_fn(op, require_shape_fn=True) File "/usr/local/lib/python3.6/site-packages/tensorflow/python/framework/common_shapes.py", line 610, in call_cpp_shape_fn debug_python_shape_fn, require_shape_fn) File "/usr/local/lib/python3.6/site-packages/tensorflow/python/framework/common_shapes.py", line 675, in _call_cpp_shape_fn_impl raise ValueError(err.message) ValueError: Negative dimension size caused by subtracting 5 from 1 for 'Conv3D' (op: 'Conv3D') with input shapes: [?,1,25,25,25], [5,5,5,25,32].

What am I doing wrong to get this error?

like image 590
João Pedro Fontes Avatar asked Mar 09 '17 16:03

João Pedro Fontes


People also ask

What is the input shape of CNN?

Suppose you are making a Convolutional Neural Network, now if you are aware of the theory of CNN, you must know that a CNN (2D) takes in a complete image as its input shape. And a complete image has 3 color channels that are red, green, black. So the shape of a normal image would be (height, width, color channels).

What is the input of 3D CNN?

A 3D CNN is simply the 3D equivalent: it takes as input a 3D volume or a sequence of 2D frames (e.g. slices in a CT scan), 3D CNNs are a powerful model for learning representations for volumetric data.

Does CNN input need to be square?

Using different sizes. That said most modern CNN's do allow you to run non-square images through them. This is somewhat advanced / unusual, so better to stick to square images unless you're confident you understand what's going on and the risks involved.

What is input shape in conv2d?

The ordering of the dimensions in the inputs. channels_last corresponds to inputs with shape (batch_size, height, width, channels) while channels_first corresponds to inputs with shape (batch_size, channels, height, width) . It defaults to the image_data_format value found in your Keras config file at ~/. keras/keras.


1 Answers

I think that the problem is that you are setting the input shape in Theano ordering but you are using Keras with Tensorflow backend and Tensorflow img ordering. In addition the y_train array has to be converted to categorical labels.

Updated code:

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)

Adding this lines should fix it.

like image 83
David de la Iglesia Avatar answered Sep 28 '22 05:09

David de la Iglesia