pythonconv-neural-networktensorflow2.0

Validation Data in CNN model is causing AttributeError: 'NoneType' object has no attribute 'items'


I am following a course on machine learning and am making a CNN model with the cats and dogs data from Kaggle.

When I fit the model with a validation generator as validation data, the model will run for one full epoch, a second failed epoch and stops at the third epoch with error:

line 2 AttributeError: 'NoneType' object has no attribute 'items'

The code I wrote is almost exactly as in the video but, the video is from 2019 so I had to make some adjustments:

I would like to understand what is causing this error.

As far as I have been able to figure out, the issue has something to do with the validation_generator / validation_data parameter:

These two options will make the model run to completion but, still alternate between a full epoch and a failed epoch with 0 value and 0 loss.

I have also tried changing the loss and optimizer in compile(), as well as change the output layer.

This is my full code, python 3.11, tensorflow 2.16.1:

import numpy as np
import pandas as pd
%matplotlib inline
import matplotlib as mpl
import matplotlib.pyplot as plt
import os
import tensorflow as tf
# from tensorflow import keras
from tensorflow.keras.preprocessing.image import ImageDataGenerator


# Source files https://drive.google.com/file/d/16AlwTDOeyFaiP3RPxKOk5s80IycK80X4/view

# set Train/Test/Validation locations
main_dir = '/home/_/VSCode/Python/udemy/Data Files/cats_and_dogs'
train_dir = main_dir + '/train'
test_dir = main_dir +'/test'
validation_dir = main_dir + '/validation'


# Create Generator objects and rescale
train_datagen = ImageDataGenerator(rescale=1./255)
test_datagen = ImageDataGenerator(rescale=1./255)


# Create generators:
train_generator = train_datagen.flow_from_directory(
    train_dir,
    target_size = (150, 150),
    batch_size = 20,
    class_mode = 'binary',
    color_mode = 'rgb'
)

validation_generator = test_datagen.flow_from_directory(
    validation_dir,
    target_size = (150, 150),
    batch_size = 10,
    class_mode = 'binary',
    color_mode = 'rgb'
)

# Test validation generator (works)
for data_batch, labels_batch in validation_generator:
    print('Data batch shape:', data_batch.shape)
    print('Labels batch shape:', labels_batch.shape)
    break


model = tf.keras.Sequential()
model.add(tf.keras.layers.Input(shape=(150, 150, 3)))


# Create 4 Convolutional layers and pooling layers
model.add(tf.keras.layers.Conv2D(32, (3,3), activation='relu'))
model.add(tf.keras.layers.MaxPooling2D((2, 2)))

model.add(tf.keras.layers.Conv2D(64, (3,3), activation='relu'))
model.add(tf.keras.layers.MaxPooling2D((2, 2)))

model.add(tf.keras.layers.Conv2D(128, (3,3), activation='relu'))
model.add(tf.keras.layers.MaxPooling2D((2, 2)))

model.add(tf.keras.layers.Conv2D(256, (3,3), activation='relu'))
model.add(tf.keras.layers.MaxPooling2D((2, 2)))


# Flatten and Dense layers
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(512, activation='relu'))
model.add(tf.keras.layers.Dense(1, activation='sigmoid'))


# Compile the model
model.compile(loss='binary_crossentropy',
              optimizer = tf.keras.optimizers.RMSprop(learning_rate=1e-4),
              metrics = ['accuracy'])


2024-06-10 14:56:36.689735: I external/local_tsl/tsl/cuda/cudart_stub.cc:32] Could not find cuda drivers on your machine, GPU will not be used.
2024-06-10 14:56:37.069020: I external/local_tsl/tsl/cuda/cudart_stub.cc:32] Could not find cuda drivers on your machine, GPU will not be used.
2024-06-10 14:56:41.409236: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:38] TF-TRT Warning: Could not find TensorRT
Found 2000 images belonging to 2 classes.
Found 1000 images belonging to 2 classes.

