多输出Tensorflow模型不会对每个输出都有输出损失

问题描述 投票:0回答:1

我使用的是 Geron 的《使用 Scikit Learn、Keras 和 Tensorflow 进行机器学习实践》一书(第 3 版)中的示例。这个例子可以获取https://github.com/ageron/handson-ml3.

我所指的示例代码位于 Ch.1 中。 10,在“使用子类化 API 构建动态模型”部分下:

class WideAndDeepModel(tf.keras.Model):
    def __init__(self, units=30, activation="relu", **kwargs):
        super().__init__(**kwargs)  # needed to support naming the model
        self.norm_layer_wide = tf.keras.layers.Normalization()
        self.norm_layer_deep = tf.keras.layers.Normalization()
        self.hidden1 = tf.keras.layers.Dense(units, activation=activation)
        self.hidden2 = tf.keras.layers.Dense(units, activation=activation)
        self.main_output = tf.keras.layers.Dense(1)
        self.aux_output = tf.keras.layers.Dense(1)
        
    def call(self, inputs):
        input_wide, input_deep = inputs
        norm_wide = self.norm_layer_wide(input_wide)
        norm_deep = self.norm_layer_deep(input_deep)
        hidden1 = self.hidden1(norm_deep)
        hidden2 = self.hidden2(hidden1)
        concat = tf.keras.layers.concatenate([norm_wide, hidden2])
        output = self.main_output(concat)
        aux_output = self.aux_output(hidden2)
        return output, aux_output

tf.random.set_seed(42)  # extra code – just for reproducibility
model = WideAndDeepModel(30, activation="relu", name="my_cool_model")

optimizer = tf.keras.optimizers.Adam(learning_rate=1e-3)
model.compile(loss="mse", loss_weights=[0.9, 0.1], optimizer=optimizer,
              metrics=["RootMeanSquaredError"])
model.norm_layer_wide.adapt(X_train_wide)
model.norm_layer_deep.adapt(X_train_deep)
history = model.fit(
    (X_train_wide, X_train_deep), (y_train, y_train), epochs=10,
    validation_data=((X_valid_wide, X_valid_deep), (y_valid, y_valid)))
eval_results = model.evaluate((X_test_wide, X_test_deep), (y_test, y_test))
weighted_sum_of_losses, main_loss, aux_loss, main_rmse, aux_rmse = eval_results
y_pred_main, y_pred_aux = model.predict((X_new_wide, X_new_deep))

理论上应该给出:

Epoch 1/10
363/363 [==============================] - 1s 2ms/step - loss: 1.3490 - output_1_loss: 1.2742 - output_2_loss: 2.0215 - output_1_root_mean_squared_error: 1.1288 - output_2_root_mean_squared_error: 1.4218 - val_loss: 1.5415 - val_output_1_loss: 0.9593 - val_output_2_loss: 6.7806 - val_output_1_root_mean_squared_error: 0.9795 - val_output_2_root_mean_squared_error: 2.6040
Epoch 2/10
363/363 [==============================] - 0s 1ms/step - loss: 0.5101 - output_1_loss: 0.4785 - output_2_loss: 0.7952 - output_1_root_mean_squared_error: 0.6917 - output_2_root_mean_squared_error: 0.8917 - val_loss: 1.3624 - val_output_1_loss: 1.0094 - val_output_2_loss: 4.5401 - val_output_1_root_mean_squared_error: 1.0047 - val_output_2_root_mean_squared_error: 2.1307
Epoch 3/10
363/363 [==============================] - 0s 1ms/step - loss: 0.4618 - output_1_loss: 0.4404 - output_2_loss: 0.6546 - output_1_root_mean_squared_error: 0.6636 - output_2_root_mean_squared_error: 0.8091 - val_loss: 0.5361 - val_output_1_loss: 0.3975 - val_output_2_loss: 1.7837 - val_output_1_root_mean_squared_error: 0.6305 - val_output_2_root_mean_squared_error: 1.3356
Epoch 4/10
363/363 [==============================] - 0s 1ms/step - loss: 0.4252 - output_1_loss: 0.4059 - output_2_loss: 0.5985 - output_1_root_mean_squared_error: 0.6371 - output_2_root_mean_squared_error: 0.7736 - val_loss: 0.5182 - val_output_1_loss: 0.4590 - val_output_2_loss: 1.0517 - val_output_1_root_mean_squared_error: 0.6775 - val_output_2_root_mean_squared_error: 1.0255

