我在我的神经网络中错误地标记了我的数据吗?
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)
```
我正在研究在 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)
```