当我更改其属性时,验证生成器的准确性几乎会降低-keras ImageDataGenerator,model.evaluate

时间:2020-10-23 13:29:49

标签: python tensorflow validation keras

我正在从目录层次结构(使用ImageDataGenerator类的生成器的flow_from_directory)读取图像。该模型是固定参数mobilenetv2 +可训练的softmax层。当我使模型适合训练数据时,训练和验证的准确性水平是可比的。如果我使用验证参数或重置生成器,则使用model.evaluate验证验证生成器的准确性会大大降低,或者如果我重新使用model.fit拟合模型,则会大大降低验证生成器的准确性。该数据库是3D视图数据库。 相关代码:

'''

batch_size=16

rescaled3D_gen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1./255, zoom_range=0.2, 
                                                                 shear_range=0.2,  
                                                                 horizontal_flip=True)             

train_gen =rescaled3D_gen.flow_from_directory(data_directory + '/train/', seed=3,
                                              target_size = (pixels, pixels), shuffle=True,
                                              batch_size = batch_size, class_mode='binary')

val_gen =rescaled3D_gen.flow_from_directory(data_directory + '/test/', seed=3,
                                            target_size = (pixels, pixels), shuffle=True,
                                            batch_size = batch_size, class_mode='binary')
#MODEL
inputs = tf.keras.Input(shape=(None, None, 3), batch_size=batch_size)
x = tf.keras.layers.Lambda(lambda img: tf.image.resize(img, (pixels,pixels)))(inputs)
x = tf.keras.layers.Lambda(tf.keras.applications.mobilenet_v2.preprocess_input)(x)

mobilev2 = tf.keras.applications.mobilenet_v2.MobileNetV2(weights = 'imagenet', input_tensor = x,
                                                          input_shape=(pixels,pixels,3),
                                                          include_top=True, pooling = 'avg')
#add a dense layer for task-specific categorization.
full_model = tf.keras.Sequential([mobilev2, 
                                tf.keras.layers.Dense(train_gen.num_classes, activation='softmax')])

for idx, layers in enumerate(mobilev2.layers):
    layers.trainable = False

mobilev2.layers[-1].trainable=True

full_model.compile(optimizer = tf.keras.optimizers.RMSprop(learning_rate=0.0001), 
             loss = 'sparse_categorical_crossentropy',
             metrics=['accuracy'])
#start fitting
val_gen.reset()
train_gen.reset()

full_model.fit(train_gen, 
               steps_per_epoch = samples_per_epoch, 
               epochs=30,
               validation_data=val_gen,
               validation_steps = int(np.floor(val_gen.samples/val_gen.batch_size)))

good_acc_score = full_model.evaluate(val_gen, steps=val_gen.n//val_gen.batch_size)

'''

通过执行以下操作来重现陌生感:

'''

val_gen.batch_size=4
val_gen.reset()
val_gen.batch_size=batch_size

'''

然后,在拟合或评估期间,验证准确性会自动降低(可能是偶然的)

'''

bad_acc_score = full_model.evaluate(val_gen, steps=val_gen.n//val_gen.batch_size)

#or

full_model.fit(train_gen, 
               steps_per_epoch = samples_per_epoch, 
               epochs=1,
               validation_data=val_gen,
               validation_steps = int(np.floor(val_gen.samples/val_gen.batch_size)))

'''

2 个答案:

答案 0 :(得分:0)

我认为该委员会的主要答复解决了我观察到的问题 Keras: Accuracy Drops While Finetuning Inception

答案 1 :(得分:0)

此处提供一些您可以尝试的方法。您可以通过如下更改train_gen来消除Lamda层

rescaled3D_gen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1./255, zoom_range=0.2,shear_range=0.2, horizontal_flip=True,
            preprocessing_function=tf.keras.applications.mobilenet_v2.preprocess_input) 

您不需要Lamda调整大小图层,因为您在目录流中指定了目标大小。 在val_gen中,您有shuffle = True。这将改变每个时期的验证图像顺序。最好将其设置为False以获得一致性。 在移动网络的代码中,您具有include_top = True和pooling ='avg'。当include_top为True时,将忽略合并参数。 设置include_top = True将使模型的顶层具有1000个节点的密集层和softmax激活函数。 我会设置include_top = False。这样,移动网络输出就是一个全局池层,可以直接为您的密集分类层提供数据。在生成器中,设置class_mode ='binary'。但是在model.compile中,您将损失设置为 sparse_categorical_crossentropy。这将起作用,但最好使用loss = BinaryCrossentropy进行编译。 为确保一致性,最好每个时期精确地通过一次验证样本。为此,应选择批大小,以使验证样本/ batch_size为整数,并使用该整数作为验证步骤的数量。 下面的代码将为您做到这一点。

b_max=80 # set this to the maximum batch size you will allow based on memory capacity
length=val_gen.samples       
batch_size=sorted([int(length/n) for n in range(1,length+1) if length % n ==0 and length/n<=b_max],reverse=True)[0]  
val_steps=int(length/batch_size)

更改验证批次大小可以更改验证丢失和准确性的结果。通常,批量越大,损失的波动越小,但可能会导致卡在局部最小值中的可能性更高。尝试这些更改,看看结果差异是否较小。