【问题标题】:model.fit() never calls custom metric specifiedmodel.fit() 从不调用指定的自定义指标
【发布时间】:2021-11-09 15:57:05
【问题描述】:

按照documentation,我正在尝试实现一个自定义指标,但是该指标永远不会被调用。我添加了在调用指标时会产生错误的完整性检查。您可以在 notebook 中找到完整的示例。

def my_metric_fn(y_true, y_pred):
    1 / 0
    while True:
        pass
    squared_difference = tf.square(y_true - y_pred)
    return tf.reduce_mean(squared_difference, axis=-1)  

但是,将指标传递给model.compile()后,代码运行没有问题

model.compile(optimizer=opt, metrics=[my_metric_fn])
history = model.fit(
train_dataset,
validation_data=validation_dataset,
epochs=epochs,
callbacks=[early_stopping]
)

我实际得到的:

Epoch 1/100
59/59 [==============================] - 27s 451ms/step - loss: 16.3928 - my_metric_fn: 0.0000e+00 - val_loss: 16.5252 - val_my_metric_fn: 0.0000e+00
Epoch 2/100
59/59 [==============================] - 25s 420ms/step - loss: 16.3508 - my_metric_fn: 0.0000e+00 - val_loss: 16.5316 - val_my_metric_fn: 0.0000e+00
Epoch 3/100
59/59 [==============================] - 25s 420ms/step - loss: 16.3420 - my_metric_fn: 0.0000e+00 - val_loss: 16.5372 - val_my_metric_fn: 0.0000e+00
Epoch 4/100
59/59 [==============================] - 25s 417ms/step - loss: 16.3365 - my_metric_fn: 0.0000e+00 - val_loss: 16.5287 - val_my_metric_fn: 0.0000e+00
Epoch 5/100
59/59 [==============================] - 25s 418ms/step - loss: 16.3251 - my_metric_fn: 0.0000e+00 - val_loss: 16.5271 - val_my_metric_fn: 0.0000e+00

【问题讨论】:

    标签: python tensorflow keras deep-learning


    【解决方案1】:

    我认为您在同时使用指标和add_loss 时遇到了这个bug。也许尝试将您的指标显式添加到您的自定义层:

    def my_metric_fn(y_true, y_pred):
        squared_difference = tf.square(y_true - y_pred)
        return tf.reduce_mean(y_true, axis=-1)  
    
    class CTCLayer(layers.Layer):
        def __init__(self, name=None):
            super().__init__(name=name)
            self.loss_fn = keras.backend.ctc_batch_cost
    
        def call(self, y_true, y_pred):
            # Compute the training-time loss value and add it
            # to the layer using `self.add_loss()`.
            batch_len = tf.cast(tf.shape(y_true)[0], dtype="int64")
            input_length = tf.cast(tf.shape(y_pred)[1], dtype="int64")
            label_length = tf.cast(tf.shape(y_true)[1], dtype="int64")
    
            input_length = input_length * tf.ones(shape=(batch_len, 1), dtype="int64")
            label_length = label_length * tf.ones(shape=(batch_len, 1), dtype="int64")
    
            loss = self.loss_fn(y_true, y_pred, input_length, label_length)
            self.add_loss(loss)
            self.add_metric(my_metric_fn(y_true, y_pred), 'my_metric_fn')
    
            # At test time, just return the computed predictions
            return y_pred
    
    Epoch 1/100
    15/59 [======>.......................] - ETA: 17s - loss: 34.6694 - my_metric_fn: 10.3142
    

    或将其添加到模型的末尾:

    opt = keras.optimizers.Adam()
    # Compile the model and return
    model.compile(optimizer=opt)
    model.add_metric(my_metric_fn(...), 'my_metric_fn')
    

    【讨论】:

    • 我想你的意思是tf.reduce_mean(squared_difference, axis=-1)。另外,下面这行model.add_metric(my_metric_fn(...), 'my_metric_fn') 是什么意思,传递给my_metric_fn() 的实际值是多少?我修改了notebook 并包含了您的建议,但我遇到了形状不兼容的问题,因此请相应地编辑您的答案。
    • 不。 model.add_metric(my_metric_fn(...), 'my_metric_fn') 只是一个例子/建议。我没有具体研究如何去做,可能是你的输入和输出;)。由于这个不兼容的形状问题,我的答案不是计算您定义的指标。我只是想向您展示如何向您的模型添加指标...您的模型的输出形状是 [16 50 21] 和您的 input_shape [16 5](标签)...您打算计算什么? y_true - y_pred 无法工作,因为它们的形状不同。
    • 我正计划计算单词和字母的准确性,因此我将修改代码以包含实际指标并重试
    • 我根据您的回答发布了另一个 question,其中包含仅在急切执行中有效的实际指标,如果您愿意,可以查看。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-24
    • 2021-06-01
    相关资源
    最近更新 更多