跳转至

借助 torchmetricsCompositionalMetric 将越大越好的指标作为损失函数

在量化研究中,我们可以使用诸如 IC 一类的指标来衡量信号的质量。若将 IC 作为损失函数,我们自然是希望其值越大越好。但是,模型的优化过程总是朝着损失函数越小的方向进行的,因此我们需要将 IC 取反后作为损失值,使得模型朝着 IC 越大的方向优化。

本文介绍了一个便捷的方法,借助 torchmetricsCompositionalMetric 将越大越好的指标作为损失函数。

Python
pred = torch.tensor([1, 2, 3, 4]).to(torch.float32)
target = torch.tensor([2, 3, 5, 10]).to(torch.float32)
print("原始相关系数:", np.corrcoef(target, pred)[0, 1])
loss_fn = 0 - PearsonCorrCoef()
print("损失函数:", loss_fn(pred, target))
Text Only
原始相关系数: 0.9431191251430151
损失函数: tensor(-0.9431)

代码示例

Python
import numpy as np
import torch
from torchmetrics.regression import MeanSquaredError, PearsonCorrCoef

相关系数为正时

当相关系数为正时,用 0 - PearsonCorrCoef() 作为损失函数会得到负值。

Python
pred = torch.tensor([1, 2, 3, 4]).to(torch.float32)
target = torch.tensor([2, 3, 5, 10]).to(torch.float32)
np.corrcoef(target, pred)[0, 1]
Text Only
0.9431191251430151
Python
loss_fn = PearsonCorrCoef()
loss_fn(pred, target)
Text Only
tensor(0.9431)
Python
loss_fn = 0 - PearsonCorrCoef()
loss_fn(pred, target)
Text Only
tensor(-0.9431)

相关系数为负时

当相关系数为负时,用 0 - PearsonCorrCoef() 作为损失函数会得到正值。

Python
pred = torch.tensor([-2, 0, -5, -8]).to(torch.float32)
np.corrcoef(target, pred)[0, 1]
Text Only
-0.909826216965074
Python
loss_fn = PearsonCorrCoef()
loss_fn(pred, target)
Text Only
tensor(-0.9098)
Python
loss_fn = 0 - PearsonCorrCoef()
loss_fn(pred, target)
Text Only
tensor(0.9098)

查看 0 - PearsonCorrCoef() 的类型,可以发现它是一个 CompositionalMetric

Python
type(0 - PearsonCorrCoef())
Text Only
torchmetrics.metric.CompositionalMetric

0 - PearsonCorrCoef() 构造 CompositionalMetric 时的 0 不可省略

注意,其中的 0 是必要的,也就是不能用 -PearsonCorrCoef()

根据 torchmetrics/metric.py 中的 __neg__ 方法,-PearsonCorrCoef() 会返回一个 CompositionalMetric,其中 operator_neg,其定义如下:

Python
def _neg(x: Tensor) -> Tensor:
    return -torch.abs(x)

如果缺少了 0,而只用 -PearsonCorrCoef(),那么得到的值是:先计算皮尔森相关系数,再取绝对值,最后取负值。因此无论如何都会得到一个非正数,这并不是我们想要的。

Python
loss_fn = -PearsonCorrCoef()
loss_fn(pred, target)
Text Only
tensor(-0.9098)

利用魔法方法实现多个指标之间的算子

torchmetrics.metric 中,Metric 类还定义了许多魔法方法,包括 __add____sub____mul____abs__ 等。这些魔法方法就是多个指标之间的算子,我们可以利用这些算子自定义地构建更加复杂的损失函数和评估指标。

Python
loss_fn = MeanSquaredError() - 2 * PearsonCorrCoef()
loss_fn(pred, target)
Text Only
tensor(114.0696)
Python
MeanSquaredError()(pred, target)
Text Only
tensor(112.2500)
Python
PearsonCorrCoef()(pred, target)
Text Only
tensor(-0.9098)

评论