Multi-output 损失 keras/tensorflow 未按预期表现。尽管 sigmoid 激活和 0-1 缩放标签,但目标 #2 MAE 损失巨大且 >1

Multi-output losses keras/tensorflow do not behave as expected. Target #2 MAE loss is huge and >1 despite sigmoid activation and 0-1 scaled labels

SOLVED: see comment by Marco Cerliani. tl;dr Each output must be passed to the model as a separate array.

我有一个神经网络,有两个不同的目标要估计:

目标 #1 为 0-无穷大,最终单节点密集层使用 'linear' 激活函数。

目标 #2 缩放为 0-1,最终单节点密集层使用 'sigmoid' 激活函数。

两个输出都使用 MAE 损失,但是目标 #2 的 MAE 几乎与目标 #1 一样高。由于 Target #2 是 0-1 而 sigmoid 只能给出 0-1 输出,我预计 Target #2 的损失不应该 >1.

事实上,当我只在单个输出模型中估计目标 #2 时,我总是得到小于 1 的损失。只有在使用 multiple-outputs.

时才会出现问题

这是一个错误,还是我做错了什么?

optimizer = tf.keras.optimizers.Adam(learning_rate=1e-5)
mae_loss = tf.keras.losses.MeanAbsoluteError()
rmse_metric = tf.keras.metrics.RootMeanSquaredError()

inputs = tf.keras.layers.Input(shape=(IMG_SIZE, IMG_SIZE, CHANNELS))
model = tf.keras.applications.vgg16.VGG16(include_top=False, input_tensor=inputs, 
weights='imagenet')

# Freeze the pretrained weights if needed
model.trainable = True

# Rebuild top
x = tf.keras.layers.GlobalAveragePooling2D(name='avg_pool')(model.output)
x = tf.keras.layers.BatchNormalization()(x)

top_dropout_rate = 0.0 # adjustable dropout
x = tf.keras.layers.Dropout(top_dropout_rate, name='top_dropout')(x)
x = tf.keras.layers.Dense(512, activation='relu', name='dense_top_1')(x)

output_1 = tf.keras.layers.Dense(1, activation='linear', name='output_1')(x)
output_2 = tf.keras.layers.Dense(1, activation='sigmoid', name='output_2')(x)
model = tf.keras.Model(inputs, [output_1, output_2], 
name='VGG16_modified')
model.compile(optimizer=optimizer, loss=mae_loss, metrics=rmse_metric)

model.fit(X_train, y_train, batch_size=16, epochs=epochs, validation_data=[X_val, y_val], verbose=1)

我也试过用两个单独的损失显式编译:

model.compile(optimizer=optimizer, loss=[mae_loss, mae_loss], metrics=[rmse_metric, rmse_metric])

示例目标:

[[2.05e+02 7.45e-01]
 [1.33e+02 1.46e-01]
 [8.00e+01 2.77e-01]
 [8.30e+01 4.29e-01]
 [9.80e+01 1.50e-01]
 [6.10e+01 3.10e-01]
 [1.00e+02 4.09e-01]
 [2.20e+02 9.17e-01]
 [1.20e+02 1.52e-01]]

终端输出(部分裁剪,但你明白了(考虑到 sigmoid 函数和以上目标,损失 #2 应该不可能 >76):

TensorFlow v.2.8.0

您的模型需要 2 个目标(output_1output_2),而您在 model.fit 期间仅使用 y_train 作为目标。

您应该以这种方式让您的模型通过两个分离的目标:

model.fit(X_train, [y_train[:,[0]],y_train[:,[1]]], ...)