# Fit the model -> validation_data on, validation_steps 50 (batch_size = 10)

model_history2 = model.fit(
    x = train_generator,
    steps_per_epoch = 100,
    epochs = 20,
    validation_data = validation_generator,
    validation_steps = 50

)

The output:

Epoch 1/20
/home/user/.local/share/virtualenvs/udemy-B00hqPiI/lib/python3.11/site-packages/keras/src/trainers/data_adapters/py_dataset_adapter.py:121: UserWarning: Your `PyDataset` class should call `super().__init__(**kwargs)` in its constructor. `**kwargs` can include `workers`, `use_multiprocessing`, `max_queue_size`. Do not pass these arguments to `fit()`, as they will be ignored.
  self._warn_if_super_not_called()
100/100 ━━━━━━━━━━━━━━━━━━━━ 143s 1s/step - accuracy: 0.5086 - loss: 0.6935 - val_accuracy: 0.5380 - val_loss: 0.6850
Epoch 2/20
2024-06-09 22:15:15.482783: W tensorflow/core/framework/local_rendezvous.cc:404] Local rendezvous is aborting with status: OUT_OF_RANGE: End of sequence
     [[{{node IteratorGetNext}}]]
/usr/lib/python3.11/contextlib.py:155: UserWarning: Your input ran out of data; interrupting training. Make sure that your dataset or generator can generate at least `steps_per_epoch * epochs` batches. You may need to use the `.repeat()` function when building your dataset.
  self.gen.throw(typ, value, traceback)
100/100 ━━━━━━━━━━━━━━━━━━━━ 9s 93ms/step - accuracy: 0.0000e+00 - loss: 0.0000e+00 - val_accuracy: 0.5480 - val_loss: 0.6847
Epoch 3/20
100/100 ━━━━━━━━━━━━━━━━━━━━ 0s 1s/step - accuracy: 0.5600 - loss: 0.6801
2024-06-09 22:18:25.040161: W tensorflow/core/framework/local_rendezvous.cc:404] Local rendezvous is aborting with status: OUT_OF_RANGE: End of sequence
     [[{{node IteratorGetNext}}]]
line 2 AttributeError: 'NoneType' object has no attribute 'items'




Full error report:


line 2 AttributeError: 'NoneType' object has no attribute 'items'
Hide Details
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[4], line 2
      1 # Fit the model
----> 2 model_history2 = model.fit(
      3     x = train_generator,
      4     steps_per_epoch = 100,
      5     epochs = 20,
      6     validation_data = validation_generator,
      7     validation_steps = 50
      8 
      9 )

File ~/.local/share/virtualenvs/udemy-B00hqPiI/lib/python3.11/site-packages/keras/src/utils/traceback_utils.py:122, in filter_traceback.<locals>.error_handler(*args, **kwargs)
    119     filtered_tb = _process_traceback_frames(e.__traceback__)
    120     # To get the full stack trace, call:
    121     # `keras.config.disable_traceback_filtering()`
--> 122     raise e.with_traceback(filtered_tb) from None
    123 finally:
    124     del filtered_tb

File ~/.local/share/virtualenvs/udemy-B00hqPiI/lib/python3.11/site-packages/keras/src/backend/tensorflow/trainer.py:350, in TensorFlowTrainer.fit(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_batch_size, validation_freq)
    329         self._eval_epoch_iterator = TFEpochIterator(
    330             x=val_x,
    331             y=val_y,
   (...)
    337             shuffle=False,
    338         )
    339     val_logs = self.evaluate(
    340         x=val_x,
    341         y=val_y,
   (...)
    347         _use_cached_eval_dataset=True,
    348     )
    349     val_logs = {
--> 350         "val_" + name: val for name, val in val_logs.items()
    351     }
    352     epoch_logs.update(val_logs)
    354 callbacks.on_epoch_end(epoch, epoch_logs)

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

Solution

  • You could use validation_batch_size instead of validation_steps to solve the problem.