迁移学习时TensorFlow中的验证和评估指标问题

时间:2020-01-14 12:19:18

标签: python tensorflow machine-learning keras deep-learning

在使用Tensorflow 2.0训练CNN时,我遇到了一些奇怪的行为,希望能为解决它们提供任何帮助。 我正在使用“ tensorflow.keras.applications”中可用的预训练网络进行迁移学习(仅训练分类负责人),并且注意到以下几点:

  1. 在第一个时期,无论我做什么,验证指标始终为零。
  2. 在第一个时期之后进行训练时,训练指标将按您期望的那样改善,但是验证指标本质上是随机猜测,即使将完全相同的数据集用作训练和验证数据集也是如此。就像它没有使用受过训练的模型进行评估一样。

我尝试了VGG16,MobileNetV2和ResNet50V2,它们都表现出相同的行为。

我能够重现的配置是:

  • Ubuntu 18.04LTS,具有驱动程序版本430.50的Nvidia RTX2080ti,CUDA10.0,TensorFlow-gpu == 2.0.0
  • MacBook Pro,TensorFlow == 2.0.0(cpu)

两者都在Conda环境中运行,并且我已经使用pip安装了TensorFlow。我在下面放了一些示例代码来说明我的工作流程的本质,以防万一我做的事情显然很愚蠢。对我的解决方法不知所措,任何帮助将不胜感激。

def parse_function(example_proto):
    image_feature_description = {
        'label': tf.io.FixedLenFeature([], tf.int64),
        'image_raw': tf.io.FixedLenFeature([], tf.string)
    }
    parsed_example = tf.io.parse_single_example(example_proto, image_feature_description)
    image = tf.io.decode_image(
                            parsed_example['image_raw'], 
                            channels = 3, 
                            dtype = tf.float32, 
                            expand_animations = False
                            )
    image = tf.image.per_image_standardization(image)
    label = tf.one_hot(parsed_example['label'], 24, dtype=tf.float32) 
    return (image, label)

def load_dataset(TFRecord_dir, record_name):
    record_files = tf.io.matching_files(os.path.join(TFRecord_dir, record_name + '.tfrecords-????'))
    shards = tf.data.TFRecordDataset(record_files)
    shards = shards.shuffle(tf.cast(tf.shape(record_files)[0], tf.int64))
    dataset = shards.map(map_func=parse_function)
    dataset = dataset.batch(batch_size=16, drop_remainder = True)
    dataset = dataset.prefetch(16)
    return dataset



base_model = tf.keras.applications.ResNet50V2(
                                            input_shape=(224,224,3),
                                            weights='imagenet',
                                            include_top = False
                                            )
base_model.trainable = False

model = tf.keras.Sequential([
        base_model,
        tf.keras.layers.GlobalAveragePooling2D(),
        tf.keras.layers.Dropout(0.5),
        tf.keras.layers.Dense(24, activation = 'softmax')
        ])

model.compile(
    optimizer=tf.keras.optimizers.Adam(),
    loss=tf.keras.losses.CategoricalCrossentropy(),
    metrics=[ 
            tf.keras.metrics.CategoricalAccuracy(),
            tf.keras.metrics.TopKCategoricalAccuracy(),
            tf.keras.metrics.Precision(),
            tf.keras.metrics.Recall()
            ])

train_dataset = load_dataset(train_dir, 'train')

model.fit(train_dataset,
                verbose = 1,
                epochs= 5,
                validation_data = train_dataset)
model.evaluate(train_dataset)

2 个答案:

答案 0 :(得分:0)

在第一个时期之后进行训练时,训练指标会提高 您会期望的,但是验证指标本质上是随机的 猜测,即使将完全相同的数据集用作训练和 验证数据集。就像它没有使用正在训练的模型 进行评估。

这意味着您的网络无法学习所有内容,而只是学习过度。随机猜测意味着您的准确度为1 / n,其中n是类别数。

您可能需要将learning_rate修改为一个较低的值(1e-5),然后再将其冻结一些较低的层(靠近您的GAP + Dropout + Dense)。

答案 1 :(得分:0)

自从开始使用提供的docker镜像以来,我不再遇到此问题。肯定安装了错误的东西,但我不知道该怎么办。

另外,对于处于同一位置的任何人,我在调试过程中发现,如果您像在transfer learning with pre-trained CNN turtorial中一样使用image = (image/127.5) - 1对图像进行规范化,则更改为image = tf.image.per_image_standardization(image),因为它表现出相同的行为,即使在docker容器中,训练指标也会提高,但验证指标在用于训练的同一数据集上将保持随机。