概
看这篇文章单纯是为了看一看这个scale-invariant error.
主要内容
我们时常通过平方误差来衡量两个图片的差异, 但是这个损失是很依赖与scale的.
比如, 有两个图片
x
,
x
′
\bm{x}, \bm{x}'
x,x′, 则其误差为
∥
x
−
x
′
∥
2
2
=
∑
i
=
1
n
(
x
i
−
x
i
′
)
2
,
\|\bm{x} - \bm{x}'\|_2^2 = \sum_{i=1}^n (\bm{x}_i - \bm{x}_i')^2,
∥x−x′∥22=i=1∑n(xi−xi′)2,
倘若此时
x
x
x的每一个元素都增加了
c
c
c, 则变成了
∥
x
+
c
−
x
′
∥
2
2
,
\|\bm{x} + c - \bm{x}'\|_2^2,
∥x+c−x′∥22,
这个实际不是非常友好的, 我们是希望这个损失最好是Scale-Invariant的, 所以我们在损失的部分加入一个值
∥
x
−
x
′
+
α
∥
2
2
,
\| \bm{x} - \bm{x}' + \alpha \|_2^2,
∥x−x′+α∥22,
注意, 这里的
x
\bm{x}
x可以理解为
x
+
c
\bm{x} + c
x+c, 那么选择一个怎样的
α
\alpha
α能够使得上述的误差最小呢(关于特定的
x
,
x
′
\bm{x}, \bm{x}'
x,x′).
2
(
x
−
x
′
+
α
)
T
1
=
0
⇒
α
=
1
n
(
x
′
−
x
)
T
1
=
1
n
∑
i
=
1
n
(
x
i
′
−
x
i
)
.
2(\bm{x} - \bm{x}' + \alpha)^T \bm{1} = 0 \Rightarrow \alpha = \frac{1}{n} (\bm{x}'- \bm{x})^T \bm{1} = \frac{1}{n}\sum_{i=1}^n (x_i' - x_i).
2(x−x′+α)T1=0⇒α=n1(x′−x)T1=n1i=1∑n(xi′−xi).
故, 最后的损失函数是
∥
x
−
x
′
+
1
n
(
x
−
x
′
)
T
1
∥
2
2
=
∥
x
−
x
′
∥
2
2
−
1
n
(
(
x
−
x
′
)
T
1
)
2
.
\| \bm{x} - \bm{x}' + \frac{1}{n}(\bm{x} - \bm{x}')^T \bm{1}\|_2^2 = \|\bm{x} - \bm{x}'\|_2^2 - \frac{1}{n} ((\bm{x} - \bm{x}')^T \bm{1})^2.
∥x−x′+n1(x−x′)T1∥22=∥x−x′∥22−n1((x−x′)T1)2.
注: 如果我们将像素置于对数空间, 即考虑 log x \log \bm{x} logx, 则上述实际上考虑的 c ⋅ x c \cdot \bm{x} c⋅x 的scale.
代码
import torch
import torch.nn as nn
import torch.nn.functional as F
def scale_invariant_loss(outs: torch.Tensor, targets: torch.Tensor, reduction="mean"):
"""
outs: N ( x C) x H x W
targets: N ( x C) x H x W
reduction: ...
"""
outs = outs.flatten(start_dim=1)
targets = targets.flatten(start_dim=1)
alpha = (targets - outs).mean(dim=1, keepdim=True)
return F.mse_loss(outs + alpha, targets, reduction=reduction)