I’ve build my model, but do not know how to fit it. Could anyone give me some tip so I can use ImageDataGenerator
in my models while working with images, or it is better to use other ways like using Dataset
?
import tensorflow as tf from tensorflow.keras.layers import Dense, Conv2D, Flatten, Dropout, MaxPooling2D import numpy as np import matplotlib.pyplot as plt import cv2 import os # const IMG_HEIGHT = 150 IMG_WIDTH = 150 BATCH = 32 EPOCHS = 5 train_dir = "data/images/train" val_dir = "data/images/val" # train image data generator train_generator = tf.keras.preprocessing.image.ImageDataGenerator( rescale=1./255, horizontal_flip=True, dtype=tf.float32 ) train_generator.flow_from_directory( directory=train_dir, target_size=(IMG_WIDTH, IMG_HEIGHT) ) # validation image data generator val_generator = tf.keras.preprocessing.image.ImageDataGenerator( rescale=1./255, horizontal_flip=False ) val_generator.flow_from_directory( directory = val_dir, target_size=(IMG_WIDTH, IMG_HEIGHT) ) # count train cats & dogs train_cats_len = len(os.listdir(os.path.join(train_dir, "cats"))) train_dogs_len = len(os.listdir(os.path.join(train_dir, "dogs"))) train_len = train_cats_len + train_dogs_len # count validation cats & dogs val_cats_len = len(os.listdir(os.path.join(val_dir, "cats"))) val_dogs_len = len(os.listdir(os.path.join(val_dir, "dogs"))) val_len = val_cats_len + val_dogs_len # build a model model = tf.keras.Sequential([ Conv2D(16, 3, padding='same', activation='relu', input_shape=(IMG_HEIGHT, IMG_WIDTH , 3)), MaxPooling2D(), Dropout(0.2), Flatten(), Dense(128, activation='relu'), Dense(64, activation='relu'), Dense(2, activation='sigmoid') ]) model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) # fit? # history = model.fit_generator( # train_generator, # steps_per_epoch=train_len // BATCH, # epochs=EPOCHS, # validation_data=val_generator, # validation_steps=val_len // BATCH, # verbose=True # ) # raises error: # ValueError: Failed to find data adapter that can handle input: <class 'tensorflow.python.keras.preprocessing.image.ImageDataGenerator'>, <class 'NoneType'>
My directory architecture:
data- |-images- |-train- |-cats |-dogs |-val- |-cats |-dogs
PS:
I found article where same method used and everything seems to work, but not in my case
Advertisement
Answer
your problem is you have the code
train_generator.flow_from_directory( directory=train_dir, target_size=(IMG_WIDTH, IMG_HEIGHT)
You need to change that to
train_generator=train_generator.flow_from_directory( directory=train_dir, target_size=(IMG_WIDTH, IMG_HEIGHT)
do the same for the val_generator. In addition the default class_mode for the ImageDataGenerator is “categorical”. Therefore in model.compile you should specify the loss as ‘categorical_crossentropy’. In your model layer with the 2 nodes the activation function should be ‘softmax’. As an aside I think your model may not perform very well as it may be a bit to simple to process the features of the data. I suggest adding several more convolutional layers with more filters. An example for a more complex model is shown below
model = tf.keras.Sequential([ Conv2D(16, 3, padding='same', activation='relu', input_shape=(IMG_HEIGHT, IMG_WIDTH , 3)), MaxPooling2D(), Conv2D(32, 3, padding='same', activation='relu', input_shape=(IMG_HEIGHT, IMG_WIDTH , 3)), MaxPooling2D(), Conv2D(64, 3, padding='same', activation='relu', input_shape=(IMG_HEIGHT, IMG_WIDTH , 3)), MaxPooling2D(), Conv2D(128, 3, padding='same', activation='relu', input_shape=(IMG_HEIGHT, IMG_WIDTH , 3)), MaxPooling2D(), Flatten(), Dense(128, activation='relu'), Dropout(.3), Dense(64, activation='relu'), Dropout(.3), Dense(2, activation='softmax') ])