我在我的神经网络中错误地标记了我的数据吗?

Am I mislabeling my data in my neural network?

我正在研究在 Tensorflow 中实现 EfficientNet。我的模型过度拟合并将所有三个 class 预测为一个 class。经过几个时期后,我的训练和验证准确率达到了 99%,我的损失小于 0.5。我在三个 classes (12, 8, 12) 之间有 32,000 张图像。

我的假设是,它与我输入数据的方式有关,并且对标签进行了热编码。可能是不小心把所有的东西都贴上了相同的标签,但我想不通在哪里。

    # 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))

这提供了正确图像和 class 标签的示例:

    # # 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")

这会不会导致标签出现问题?

    # 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)

我的网络:

    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)

如果您使用 labels='inferred',您还应该指定 class_names,这将是您从中获取图像的三个文件夹的名称。

嗯,首先你编写的代码比你需要的多。在 train_ds 和 val_ds 中,您没有指定参数 label_mode。默认设置为 'int'。这意味着您的标签将是整数。如果您使用 loss=tf.keras.losses.SparseCategoricalCrossentropy 编译您的模型,这很好。如果你设置了

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

您确实将标签转换为单热编码,而且似乎已正确完成。但是您可以通过将标签模式设置为分类来避免这样做,如前所述。您还编写了调整图像大小的代码。这不是必需的,因为 tf.keras.utils.image_dataset_from_directory 已为您调整了图像的大小。我无法将您的模型设为 运行,可能是因为我没有 x = img_augmentation(inputs) 的代码。你有代码

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

既然你用的是模型API我觉得应该是

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

注意我包括 pooliing='max' 所以 efficientnet 产生一维张量输出因此你不需要层

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

我还修改了您的代码以生成 test_ds,这样我就可以测试模型的准确性。当然,我使用了不同的数据集,但结果很好。 我的完整代码如下所示

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)
```