keras model fit: ValueError: Failed to find data adapter that can handle input: <class 'method'>, <class 'NoneType'>

Viewed 4669

I'm building a simple CNN Model for multi class classification. The training and test data is in data_path according to the classes sub directories as required by the flow_from_directory function of ImageDataGenerator.

Here's my code to build and train the model on the data:

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dropout, Flatten, Dense, Conv2D, MaxPooling2D
from tensorflow.keras.preprocessing.image import ImageDataGenerator

# Build Model

model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=(40, 24, 1)))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
model.add(Conv2D(64, kernel_size=(3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
model.add(Conv2D(64, kernel_size=(3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(12, activation='softmax'))

model.compile('binary_crossentropy', 'SGD', ['accuracy'])

# Init Generators

generator = ImageDataGenerator(rescale=1./255,
                               horizontal_flip=True,
                               fill_mode='nearest',
                               validation_split=0.2)

def get_train_images():
    train_images = generator.flow_from_directory(os.path.join(data_path, 'train'),
                                                 target_size=(40, 24, 1),
                                                 batch_size=32,
                                                 color_mode='grayscale',
                                                 class_mode='categorical',
                                                 subset='training',
                                                 shuffle=True)

def get_validation_images():
    validation_images = generator.flow_from_directory(os.path.join(data_path, 'train'),
                                                      target_size=(40, 24, 1),
                                                      batch_size=32,
                                                      color_mode='grayscale',
                                                    class_mode='categorical',
                                                      subset='validation',
                                                      shuffle=True)

# Train Model

model.fit(get_train_images, validation_data=get_validation_images, epochs=20)

The fit function gives the following error:

File "C:\Python38\lib\site-packages\tensorflow\python\keras\engine\training.py", line 108, in _method_wrapper
    return method(self, *args, **kwargs)
  File "C:\Python38\lib\site-packages\tensorflow\python\keras\engine\training.py", line 1049, in fit
    data_handler = data_adapter.DataHandler(
  File "C:\Python38\lib\site-packages\tensorflow\python\keras\engine\data_adapter.py", line 1104, in __init__
    adapter_cls = select_data_adapter(x, y)
  File "C:\Python38\lib\site-packages\tensorflow\python\keras\engine\data_adapter.py", line 968, in select_data_adapter
    raise ValueError(
ValueError: Failed to find data adapter that can handle input: <class 'method'>, <class 'NoneType'>

It looks to be some sort of compatability issues. I'm using tensorflow version 2.3.1. Can someone point out what I'm doing wrong and help me solve this issue?

Thanks!

2 Answers

There are 2 things I had to change to fix the issue:

  • The target size to flow_from_directory should be (40, 24) and not (40, 24, 1)
  • I had function wrappers to get the flow_from_directory generators and I was passing these functions to the fit function as parameters. Instead, I had to pass the return value of these wrappers to the fit function

The correct way should be:

model.fit(get_train_images(), validation_data=get_validation_images(), epochs=20)

did you execute

model=model.compile(tf.keras.optimizers.Adam(), loss='categorical_crossentropy', metrics=['accuracy']) 

For the validation_images in flow_from_directory set shuffle=False that way the validation data is presented in the same order to the model for each epoch.

Related