选择Tensorflow模型的损失函数和评估指标

我正在尝试进行迁移学习,使用预训练的Xception模型并添加一个新的分类器。

这是我的模型:

base_model = keras.applications.Xception(    weights="imagenet",    input_shape=(224,224,3),    include_top=False)

我使用的数据集是oxford_flowers102,直接从tensorflow数据集中获取。这是数据集页面。

我在选择一些参数时遇到了问题 – 要么训练准确率显示出可疑的低值,要么出现错误。

我需要帮助来指定这些参数,适用于这个(oxford_flowers102)数据集:

  1. 为分类器添加新的全连接层。我尝试使用:outputs = keras.layers.Dense(102, activation='softmax')(x),我不知道是否应该在这里选择激活函数。
  2. 模型的损失函数。
  3. 评估指标。

我尝试过:

model.compile(    optimizer=keras.optimizers.Adam(),    loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),    metrics=[keras.metrics.Accuracy()],)

我不确定应该选择SparseCategoricalCrossentropy还是CategoricalCrossentropy,以及from_logits参数的用法?

我也不确定在评估指标中是应该选择keras.metrics.Accuracy()还是keras.metrics.CategoricalAccuracy()

我确实缺乏一些理论知识,但现在我只需要让它工作。期待您的回答!


回答:

关于数据集:oxford_flowers102

该数据集被分为训练集验证集测试集。训练集和验证集各包含每个类别的10张图片(共1020张图片)。测试集包含剩余的6149张图片(每个类别至少20张)。

'test'        6,149'train'       1,020'validation'  1,020

如果我们检查,会看到

import tensorflow_datasets as tfdstfds.disable_progress_bar()data, ds_info = tfds.load('oxford_flowers102',                           with_info=True, as_supervised=True)train_ds, valid_ds, test_ds = data['train'], data['validation'], data['test']for i, data in enumerate(train_ds.take(3)):  print(i+1, data[0].shape, data[1])1 (500, 667, 3) tf.Tensor(72, shape=(), dtype=int64)2 (500, 666, 3) tf.Tensor(84, shape=(), dtype=int64)3 (670, 500, 3) tf.Tensor(70, shape=(), dtype=int64)
ds_info.features["label"].num_classes102

所以,它有102个类别或分类,目标是以整数形式给出,输入形状各不相同。

澄清

首先,如果你保留这个整数目标或标签,你应该使用sparse_categorical_accuracy来计算准确率,并使用sparse_categorical_crossentropy作为损失函数。但如果你将整数标签转换为独热编码向量,那么你应该使用categorical_accuracy来计算准确率,并使用categorical_crossentropy作为损失函数。由于这些数据集有整数标签,你可以选择sparse_categorical,或者你可以将标签转换为独热编码以使用categorical

其次,如果你将最后一层的输出设置为outputs = keras.layers.Dense(102, activation='softmax')(x),你将获得概率分数。但如果你设置为outputs = keras.layers.Dense(102)(x),那么你将获得logits。因此,如果你设置了activations='softmax',那么你不应该使用from_logit = True。例如,在你上面的代码中,你应该按如下方式做(这里有一些理论供你参考):

...(a)# 使用softmax激活函数(无logits输出)outputs = keras.layers.Dense(102, activation='softmax')(x)...model.compile(    optimizer=keras.optimizers.Adam(),    loss=keras.losses.SparseCategoricalCrossentropy(from_logits=False),    metrics=[keras.metrics.Accuracy()],)or,(b)# 无激活函数,输出将是logitsoutputs = keras.layers.Dense(102)(x)...model.compile(    optimizer=keras.optimizers.Adam(),    loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),    metrics=[keras.metrics.Accuracy()],)

第三使用字符串标识符,例如metrics=['acc'] , optimizer='adam'。但在你的情况下,你需要更具体,因为你提到了特定的损失函数。因此,代替keras.metrics.Accuracy(),你应该选择keras.metrics.SparseCategoricalAccuracy()如果你的目标是整数,或者选择keras.metrics.CategoricalAccuracy()如果你的目标是独热编码向量

代码示例

这是一个端到端的示例。注意,我将将整数标签转换为独热编码向量(目前,这对我来说只是偏好问题)。此外,我希望从最后一层获得概率(而不是logits),这意味着from_logits = False。对于所有这些,我需要在训练中选择以下参数:

# 使用softmax获取概率 outputs = keras.layers.Dense(102,                    activation='softmax')(x)# 因此没有logits,设置为false(顺便说一下,默认情况下它已经是false)loss = keras.losses.CategoricalCrossentropy(from_logits=False),# 正确指定评估指标 metrics = keras.metrics.CategoricalAccuracy(),

让我们完成整个代码。

import tensorflow_datasets as tfdstfds.disable_progress_bar()data, ds_info = tfds.load('oxford_flowers102',                          with_info=True, as_supervised=True)train_ds, valid_ds, test_ds = data['train'], data['validation'], data['test']NUM_CLASSES = ds_info.features["label"].num_classestrain_size =  len(data['train'])batch_size = 64img_size = 120 

预处理和增强

import tensorflow as tf # 预处理函数 def normalize_resize(image, label):    image = tf.cast(image, tf.float32)    image = tf.divide(image, 255)    image = tf.image.resize(image, (img_size, img_size))    label = tf.one_hot(label , depth=NUM_CLASSES) # 整数转换为独热编码    return image, label# 增强函数 def augment(image, label):    image = tf.image.random_flip_left_right(image)    return image, label train = train_ds.map(normalize_resize).cache().map(augment).shuffle(100).\                          batch(batch_size).repeat()valid = valid_ds.map(normalize_resize).cache().batch(batch_size)test = test_ds.map(normalize_resize).cache().batch(batch_size)

模型

from tensorflow import keras base_model = keras.applications.Xception(    weights='imagenet',      input_shape=(img_size, img_size, 3),    include_top=False)  base_model.trainable = Falseinputs = keras.Input(shape=(img_size, img_size, 3))x = base_model(inputs, training=False)x = keras.layers.GlobalAveragePooling2D()(x)outputs = keras.layers.Dense(NUM_CLASSES, activation='softmax')(x)model = keras.Model(inputs, outputs)

好的,此外,我还想使用两个评估指标来计算top-1top-3准确率。

model.compile(optimizer=keras.optimizers.Adam(),              loss=keras.losses.CategoricalCrossentropy(),              metrics=[                       keras.metrics.TopKCategoricalAccuracy(k=3, name='acc_top3'),                       keras.metrics.TopKCategoricalAccuracy(k=1, name='acc_top1')                    ])model.fit(train, steps_per_epoch=train_size // batch_size,          epochs=20, validation_data=valid, verbose=2)
...Epoch 19/2015/15 - 2s - loss: 0.2808 - acc_top3: 0.9979 - acc_top1: 0.9917 - val_loss: 1.5025 - val_acc_top3: 0.8147 - val_acc_top1: 0.6186Epoch 20/2015/15 - 2s - loss: 0.2743 - acc_top3: 0.9990 - acc_top1: 0.9885 - val_loss: 1.4948 - val_acc_top3: 0.8147 - val_acc_top1: 0.6255

评估

# 在测试集上评估 model.evaluate(test, verbose=2)97/97 - 18s - loss: 1.6482 - acc_top3: 0.7733 - acc_top1: 0.5994[1.648208498954773, 0.7732964754104614, 0.5994470715522766]

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注