Search code examples
kerasdeep-learningtensorflow2.0tf.kerastensorflow-datasets

Tensorflow: Cannot train neural network due to the ValueError: slice index 0 of dimension 0 out of bounds error


I'm precticing building neural networks, but I keep getting stuck on the training of the NN.

This time I wanted to do Intel Image Classification from (Kaggle).

I'm using tensorflow 2.12 in WSL.

Imports, labels, datapaths:


import tensorflow as tf
import os
from tqdm import tqdm
import numpy as np

# Labels
labels = ["buildings", "forest", "glacier", "mountain", "sea", "street"]

# Data directories
train_data = os.path.join(os.getcwd(), "data", "seg_train", "seg_train")
test_data = os.path.join(os.getcwd(), "data", "seg_test", "seg_test")

# Shape of the input data (needs color channel as last dimension)
data_shape = (150, 150, 3)

# Set up filepath dictionary
train_dirs = {}
test_dirs = {}

for label in labels:
    train_dirs[label] = os.path.join(train_data, label)
    test_dirs[label] = os.path.join(test_data, label)

Helper functions to process the data:


# Prepare list of files with asociated labels and remove files that have size other than desired data_shape

def remove_bad_data(dirs_dict):
    
    indexed_files = []
    
    for idx, directory in enumerate(dirs_dict):
        listfiles = os.listdir(dirs_dict[directory])
        
        for file in listfiles:
            image_path = os.path.join(dirs_dict[directory], file)
            image = tf.io.read_file(image_path)
            image = tf.io.decode_image(image, channels=data_shape[-1])
            
            if image.shape == data_shape:
                indexed_files.append((image_path, idx))
            else:
                os.remove(image_path)
                print(f"Removed file with shape {image.shape} located at: {image_path}")
            
    return indexed_files

# Define image preprocessing function
def preprocess_images(image_path, label):
    
    image = tf.io.read_file(image_path)
    image = tf.io.decode_image(image, channels=data_shape[-1])/255
    
    return (image, label)

# Define dataset pipeline function
def dataset_pipeline(dataset):
    
    dataset = dataset.map(map_func=preprocess_images)
    dataset = dataset.cache()
    dataset = dataset.shuffle(buffer_size=len(dataset))
    dataset = dataset.prefetch(buffer_size=tf.data.AUTOTUNE)
    
    return dataset

Creating dataset

train_files = remove_bad_data(train_dirs)
test_files = remove_bad_data(test_dirs)

# Create a dataset
train_files = np.array(train_files)
train_dataset = tf.data.Dataset.from_tensor_slices((train_files[:,0].astype(str), train_files[:,1].astype(int)))
train_dataset = dataset_pipeline(dataset=train_dataset)

at this point, the train_dataset.as_numpy_iterator().next() returns a tuple of (150, 150, 3) array and a label (int 0 to 6).

# Define the model architecture 
input_layer = tf.keras.Input(shape=data_shape, name="input_layer")

conv_layer = tf.keras.layers.Conv2D(filters=16, kernel_size=3, padding="same", activation="relu", name="first_conv2d")(input_layer)
maxpool_layer = tf.keras.layers.MaxPool2D(name="first_maxpool")(conv_layer)
conv_layer = tf.keras.layers.Conv2D(filters=32, kernel_size=3, padding="same", activation="relu", name="second_conv2d")(maxpool_layer)
maxpool_layer = tf.keras.layers.MaxPool2D(name="second_maxpool")(conv_layer)
conv_layer = tf.keras.layers.Conv2D(filters=64, kernel_size=3, padding="same", activation="relu", name="third_conv2d")(maxpool_layer)
maxpool_layer = tf.keras.layers.MaxPool2D(name="third_maxpool")(conv_layer)
conv_layer = tf.keras.layers.Conv2D(filters=128, kernel_size=3, padding="same", activation="relu", name="fourth_conv2d")(maxpool_layer)
maxpool_layer = tf.keras.layers.MaxPool2D(name="fourth_maxpool")(conv_layer)

flatten_layer = tf.keras.layers.Flatten(name="flatten_layer")(maxpool_layer)
dense_layer = tf.keras.layers.Dense(units=128, activation="relu")(flatten_layer)

output_layer = tf.keras.layers.Dense(units=len(labels), name="output_layer")(dense_layer)

# Initialize model
model = tf.keras.Model(inputs=input_layer, outputs=output_layer, name="intel_classification")
model.compile(optimizer='adam', loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), metrics=['accuracy'])
tf.keras.utils.plot_model(model, "model.png", show_shapes=True)


