前言
通过前面几节我们对评估模型的不确定性有了一个大概的认识:多次预测的值围绕均值上下浮动的程度,也称为方差。这篇文章主要是介绍计算机视觉的回归任务里面如何计算epistemic uncertainty 和 aleatoric uncertainty,并且对回归任务给出了新的损失函数,对噪声数据有更好的鲁棒性,如果对不确定性不了解的话不建议直接阅读,文章有的地方表述并不友好,结合贝叶斯基础和程序观察会更容易理解作者想表达什么。
损失函数(以回归任务为例)
通过dropout+变分推断近似贝叶斯神经网络所得到的不确定性可以计算为:
V
a
r
(
y
)
=
σ
2
+
1
T
∑
t
=
1
T
f
W
^
t
(
x
)
T
f
W
^
t
(
x
)
−
E
(
y
)
T
E
(
y
)
Var(y)=\sigma^2+\frac{1}{T}\sum_{t=1}^T f^{\hat W_t}(x)^Tf^{\hat W_t}(x)-E(y)^TE(y)
Var(y)=σ2+T1t=1∑TfW^t(x)TfW^t(x)−E(y)TE(y)
其中
σ
2
\sigma^2
σ2为数据的固有噪声,认为它是一个定值,
x
x
x是一个测试样本,经过多次前向传播计算
f
W
^
t
(
x
)
f^{\hat W_t}(x)
fW^t(x),
E
(
y
)
≈
1
T
∑
t
=
1
T
f
W
^
t
(
x
)
E(y)\approx \frac{1}{T}\sum_{t=1}^T f^{\hat W_t}(x)
E(y)≈T1∑t=1TfW^t(x),实际上后面就是在计算预测方差。
如果将数据的噪声认为是一个方差,传统的贝叶斯模型认为这个方差与数据无关,但是在heteroscedastic aleatoric uncertainty中认为方差是一个与数据有关的变量,
σ
(
i
)
\sigma(i)
σ(i)大的样本表示该样本含有的噪声数据比较多(方差大)。在heteroscedastic模型中,损失函数的计算表示为:
L
N
N
(
θ
)
=
1
N
∑
i
=
1
N
1
2
σ
(
x
i
)
2
∣
∣
y
i
−
f
(
x
i
)
∣
∣
2
+
1
2
log
σ
(
x
i
)
2
\mathcal{L}_{NN}(\theta)=\frac{1}{N}\sum_{i=1}^{N}\frac{1}{2\sigma(x_i)^2}||y_i-f(x_i)||^2+\frac{1}{2}\log \sigma(x_i)^2
LNN(θ)=N1i=1∑N2σ(xi)21∣∣yi−f(xi)∣∣2+21logσ(xi)2
作者想将MC dropout计算不确定性的方式和heteroscedastic对噪声的表示方式整合起来,设对于一个输入样本,计算得到网络的输出,网络以dropout的形式而不是贝叶斯网络的形式出现:
[
y
^
,
σ
^
2
]
=
f
W
^
(
x
)
[\hat y,\hat \sigma^2]=f^{\hat W}(x)
[y^,σ^2]=fW^(x)
其中
W
^
\hat W
W^表示从后验分布
q
(
W
)
q(W)
q(W)中采样,
y
^
\hat y
y^表示预测值,
σ
^
2
\hat \sigma^2
σ^2表示对于该样本的噪声方差。网络要优化的损失函数目标为:
L
B
N
N
(
θ
)
=
1
D
∑
i
1
2
σ
^
i
−
2
∣
∣
y
i
−
y
^
i
∣
∣
2
+
1
2
log
σ
^
i
2
\mathcal{L}_{BNN}(\theta)=\frac{1}{D}\sum_i\frac{1}{2}\hat \sigma_i^{-2}||y_i-\hat y_i||^2+\frac{1}{2}\log \hat \sigma_i^2
LBNN(θ)=D1i∑21σ^i−2∣∣yi−y^i∣∣2+21logσ^i2
这篇文章缺少必要的推导过程,上面那个公式应该是从Monte Carlo dropout的损失函数推出来的,反应模型的不确定,
σ
i
2
\sigma_i^2
σi2是数据的不确定性。在测试阶段,分别计算数据不确定,模型不确定性,总不确定性:
数据不确定:
网络输出的每个样本对应的
σ
(
i
)
\sigma(i)
σ(i)
模型(认知)不确定:
将样本进行
T
T
T次前向传播,计算所得到的
y
^
t
\hat y_t
y^t的方差,即:
E
(
y
^
t
2
)
−
E
(
y
^
t
)
2
=
1
T
∑
t
=
1
T
y
^
t
2
−
(
1
T
∑
t
=
1
T
y
^
t
)
2
E({\hat y_t}^2)-E(\hat y_t)^2=\frac{1}{T}\sum_{t=1}^T{\hat y_t}^2-(\frac{1}{T}\sum_{t=1}^T\hat y_t)^2
E(y^t2)−E(y^t)2=T1t=1∑Ty^t2−(T1t=1∑Ty^t)2
总不确定性:
上面两者之和
程序
# 测试数据的不确定性,计算预测的均值和方差,也就是说每一个样本的预测值都是一个高斯分布σ(i)
# 每个mean对应的是一个预测值
def test_aleatoric(self, input, forward_func):
results = forward_func(input)
mean1 = results['mean']
var1 = torch.exp(results['var'])
var1_norm = var1 / var1.max()
results = {'mean': mean1, 'var': var1_norm}
return results
# 测试模型的不确定性,需要多次前向传播,计算总次数对应的均值和方差,var=E(x^2)-(E(x)^2)
def test_epistemic(self, input, forward_func):
mean1s = []
mean2s = []
for i_sample in range(self.n_samples):
results = forward_func(input)
mean1 = results['mean']
mean1s.append(mean1 ** 2)
mean2s.append(mean1)
mean1s_ = torch.stack(mean1s, dim=0).mean(dim=0)
mean2s_ = torch.stack(mean2s, dim=0).mean(dim=0)
var1 = mean1s_ - mean2s_ ** 2
var1_norm = var1 / var1.max()
results = {'mean': mean2s_, 'var': var1_norm}
return results
# 数据的不确定 + 模型的不确定,方差对应从模型不确定性计算的方差 + 数据不确定的方差
def test_combined(self, input, forward_func):
mean1s = []
mean2s = []
var1s = []
for i_sample in range(self.n_samples):
results = forward_func(input)
mean1 = results['mean']
mean1s.append(mean1 ** 2)
mean2s.append(mean1)
var1 = results['var']
var1s.append(torch.exp(var1))
mean1s_ = torch.stack(mean1s, dim=0).mean(dim=0)
mean2s_ = torch.stack(mean2s, dim=0).mean(dim=0)
var1s_ = torch.stack(var1s, dim=0).mean(dim=0)
var2 = mean1s_ - mean2s_ ** 2
var_ = var1s_ + var2
var_norm = var_ / var_.max()
results = {'mean': mean2s_, 'var': var_norm}
return results