3
votes

I am trying to build an image classifier but im running in to the error as mentioned in the title of this post. Below is the code im working on. How do i convert my numpy array that is of shape (8020,) to the shape as required by the function fit()? I tried to print the input shape: train_img_array.shape[1:] but it gives an empty shape: ()

import numpy as np
img_train.shape
img_valid.shape
img_train.head(5)
img_valid.head(5)

(8020, 4)
(2006, 4)
         ID  index  class                                               data
8030  11596  11596      0  [[[255, 255, 255, 0], [255, 255, 255, 0], [255...
2152  11149  11149      0  [[[255, 255, 255, 0], [255, 255, 255, 0], [255...
550   10015  10015      0  [[[255, 255, 255, 0], [255, 255, 255, 0], [255...
1740   9035   9035      0  [[[255, 255, 255, 0], [255, 255, 255, 0], [255...
9549   8218   8218      1  [[[255, 255, 255, 0], [255, 255, 255, 0], [255...
         ID  index  class                                               data
3312   5481   5481      0  [[[255, 255, 255, 0], [255, 255, 255, 0], [255...
9079  10002  10002      0  [[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], ...
6129  11358  11358      0  [[[255, 255, 255, 0], [255, 255, 255, 0], [255...
1147   2613   2613      1  [[[255, 255, 255, 0], [255, 255, 255, 0], [255...
7105   5442   5442      1  [[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], ...

img_train.dtypes

ID        int64
index     int64
class     int64
data     object
dtype: object

train_img_array = np.array([])
train_id_array = np.array([])
train_lab_array = np.array([])
train_id_array = img_train['ID'].values
train_lab_array = img_train['class'].values
train_img_array =img_train['data'].values

train_img_array.shape
train_lab_array.shape
train_id_array.shape

(8020,)
(8020,)
(8020,)

# Importing the Keras libraries and other packages


#matplotlib inline
from __future__ import print_function

import keras
from keras.models import Sequential
from keras.layers import Conv2D
from keras.layers import MaxPooling2D
from keras.layers import Flatten
from keras.layers import Dense
from keras.layers import Dropout
Using Theano backend.
WARNING (theano.tensor.blas): Using NumPy C-API based implementation for BLAS functions.

classifier = Sequential()
classifier.add(Conv2D(32, (3, 3), padding='same', activation='relu', input_shape = (256, 256, 3)))
classifier.add(Conv2D(32, (3, 3), activation='relu'))
classifier.add(MaxPooling2D(pool_size=(2, 2)))
classifier.add(Dropout(0.25))

classifier.add(Conv2D(64, (3, 3), padding='same', activation='relu'))
classifier.add(Conv2D(64, (3, 3), activation='relu'))
classifier.add(MaxPooling2D(pool_size=(2, 2)))  
classifier.add(Dropout(0.25))

classifier.add(Conv2D(64, (3, 3), padding='same', activation='relu'))
classifier.add(Conv2D(64, (3, 3), activation='relu'))
classifier.add(MaxPooling2D(pool_size=(2, 2)))
classifier.add(Dropout(0.25))

classifier.add(Conv2D(64, (3, 3), padding='same', activation='relu'))
classifier.add(Conv2D(64, (3, 3), activation='relu'))
classifier.add(MaxPooling2D(pool_size=(2, 2)))
classifier.add(Dropout(0.25))

classifier.add(Flatten())
classifier.add(Dense(units = 256, activation = 'relu'))
classifier.add(Dropout(0.25))
classifier.add(Dense(units = 1, activation = 'sigmoid'))    classifier.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])
classifier.summary()

batch_size = 32
epochs = 15


history = classifier.fit(train_img_array, train_lab_array, batch_size=batch_size, epochs=epochs, verbose=1, 
                   validation_data=(valid_img_array, valid_lab_array))
classifier.evaluate(valid_img_array, valid_lab_array)


ValueError: Error when checking input: expected conv2d_1_input to have 4 dimensions, but got array with shape (8020, 1)

Edit: ----------------------------------------------------------- As Nassim requested, adding a few more details to this post:

print(train_img_array) 

[ array([[[255, 255, 255,   0],
        [255, 255, 255,   0],
        [255, 255, 255,   0],
        ..., 
        [255, 255, 255,   0],
        [255, 255, 255,   0],
        [255, 255, 255,   0]],

       [[255, 255, 255,   0],
        [255, 255, 255,   0],
        [255, 255, 255,   0],
        ..., 
        ..., 
        [255, 255, 255,   0],
        [255, 255, 255,   0],
        [255, 255, 255,   0]]], dtype=uint8)
 array([[[255, 255, 255,   0],
        [255, 255, 255,   0],
        [255, 255, 255,   0],
        ..., 
        ..., 
        [0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]]], dtype=uint8)]


print(list(train_img_array)) 

[array([[[255, 255, 255,   0],
        [255, 255, 255,   0],
        [255, 255, 255,   0],
        ..., 
        [255, 255, 255,   0],
        [255, 255, 255,   0],
        [255, 255, 255,   0]],

       [[255, 255, 255,   0],
        [255, 255, 255,   0],
        [255, 255, 255,   0],
        ..., 
        ..., 
        [255, 255, 255,   0],
        [255, 255, 255,   0],
        [255, 255, 255,   0]]], dtype=uint8), array([[[255, 255, 255,   0],
        [255, 255, 255,   0],
        [255, 255, 255,   0],
        ..., 


print(np.array(list(train_img_array)))
throws the error:

ValueError: could not broadcast input array from shape (700,584,4) into shape (700,584)
1
you should actually show the model. Not just a call to createModel().deeiip
I did not include the model as i thought it wouldnt mak a difference to this discussion. But i will include it now.redwolf_cr7
According to keras docs the input for the conv2d layer must be 4-dimensional of the type: (samples, channels, rows, cols) or (samples, rows, cols, channels)Dav2357
@Dav2357: Thanks Dav... But my question is how do i get my training and validation data in to that shape?redwolf_cr7
can you print(type(train_img_array[0])) then print(train_img_array[0].shape) then print(train_img_array[0]) ?Nassim Ben

1 Answers

5
votes

So after debuging by using the result :

> print(type(train_img_array[0]))
<type 'numpy.ndarray'>

> print(train_img_array[0].shape)
(700, 584, 4)

> print(rain_img_array[0])
array([[[255, 255, 255, 0], [255, 255, 255, 0], [255, 255, 255, 0], ..., ..., [255, 255, 255, 0], [255, 255, 255, 0], [255, 255, 255, 0]]], dtype=uint8)

we see that what is returned when you do :

train_img_array =img_train['data'].values

is actually one numpy array of shape (8020, ) where all the elements are other numpy arrays containin images. Basically two numpy arrays nested.

So what you want is to kind of flatten that nested structure of nested arrays into one single array object. The way I would do it, it might be a bit hacky but should work, is the following :

train_img_array =img_train['data'].values
train_img_array = np.array(list(train_img_array))

So basically transform the structure of numpy array of numpy arrays into a list of numpy arrays. Then when you build a numpy array out of the list of numpy arrays, you get (magic) a numpy array with one more dimension.

The shape after this operation should be (8020, 700, 584, 4)

Now, I see one more potential issue you might encounter with this is the format of your image. The channel dimension of your images is the last one (4 channels here). You should then, in your convolutional layers specify :

conv2D(... , data_format="channels_last", )

Also, your input shape for the first layer is (700, 584, 4), not (256, 256, 3)

hope it works :-)