0

i'm new to deep learning with Keras, so please inform me if i need to include more data in this post! So currently i have done some image augmentation to my training set for the MNIST dataset i had. So, i referred to this post here and i tried to save my augmented image models into the array. But when i try to reload the images and put into my mode.fit(), it throws me this error:

AttributeError: 'NoneType' object has no attribute 'shape'

How do i solve this?

Here is my current codes:

# get the dataset from keras library in tensorflow 2.0
mnist = tf.keras.datasets.mnist

# unpack the dataset to the respective x_train, y_train, x_test and y_test
(x_train, y_train), (x_test, y_test) = mnist.load_data()

# flatten 28*28 pixel images to 784 pixels for each image(from a 2D array to a 1D array)
num_pixels = x_train.shape[1] * x_train.shape[2]
X_train = x_train.reshape(x_train.shape[0], num_pixels).astype('float32')
X_test = x_test.reshape(x_test.shape[0], num_pixels).astype('float32')

# standardise X_train and X_test
X_train /= 255
X_test /= 255

# convert to categorical 
Y_train = tf.keras.utils.to_categorical(y_train, num_classes)
Y_test = tf.keras.utils.to_categorical(y_test, num_classes)


# reshape x_train and x_test to (n_images, x_shape, y_shape, channels)
# we are going to make chanels be 1 as we are not dealing with rgb images.
X_train = x_train.reshape(x_train.shape[0], 28, 28, 1)
X_test = x_test.reshape(x_test.shape[0], 28, 28, 1)
#  my cnn model
# Instantiate a Sequential model
model = Sequential(name="cnn_model_hyperParamTuned_sequential_LeNet")

# Layer 1 Conv2D
model.add(Conv2D(filters=150, kernel_size=(5, 5), strides=(1, 1), activation='elu', input_shape=(28, 28, 1), padding='same'))
model.add(BatchNormalization())
# Layer 2 Pooling Layer
model.add(AveragePooling2D(pool_size=(2, 2), strides=(2, 2)))

# Layer 3 Conv2D
model.add(Conv2D(filters=140, kernel_size=(5, 5), strides=(1, 1), activation='elu', padding='valid'))
model.add(BatchNormalization())
# Layer 4 Pooling Layer
model.add(AveragePooling2D(pool_size=(2, 2), strides=(2, 2)))

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

# Layer 6 Fully Connected Layer (Hidden Layer)
model.add(Dense(units=120, activation='tanh', kernel_initializer='normal', kernel_regularizer=l2(0.0001)))
model.add(Dropout(0.2))

# # Layer 7 Fully Connected Layer (Hidden Layer)
# model.add(Dense(units=84, activation='softmax'))

# Output layer
model.add(Dense(units=num_classes, activation='softmax'))

model.compile(optimizer='sgd',
          loss='categorical_crossentropy',
          metrics=['accuracy'])
# declare decay_rate and learning_rate here
learning_rate = 0.1 
decay_rate = 0.1

# define the learning rate change 
def exp_decay(epoch):
    lrate = learning_rate * np.exp(-decay_rate*epoch)
    return lrate
    
# learning schedule callback
loss_history = History()
lr_rate = LearningRateScheduler(exp_decay)
callbacks_list = [lr_rate]
# we shall do some ImageDataGenerator here to augment the input data, which can help prevent over-fitting
train_gen = ImageDataGenerator(
    rotation_range=8,
    shear_range=0.01,
    zoom_range=0.08,
    width_shift_range=0.1,
    height_shift_range=0.1,
    zca_whitening=True
)
test_gen =  ImageDataGenerator()
# we want to store the augmented data in a numpy array so the next time we run this we do not get a different set of images, which might result in a totally different loss score
augmented_data = []
num_augmented = 0

for X_batch, Y_batch in train_gen.flow(X_train, Y_train, batch_size=100):
  augmented_data.append(X_batch)
  num_augmented += 100
  if num_augmented == X_train.shape[0]:
    break

# concatenate the augmented data into a numpy array
augmented_data = np.concatenate(augmented_data)

# create a "flow" for the data to flow through
# train_generator = train_gen.flow(X_train, Y_train, batch_size=100)
test_generator = test_gen.flow(X_test, Y_test, batch_size=100)
# train the model(we use .fit since .fit_generator is depreciated already)
history = model.fit(augmented_data,
                    batch_size=640,
                    steps_per_epoch=60000//100,
                    epochs=60,
                    callbacks=[EarlyStopping(monitor='val_loss', patience=5), callbacks_list],
                    validation_data=test_generator,
                    validation_steps=10000//100,
                    verbose=1)
3
  • Your code says nothing about X_train, it's neither imported nor defined. It only shows you're using it but nothing can be said about how it originated. Please provide the code so there will be a way to see why it's None. Commented Nov 19, 2020 at 4:25
  • @dmitryro Hi i have included the parts inside already. Commented Nov 19, 2020 at 4:35
  • @proddoggy4life so in your line (x_train, y_train), (x_test, y_test) = mnist.load_data() you're assuming the tuple that you get from mnist.load_data() call has x_train element not empty, which turns out to be not the case and has to be checked before everything else is used at all. You have to check what is returned and find out why it's empty. Commented Nov 19, 2020 at 4:46

1 Answer 1

1

If you use zca_whitening=True then it is necessary to fit the generator to the data before you train so use

train_gen.fit(X_train)

I ran your code up to

# concatenate the augmented data into a numpy array
augmented_data = np.concatenate(augmented_data)

I printed the shape of the augmented data which looks correct with shape of (60000, 28, 28, 1) I did not proceed any further so was not able to find the problem but at least the data going into model.fit looks correct. I had trouble with the code for your model.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.