Home > database >  Am I mislabeling my data in my neural network?
Am I mislabeling my data in my neural network?

Time:10-08

I'm working on an implementation of EfficientNet in Tensorflow. My model is overfitting and predicting all three classes as just a single class. My training and validation accuracy is in the 99% after a few epochs and my loss is <0.5. I have 32,000 images between the three classes (12, 8, 12).

My hypothesis is that it has to do with the way I input the data and one hot coded the labels. Perhaps it is due to everything being labeled the same accidentally, but I can't figure out where.

    # Load Data
    train_ds = tf.keras.utils.image_dataset_from_directory(
        train_dir,
        labels='inferred',
        seed=42,
        image_size=(height, width),
        batch_size=batch_size
    )
    
    val_ds = tf.keras.utils.image_dataset_from_directory(
        val_dir,
        labels='inferred',
        seed=42,
        image_size=(height, width),
        batch_size=batch_size
    )

    class_names = train_ds.class_names
    num_classes = len(class_names)
    print('There are '   str(num_classes)   ' classes:\n'   str(class_names))
    
    # Resize images
    train_ds = train_ds.map(lambda image, label: (
        tf.image.resize(image, (height, width)), label))
    val_ds = val_ds.map(lambda image, label: (
        tf.image.resize(image, (height, width)), label))

This provides a sample of the correct images and class labels:

    # # Visualization of samples
    # plt.figure(figsize=(10, 10))
    # for images, labels in train_ds.take(1):
    #   for i in range(9):
    #     ax = plt.subplot(3, 3, i   1)
    #     plt.imshow(images[i].numpy().astype("uint8"))
    #     plt.title(class_names[labels[i]])
    #     plt.axis("off")

Could this be causing an issue with labels?

    # Prepare inputs
    # One-hot / categorical encoding
    def input_preprocess(image, label):
        label = tf.one_hot(label, num_classes)
        return image, label
    
    
    train_ds = train_ds.map(input_preprocess,
                            num_parallel_calls=tf.data.AUTOTUNE)
    train_ds = train_ds.prefetch(tf.data.AUTOTUNE)
    
    val_ds = val_ds.map(input_preprocess)

My network:

    def build_model(num_classes):
        inputs = Input(shape=(height, width, 3))
        x = img_augmentation(inputs)
        model = EfficientNetB0(
            include_top=False, input_tensor=x, weights="imagenet")
    
        # Freeze the pretrained weights
        model.trainable = False
    
        # Rebuild top
        x = layers.GlobalAveragePooling2D(name="avg_pool")(model.output)
        x = layers.BatchNormalization()(x)
    
        top_dropout_rate = 0.4
        x = layers.Dropout(top_dropout_rate, name="top_dropout")(x)
        outputs = layers.Dense(num_classes, activation="softmax", name="pred")(x)
    
        # Compile
        model = tf.keras.Model(inputs, outputs, name="EfficientNet")
        optimizer = tf.keras.optimizers.Adam(learning_rate=1e-3)
        model.compile(
            optimizer=optimizer, loss="categorical_crossentropy", metrics=["accuracy"]
        )
        return model
    
    
    with strategy.scope():
        model = build_model(num_classes=num_classes)
    
    epochs = 40
    hist = model.fit(train_ds, epochs=epochs, validation_data=val_ds,
                     workers=6, verbose=1, callbacks=callback)
    plot_hist(hist)

CodePudding user response:

If you use labels='inferred', you should also specify class_names which will be the name of the three folders you're getting images from.

CodePudding user response:

Well first off you are writing more code than you need to. In train_ds and val_ds you did not specify the parameter label_mode. By default it is set to 'int'. Which means your labels will be integers. This is fine if your compile your model using loss=tf.keras.losses.SparseCategoricalCrossentropy. If you had set

label_mode= 'categorical' then you can use loss=tf.keras.losses.CategoricalCrossentropy 

You did convert you labels to one-hot-encoded and that appears to have been done correctly. But you could have avoided having to do that by setting the label mode to categorical as mentioned. You also wrote code to resize the images. This is not necessary since tf.keras.utils.image_dataset_from_directory resized the images for you. I had trouble getting your model to run probably because I don't have the code for x = img_augmentation(inputs). you have the code

model = EfficientNetB0(
            include_top=False, input_tensor=x, weights="imagenet")

Since you are using the model API I think this should be

model = EfficientNetB0( include_top=False, weights="imagenet", pooling='max')(x)

NOTE I included pooliing='max' so efficientnet produces a one dimensional tensor output and thus you do not need the layer

x = layers.GlobalAveragePooling2D(name="avg_pool")(model.output)

I also modified your code to produce a test_ds so I could test the accuracy of the model. Of course I used a different dataset but the results were fine. My complete code is shown below

train_dir=r'../input/beauty-detection-data-set/train'
val_dir=r'../input/beauty-detection-data-set/valid'
batch_size=32
height=224
width=224
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
    train_dir,
    labels='inferred',
    validation_split=0.1,
    subset="training",
    label_mode='categorical',
    seed=42,
    image_size=(height, width),
    batch_size=batch_size
)
test_ds = tf.keras.preprocessing.image_dataset_from_directory(
    train_dir,
    labels='inferred',
    validation_split=0.1,
    subset="validation",
    label_mode='categorical',
    seed=42,
    image_size=(height, width),
    batch_size=batch_size)


val_ds = tf.keras.preprocessing.image_dataset_from_directory(
    val_dir,
    labels='inferred',
    seed=42,
    label_mode='categorical',
    image_size=(height, width),
    batch_size=batch_size
)
class_names = train_ds.class_names
num_classes = len(class_names)
print('There are '   str(num_classes)   ' classes:\n'   str(class_names))
img_shape=(224,224,3)
base_model=tf.keras.applications.EfficientNetB3(include_top=False, weights="imagenet",input_shape=img_shape, pooling='max') 
x=base_model.output
x=keras.layers.BatchNormalization(axis=-1, momentum=0.99, epsilon=0.001 )(x)
x = Dense(256, kernel_regularizer = regularizers.l2(l = 0.016),activity_regularizer=regularizers.l1(0.006),
                bias_regularizer=regularizers.l1(0.006) ,activation='relu')(x)
x=Dropout(rate=.45, seed=123)(x)        
output=Dense(num_classes, activation='softmax')(x)
model=Model(inputs=base_model.input, outputs=output)
model.compile(Adamax(lr=.001), loss='categorical_crossentropy', metrics=['accuracy']) 
epochs =5
hist = model.fit(train_ds, epochs=epochs, validation_data=val_ds,
                  verbose=1)
accuracy =model.evaluate(test_ds, verbose=1)[1]
print (accuracy)
```




  • Related