为什么我的模型在使用 tf.data 加载数据时准确率很低?
Why is my model giving poor accuracy when the data is loaded using tf.data?
我是 tf.data API 的新手,并试图在 Dogs vs. Cats Redux: Kernels Edition Kaggle 竞赛中使用它从磁盘加载图像。为此,我首先创建了一个名为 train_df 的 pandas DataFrame,其中包含两列 - file_path包含目标标签 0(对于猫)和 1(对于狗)的图像和 target 的相对路径。 DataFrame 的前 10 行如下所示:
然后,我尝试使用以下代码加载图像:
import tensorflow as tf
BATCH_SIZE = 128
IMG_HEIGHT = 224
IMG_WIDTH = 224
def read_images(X, y):
X = tf.io.read_file(X)
X = tf.io.decode_image(X, expand_animations=False, dtype=tf.float32, channels=3)
X = tf.image.resize(X, [IMG_HEIGHT, IMG_WIDTH])
X = tf.keras.applications.efficientnet.preprocess_input(X, data_format="channels_last")
return (X, y)
def build_data_pipeline(X, y):
data = tf.data.Dataset.from_tensor_slices((X, y))
data = data.map(read_images)
data = data.batch(BATCH_SIZE)
data = data.prefetch(tf.data.AUTOTUNE)
return data
tf_data = build_data_pipeline(train_df["file_path"], train_df["target"])
在此之后,我尝试使用以下代码训练我的模型
model.fit(tf_data, epochs=10)
但训练准确率仅为 50%,而使用 ImageDataGenerator,我获得的准确率为 99%。因此,问题出在我无法找到的数据加载部分。
我使用了 EfficientNetB0,其权重从 imagenet 训练为特征提取器,最后使用单个神经元层作为分类器。
预训练 EfficientNetB0 模型:
pretrained_model = tf.keras.applications.EfficientNetB0(
input_shape=(IMG_HEIGHT, IMG_WIDTH, 3),
include_top=False,
weights="imagenet"
)
for layer in pretrained_model.layers:
layer.trainable = False
EfficientNetB0 末尾有一个神经元的密集层:
pretrained_output = pretrained_model.get_layer('top_activation').output
x = tf.keras.layers.GlobalAveragePooling2D()(pretrained_output)
x = tf.keras.layers.BatchNormalization()(x)
x = tf.keras.layers.Dense(1, activation="sigmoid")(x)
model = tf.keras.models.Model(pretrained_model.input, x)
编译模型:
model.compile(
optimizer="adam",
loss="binary_crossentropy",
metrics=["accuracy"]
)
在上面notebook中,将输入读取函数read_images
改成如下:
def read_images(X, y):
X = tf.io.read_file(X)
X = tf.image.decode_jpeg(X, channels = 3)
X = tf.image.resize(X, [IMG_HEIGHT, IMG_WIDTH]) #/255.0
return (X, y)
另请注意,tf.keras.applications.EfficientNet-Bx
有 in-built normalization 层。所以,最好不要在上面的函数中对数据进行归一化(即/255.0
)。
我是 tf.data API 的新手,并试图在 Dogs vs. Cats Redux: Kernels Edition Kaggle 竞赛中使用它从磁盘加载图像。为此,我首先创建了一个名为 train_df 的 pandas DataFrame,其中包含两列 - file_path包含目标标签 0(对于猫)和 1(对于狗)的图像和 target 的相对路径。 DataFrame 的前 10 行如下所示:
然后,我尝试使用以下代码加载图像:
import tensorflow as tf
BATCH_SIZE = 128
IMG_HEIGHT = 224
IMG_WIDTH = 224
def read_images(X, y):
X = tf.io.read_file(X)
X = tf.io.decode_image(X, expand_animations=False, dtype=tf.float32, channels=3)
X = tf.image.resize(X, [IMG_HEIGHT, IMG_WIDTH])
X = tf.keras.applications.efficientnet.preprocess_input(X, data_format="channels_last")
return (X, y)
def build_data_pipeline(X, y):
data = tf.data.Dataset.from_tensor_slices((X, y))
data = data.map(read_images)
data = data.batch(BATCH_SIZE)
data = data.prefetch(tf.data.AUTOTUNE)
return data
tf_data = build_data_pipeline(train_df["file_path"], train_df["target"])
在此之后,我尝试使用以下代码训练我的模型
model.fit(tf_data, epochs=10)
但训练准确率仅为 50%,而使用 ImageDataGenerator,我获得的准确率为 99%。因此,问题出在我无法找到的数据加载部分。
我使用了 EfficientNetB0,其权重从 imagenet 训练为特征提取器,最后使用单个神经元层作为分类器。
预训练 EfficientNetB0 模型:
pretrained_model = tf.keras.applications.EfficientNetB0(
input_shape=(IMG_HEIGHT, IMG_WIDTH, 3),
include_top=False,
weights="imagenet"
)
for layer in pretrained_model.layers:
layer.trainable = False
EfficientNetB0 末尾有一个神经元的密集层:
pretrained_output = pretrained_model.get_layer('top_activation').output
x = tf.keras.layers.GlobalAveragePooling2D()(pretrained_output)
x = tf.keras.layers.BatchNormalization()(x)
x = tf.keras.layers.Dense(1, activation="sigmoid")(x)
model = tf.keras.models.Model(pretrained_model.input, x)
编译模型:
model.compile(
optimizer="adam",
loss="binary_crossentropy",
metrics=["accuracy"]
)
在上面notebook中,将输入读取函数read_images
改成如下:
def read_images(X, y):
X = tf.io.read_file(X)
X = tf.image.decode_jpeg(X, channels = 3)
X = tf.image.resize(X, [IMG_HEIGHT, IMG_WIDTH]) #/255.0
return (X, y)
另请注意,tf.keras.applications.EfficientNet-Bx
有 in-built normalization 层。所以,最好不要在上面的函数中对数据进行归一化(即/255.0
)。