在训练模型后,我使用predict
方法从我的测试数据中推断分数。
根据预测的分数,我如何使用模型汇编的损失和指标来计算我的预测损失?
我尝试过的
基于自定义fit()
指南中的内容,我尝试使用compiled_loss
方法
y_pred = model.predict(x_test)
model.compiled_loss(y_test, y_pred, regularization_losses=model.losses)
但它返回错误
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-6-3eb62dca0b87> in <module>()
1 y_pred = model.predict(x_test)
----> 2 loss = model.compiled_loss(y_test, y_pred)
1 frames
/usr/local/lib/python3.7/dist-packages/keras/engine/compile_utils.py in match_dtype_and_rank(y_t, y_p, sw)
673 def match_dtype_and_rank(y_t, y_p, sw):
674 """Match dtype and rank of predictions."""
--> 675 if y_t.shape.rank == 1 and y_p.shape.rank == 2:
676 y_t = tf.expand_dims(y_t, axis=-1)
677 if sw is not None:
AttributeError: 'tuple' object has no attribute 'rank'
如何繁殖
我使用了简单MNIST convnet示例,然后是
y_pred = model.predict(x_test)
model.compiled_loss(y_test, y_pred, regularization_losses=model.losses)
以再现错误
关于我的问题
我正在根据自定义指标验证我的数据。然而,一些Keras用户建议,全局指标不应按批次平均,而应根据回调中整个验证数据的预测分数计算。
参见:
第5794期
如何在Keras中计算F1宏?
对此,糟糕的解决方案是从evaluate
方法计算损失和度量,从predict
计算我的自定义度量。这个问题是我进行了两次推理。
一个不那么糟糕的解决方案是单独实现我的损失函数,这样它就可以根据预测的分数工作。
参见:
在不运行模型的情况下计算Keras中的损失
这样做的问题是,它降低了我选择损失函数的灵活性,因为我必须在稍后的回调中单独实现每个损失函数。
但我真的很想知道,汇编的损失和指标不是已经可以访问了吗?
这里有一个函数,可以计算给定先前预测输出的度量:
import tensorflow as tf
def calculate_metrics(model, y, y_pred, sample_weight=None):
y = tf.convert_to_tensor(y)
y_pred = tf.convert_to_tensor(y_pred)
if not sample_weight is None:
sample_weight = tf.convert_to_tensor(sample_weight)
model.compute_loss(x=None, y=y, y_pred=y_pred, sample_weight=sample_weight)
metrics = model.compute_metrics(x=None, y=y, y_pred=y_pred,
sample_weight=sample_weight)
for k,v in metrics.items():
metrics[k] = float(v)
return metrics
它期望y
、y_pred
和sample_weight
(如果提供)是numpy数组。这意味着它们需要立即适应记忆。这也意味着度量值可能与model.evaluate
返回的值略有不同,但我认为您理解这一点,因为您的评论是";全局度量不应按批次求平均值">
但它返回错误
AttributeError: 'tuple' object has no attribute 'rank'
model.compiled_loss
(以及model.compute_loss
和model.compute_metrics
)期望每个输入都是Tensor
。张量具有属性shape
,其为类型TensorShape
,其又具有属性rank
。我希望您的y_test
是ndarray
,它也有属性shape
,但它是类型tuple
,它没有属性rank
。这就是我的函数将输入转换为张量的原因。返回的度量值也是张量,所以我手动将其中的每个值转换为普通的pythonfloat
。
但我真的很想知道,汇编的损失和指标不是已经可以访问了吗?
度量在model.fit
方法返回的History
对象中可用,因此,如果您正在评估新训练的模型,则不需要重新计算度量。但是,如果您正在加载以前训练过的模型并希望获得度量,则需要使用model.evaluate
或根据model.predict
的结果计算度量,就像我们在这里所做的那样。查看代码,可以分别比较model.test_step
和model.predict_step
。请注意,model.predict_step
只是运行推断并返回预测,因此在运行model.predict
时永远不会计算度量。一个比我提供的更好的解决方案是将model.predict
的元素组合到model.evaluate
中,这样它就可以选择性地返回y_pred
,而不是在计算度量后丢弃它,但这需要修改tensorflow代码。