此输出取自提供的 Jupyter 笔记本 - 我实际上没有得到此输出。

我无法立即运行此代码,因为 Tensorflow 抱怨:

ValueError: For a model with multiple outputs, when providing the `metrics` argument as a list, it should have as many entries as the model has outputs. Received:
metrics=['RootMeanSquaredError']
of length 1 whereas the model has 2 outputs.

我可以通过添加另一个“RootMeanSquaredError”来解决这个问题。我的主要问题是在训练期间获得以下输出:

Epoch 1/10
66/66 ━━━━━━━━━━━━━━━━━━━━ 1s 3ms/step - RootMeanSquaredError: 0.4504 - RootMeanSquaredError_1: 0.4841 - loss: 0.2072 - val_RootMeanSquaredError: 0.3687 - val_RootMeanSquaredError_1: 0.4427 - val_loss: 0.1420
Epoch 2/10
66/66 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - RootMeanSquaredError: 0.3633 - RootMeanSquaredError_1: 0.4302 - loss: 0.1374 - val_RootMeanSquaredError: 0.3614 - val_RootMeanSquaredError_1: 0.4205 - val_loss: 0.1352
Epoch 3/10
66/66 ━━━━━━━━━━━━━━━━━━━━ 0s 2ms/step - RootMeanSquaredError: 0.3568 - RootMeanSquaredError_1: 0.4135 - loss: 0.1317 - val_RootMeanSquaredError: 0.3564 - val_RootMeanSquaredError_1: 0.4134 - val_loss: 0.1314
Epoch 4/10
66/66 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - RootMeanSquaredError: 0.3519 - RootMeanSquaredError_1: 0.4075 - loss: 0.1281 - val_RootMeanSquaredError: 0.3510 - val_RootMeanSquaredError_1: 0.4096 - val_loss: 0.1277
Epoch 5/10
66/66 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - RootMeanSquaredError: 0.3475 - RootMeanSquaredError_1: 0.4041 - loss: 0.1250 - val_RootMeanSquaredError: 0.3469 - val_RootMeanSquaredError_1: 0.4063 - val_loss: 0.1248

尽管有 2 个输出,为什么我只得到 loss 和 val_loss ?其他输出对应于每个输出的指标。我期待损失、output_1_loss、output_2_loss 等

我尝试删除metrics关键字参数,并且在训练期间只打印loss和val_loss。我还尝试了不同的自定义子类模型类,但结果相同。我还尝试使用功能 API 创建模型并得到了同样的结果。

尝试设置 verbose=2 不变。尝试了单个输入(而不是两个输入),没有任何变化。

尝试设置输出层的名称参数并传递字典参数:

model.compile(loss={'out0':'mse','out1':'mse'}, loss_weights=[0.9, 0.1], optimizer=optimizer,
              metrics={'out0':'RootMeanSquaredError','out1':'RootMeanSquaredError'})
history = model.fit(
    (train_feat[0], train_feat[1]), {'out0': train_label[0], 'out1': train_label[1]}, epochs=10,
    validation_data=((val_feat[0], val_feat[1]), {'out0': val_label[0], 'out1': val_label[1]}))

没有任何变化。

尝试传递

loss=[tf.keras.losses.MeanSquaredError(), tf.keras.loss.MeanSquaredError()]
列表,没有任何变化。

一篇文章似乎也有同样的问题,但修复了使用指标进行监控的问题:

多输出回归中如何得到每个输出的损失?

另一篇文章似乎用相同的设置得到了我想要的:

仅显示 Keras 中多输出模型训练期间的总损失

我使用的是 Python 3.9、Tensorflow 2.17.0 和 Keras 3.4.1。我有什么遗漏的吗?

python tensorflow keras
1个回答
0
投票

升级到Keras 3.5.0解决了错误

© www.soinside.com 2019 - 2024. All rights reserved.