history = model.fit(train_dataset)

When i try to train the model, I keep getting this error:

ValueError: slice index 0 of dimension 0 out of bounds. for '{{node strided_slice}} = StridedSlice[Index=DT_INT32, T=DT_INT32, begin_mask=0, ellipsis_mask=0, end_mask=0, new_axis_mask=0, shrink_axis_mask=1](Shape, strided_slice/stack, strided_slice/stack_1, strided_slice/stack_2)' with input shapes: [0], [1], [1], [1] and with computed input tensors: input[1] = <0>, input[2] = <1>, input[3] = <1>.

I tried changing the loss function to CategoricalCrossentropy() but then I encounter another error:


2023-04-18 15:25:56.800730: I tensorflow/core/common_runtime/executor.cc:1197] [/device:CPU:0] (DEBUG INFO) Executor start aborting (this does not indicate an error and you can ignore this message): INVALID_ARGUMENT: You must feed a value for placeholder tensor 'Placeholder/_1' with dtype int64 and shape [13986]
         [[{{node Placeholder/_1}}]]
2023-04-18 15:25:56.800956: I tensorflow/core/common_runtime/executor.cc:1197] [/device:CPU:0] (DEBUG INFO) Executor start aborting (this does not indicate an error and you can ignore this message): INVALID_ARGUMENT: You must feed a value for placeholder tensor 'Placeholder/_1' with dtype int64 and shape [13986]
         [[{{node Placeholder/_1}}]]
Traceback (most recent call last):
  File "/home/jw/projects/testmodels/main.py", line 109, in <module>
    history = model.fit(train_dataset)
  File "/home/jw/projects/testmodels/venv/lib/python3.10/site-packages/keras/utils/traceback_utils.py", line 70, in error_handler
    raise e.with_traceback(filtered_tb) from None
  File "/tmp/__autograph_generated_file7w1vt_rv.py", line 15, in tf__train_function
    retval_ = ag__.converted_call(ag__.ld(step_function), (ag__.ld(self), ag__.ld(iterator)), None, fscope)
ValueError: in user code:

    File "/home/jw/projects/testmodels/venv/lib/python3.10/site-packages/keras/engine/training.py", line 1284, in train_function  *
        return step_function(self, iterator)
    File "/home/jw/projects/testmodels/venv/lib/python3.10/site-packages/keras/engine/training.py", line 1268, in step_function  **
        outputs = model.distribute_strategy.run(run_step, args=(data,))
    File "/home/jw/projects/testmodels/venv/lib/python3.10/site-packages/keras/engine/training.py", line 1249, in run_step  **
        outputs = model.train_step(data)
    File "/home/jw/projects/testmodels/venv/lib/python3.10/site-packages/keras/engine/training.py", line 1051, in train_step
        loss = self.compute_loss(x, y, y_pred, sample_weight)
    File "/home/jw/projects/testmodels/venv/lib/python3.10/site-packages/keras/engine/training.py", line 1109, in compute_loss
        return self.compiled_loss(
    File "/home/jw/projects/testmodels/venv/lib/python3.10/site-packages/keras/engine/compile_utils.py", line 265, in __call__
        loss_value = loss_obj(y_t, y_p, sample_weight=sw)
    File "/home/jw/projects/testmodels/venv/lib/python3.10/site-packages/keras/losses.py", line 142, in __call__
        losses = call_fn(y_true, y_pred)
    File "/home/jw/projects/testmodels/venv/lib/python3.10/site-packages/keras/losses.py", line 268, in call  **
        return ag_fn(y_true, y_pred, **self._fn_kwargs)
    File "/home/jw/projects/testmodels/venv/lib/python3.10/site-packages/keras/losses.py", line 1984, in categorical_crossentropy
        return backend.categorical_crossentropy(
    File "/home/jw/projects/testmodels/venv/lib/python3.10/site-packages/keras/backend.py", line 5559, in categorical_crossentropy
        target.shape.assert_is_compatible_with(output.shape)

    ValueError: Shapes () and (None, 6) are incompatible

Solution

  • You forgot to batch the dataset.

    BATCHSIZE = 32
    def dataset_pipeline(dataset):
        
        dataset = dataset.map(map_func=preprocess_images)
        dataset = dataset.cache()
        dataset = dataset.shuffle(buffer_size=len(dataset))
        dataset = dataset.prefetch(buffer_size=tf.data.AUTOTUNE)
        dataset = dataset.batch(BATCHSIZE) # you need to add this
        
        return dataset
    

    You are supposed to pass tensor of size (batch_size, 150, 150, 3) to the model.fit method.