Keras模型精度高但val_acc低

Ben*_*lau 5 python deep-learning keras tensorflow

我正在使用 Oxford-IIIT 宠物数据集的 resnet50 迁移学习来对 37 个品种的猫和狗进行分类。这个想法是使用 Keras 代码密切关注 fastai 的实现。然而,我设法获得了高达 90% 的训练准确率,但似乎无法将我的 val_accuracy 提高到高于随机猜测(1/37 或 ~ 3% val_acc)。

知道 Keras 如何计算验证 acc 以及如何改进它?还是我的预处理步骤有问题?多谢。

为了获得验证步骤,我使用 sklearn StratifiedShuffleSplit 来获得平衡的验证集。

# Create dataframe with labels and filenames
annotations = pd.read_csv("annotation/list.txt",header=None,delim_whitespace=True)

annotations.drop([1,2,3],axis=1, inplace=True)
annotations.columns = ["filenames"]

# Create label columns
trans = str.maketrans("_0123456789","           ")
annotations["labels"] = annotations["filenames"].str.translate(trans).str.strip()
annotations["filenames"] = annotations["filenames"] +".jpg" 

Run Code Online (Sandbox Code Playgroud)
# Creating a validation set
from sklearn.model_selection import StratifiedShuffleSplit

df_array = annotations.to_numpy(copy=True)

sss = StratifiedShuffleSplit(n_splits = 1, test_size=0.2)

valid_idx = [test for _,test in sss.split(df_array[:,0],df_array[:,1])]

validation = annotations.iloc[valid_idx[0]]
annotations.drop(valid_idx[0], inplace=True)
Run Code Online (Sandbox Code Playgroud)

然后,构建我的生成器并训练我的模型。

from tensorflow.keras.preprocessing.image import ImageDataGenerator

bs = 64

def normalize(x):
  imagenet_mean = np.array([0.485, 0.456, 0.406]).reshape(1,1,3)
  imagenet_sd = np.array([0.229, 0.224, 0.225]).reshape(1,1,3)
  return (x- imagenet_mean)/imagenet_sd



train_datagen = ImageDataGenerator(rescale=1/255.,
                                  horizontal_flip = True,
                                  rotation_range=10,
                                  width_shift_range = 0.1,
                                  height_shift_range =0.1,
                                  brightness_range =(0.9,1.1),
                                  shear_range =0.1,
                                  preprocessing_function=normalize)

train_generator = train_datagen.flow_from_dataframe(dataframe=annotations,
                                                   directory =os.getcwd(),
                                                   x_col="filenames",
                                                   y_col="labels",
                                                   target_size = (224,224),
                                                   batch_size = bs,
                                                   )


val_datagen = ImageDataGenerator(rescale=1/255.,
                                preprocessing_function=normalize)

validation_generator = val_datagen.flow_from_dataframe(dataframe=validation,
                                                   directory =os.getcwd(),
                                                   x_col="filenames",
                                                   y_col="labels",
                                                   target_size = (224,224),
                                                   batch_size=bs,
                                                   )


from tensorflow.keras.applications.resnet50 import ResNet50
from tensorflow.keras import optimizers
from tensorflow.keras import Model
from tensorflow.keras.layers import Dense, GlobalAveragePooling2D, Flatten, BatchNormalization, Dropout


base_model = ResNet50(include_top=False,weights="imagenet")
x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Flatten()(x)
x = BatchNormalization(epsilon=1e-05,momentum=0.1)(x)
x = Dropout(0.25)(x)
x = Dense(512,activation="relu")(x)
x = BatchNormalization(epsilon=1e-05,momentum=0.1)(x)
x = Dropout(0.5)(x)
predictions = Dense(37,activation="softmax")(x)

model = Model(inputs=base_model.input,outputs=predictions)

for layer in base_model.layers:
    layer.trainable = False

lr= 0.001
opti = optimizers.Adam(lr=lr, decay=lr/50)
model.compile(optimizer=opti,
             loss="categorical_crossentropy",
             metrics=["accuracy"])

model.fit_generator(train_generator,
                   epochs=10,
                   validation_data = validation_generator)

for layer in base_model.layers:
    layer.trainable = True

model.fit_generator(train_generator,
                   epochs=10,
                   validation_data = validation_generator)

Run Code Online (Sandbox Code Playgroud)
By the 10 epochs before unfreezing my layers

loss = 0.2189
acc = 0.9255
val_loss = 5.5082
val_acc = 0.0401
Run Code Online (Sandbox Code Playgroud)