为 Tensorflow 模型选择损失和指标
Selecting loss and metrics for Tensorflow model
我正在尝试使用预训练的 Xception 模型和新添加的分类器进行迁移学习。
这是型号:
base_model = keras.applications.Xception(
weights="imagenet",
input_shape=(224,224,3),
include_top=False
)
我使用的数据集 oxford_flowers102
直接取自 tensorflow 数据集。
This 是一个数据集页面。
我在 select 一些参数 时遇到问题 - 要么训练精度显示可疑的低值,要么存在错误。
我需要帮助指定此参数,对于此 (oxford_flowers102) 数据集:
- 为分类器新增了密集层。我正在尝试:
outputs = keras.layers.Dense(102, activation='softmax')(x)
我不确定我是否应该 select 激活函数。
- 模型的损失函数。
- 指标。
我试过了:
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 个图像组成,每个 class 个图像(每个总计 1020 个图像)。测试集由剩余的 6149 张图像组成(每个 class 最少 20)。
'test' 6,149
'train' 1,020
'validation' 1,020
如果我们检查,我们会看到
import tensorflow_datasets as tfds
tfds.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_classes
102
因此,它有 102 个类别或 class 个类别,并且目标带有一个具有不同形状输入的 整数 。
澄清
首先,如果你保留这个整数目标或标签,你应该使用sparse_categorical_accuracy
for accuracy and sparse_categorical_crossentropy
for loss function. But if you transform your integer label to a one-hot encoded vector, then you should use categorical_accuracy
for accuracy, and categorical_crossentropy
作为损失函数。由于这些数据集有整数标签,您可以选择 sparse_categorical
或者您可以将标签转换为 one-hot 以便使用 categorical
.
第二层,如果你设置outputs = keras.layers.Dense(102, activation='softmax')(x)
到最后一层,你会得到概率分数。但是如果你设置outputs = keras.layers.Dense(102)(x)
,那么你会得到logits。所以,如果你设置 activations='softmax'
,那么你不应该使用 from_logit = True
。例如,在您上面的代码中,您应该执行以下操作(这里是 适合您):
...
(a)
# Use softmax activation (no logits output)
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)
# no activation, output will be logits
outputs = keras.layers.Dense(102)(x)
...
model.compile(
optimizer=keras.optimizers.Adam(),
loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=[keras.metrics.Accuracy()],
)
第三,keras使用字符串标识符如metrics=['acc'] , optimizer='adam'
。但是在您的情况下,您需要更具体一些,因为您提到了特定于损失函数的内容。所以,如果你的目标是整数,你应该选择 keras.metrics.SparseCategoricalAccuracy()
而不是 keras.metrics.Accuracy()
,如果你的目标是整数,你应该选择 keras.metrics.CategoricalAccuracy()
热编码向量.
代码示例
这是一个端到端的例子。请注意,我将将整数标签转换为单热编码向量(现在,这是我的偏好问题)。另外,我想要最后一层的 probabilities(不是 logits),这意味着 from_logits = False
。对于所有这些,我需要在训练中选择以下参数:
# use softmax to get probabilities
outputs = keras.layers.Dense(102,
activation='softmax')(x)
# so no logits, set it false (FYI, by default it already false)
loss = keras.losses.CategoricalCrossentropy(from_logits=False),
# specify the metrics properly
metrics = keras.metrics.CategoricalAccuracy(),
让我们完成整个代码。
import tensorflow_datasets as tfds
tfds.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_classes
train_size = len(data['train'])
batch_size = 64
img_size = 120
预处理和增强
import tensorflow as tf
# pre-process functions
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) # int to one-hot
return image, label
# augmentation
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 = False
inputs = 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-1
and top-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/20
15/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.6186
Epoch 20/20
15/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
评价
# evaluate on test set
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]
我正在尝试使用预训练的 Xception 模型和新添加的分类器进行迁移学习。
这是型号:
base_model = keras.applications.Xception(
weights="imagenet",
input_shape=(224,224,3),
include_top=False
)
我使用的数据集 oxford_flowers102
直接取自 tensorflow 数据集。
This 是一个数据集页面。
我在 select 一些参数 时遇到问题 - 要么训练精度显示可疑的低值,要么存在错误。
我需要帮助指定此参数,对于此 (oxford_flowers102) 数据集:
- 为分类器新增了密集层。我正在尝试:
outputs = keras.layers.Dense(102, activation='softmax')(x)
我不确定我是否应该 select 激活函数。 - 模型的损失函数。
- 指标。
我试过了:
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 个图像组成,每个 class 个图像(每个总计 1020 个图像)。测试集由剩余的 6149 张图像组成(每个 class 最少 20)。
'test' 6,149
'train' 1,020
'validation' 1,020
如果我们检查,我们会看到
import tensorflow_datasets as tfds
tfds.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_classes
102
因此,它有 102 个类别或 class 个类别,并且目标带有一个具有不同形状输入的 整数 。
澄清
首先,如果你保留这个整数目标或标签,你应该使用sparse_categorical_accuracy
for accuracy and sparse_categorical_crossentropy
for loss function. But if you transform your integer label to a one-hot encoded vector, then you should use categorical_accuracy
for accuracy, and categorical_crossentropy
作为损失函数。由于这些数据集有整数标签,您可以选择 sparse_categorical
或者您可以将标签转换为 one-hot 以便使用 categorical
.
第二层,如果你设置outputs = keras.layers.Dense(102, activation='softmax')(x)
到最后一层,你会得到概率分数。但是如果你设置outputs = keras.layers.Dense(102)(x)
,那么你会得到logits。所以,如果你设置 activations='softmax'
,那么你不应该使用 from_logit = True
。例如,在您上面的代码中,您应该执行以下操作(这里是
...
(a)
# Use softmax activation (no logits output)
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)
# no activation, output will be logits
outputs = keras.layers.Dense(102)(x)
...
model.compile(
optimizer=keras.optimizers.Adam(),
loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=[keras.metrics.Accuracy()],
)
第三,keras使用字符串标识符如metrics=['acc'] , optimizer='adam'
。但是在您的情况下,您需要更具体一些,因为您提到了特定于损失函数的内容。所以,如果你的目标是整数,你应该选择 keras.metrics.SparseCategoricalAccuracy()
而不是 keras.metrics.Accuracy()
,如果你的目标是整数,你应该选择 keras.metrics.CategoricalAccuracy()
热编码向量.
代码示例
这是一个端到端的例子。请注意,我将将整数标签转换为单热编码向量(现在,这是我的偏好问题)。另外,我想要最后一层的 probabilities(不是 logits),这意味着 from_logits = False
。对于所有这些,我需要在训练中选择以下参数:
# use softmax to get probabilities
outputs = keras.layers.Dense(102,
activation='softmax')(x)
# so no logits, set it false (FYI, by default it already false)
loss = keras.losses.CategoricalCrossentropy(from_logits=False),
# specify the metrics properly
metrics = keras.metrics.CategoricalAccuracy(),
让我们完成整个代码。
import tensorflow_datasets as tfds
tfds.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_classes
train_size = len(data['train'])
batch_size = 64
img_size = 120
预处理和增强
import tensorflow as tf
# pre-process functions
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) # int to one-hot
return image, label
# augmentation
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 = False
inputs = 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-1
and top-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/20
15/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.6186
Epoch 20/20
15/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
评价
# evaluate on test set
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]