神经网络训练不确定性
基于MC Dropout(蒙特卡罗丢弃法)获取神经网络Uncertainty(不确定性)
作用:
一般的神经网络可以有很多输出,但是无法确定网络的输出是否可靠,即无法确定有多大的把握可以相信网络的输出。如果网络输出结果的同时能够得出不确定性,那么在处理一些问题的时候能够更加灵活。
原理:
基于贝叶斯公式
实现
可使用蒙特卡罗方法实现,如MC Dropout。
主要步骤:
- 在网络输出之前给某些层加上dropout
- 网络训练的时候使用特定的损失函数进行优化
- 在测试网络时,需要将dropout打开,将网络运行N次,得到N个输出
- 统计N个输出的均值和方差,均值可作为输出结果,方差可作为不确定性
补充:获取不确定性不一定要用方差,也可以直接是神经网络的输出
损失函数(回归)
一般为:
\(L=\frac{1}{D}\sum_i\frac{1}{2}\hat{\sigma}^2{\bigg\lVert y_i-\hat{y}_i\bigg\lVert}^2+\frac{1}{2}log\hat{\sigma}^2\)
代码:
'''
使用RDN网络预测根据图像上下文像素预测完整图像的一个例子
'''
# 开启dropout
def enable_dropout(model):
for m in model.modules():
if type(m) == nn.Dropout:
m.train()
# 定义模型
model = RDN(
num_channels=3,
num_features=args.num_features,
growth_rate=args.growth_rate,
num_blocks=args.num_blocks,
num_layers=args.num_layers
).to(device)
#加载权重
state_dict = model.state_dict()
for n, p in torch.load(args.weights_file, map_location=lambda storage, loc: storage).items():
if n in state_dict.keys():
state_dict[n].copy_(p)
else:
raise KeyError(n)
# eval模式默认不启用dropout,这里将其开启
model.eval()
enable_dropout(model)
# 处理模型输入参数
t = Image.open(args.image_file).convert('RGB')
p, t = get_p(t, t.height, t.width, 3)
p = np.expand_dims(np.array(p).astype(np.float32).transpose([2, 0, 1]), 0) / 255.0
t = np.expand_dims(np.array(t).astype(np.float32).transpose([2, 0, 1]), 0) / 255.0
p = torch.from_numpy(p).to(device)
t = torch.from_numpy(t).to(device)
# 回归模型预测结果集合,因为将模型运行args.num_DS次以获取方差,所以需要记录每一次预测结果
preds = []
# 将模型运行args.num_DS次以获取方差
for i in range(args.num_DS):
with torch.no_grad():
log_sigma_2 = model(p)
preds.append(pred)
# 计算方差作为不确定性
uncertain_e = torch.var(torch.cat(preds), dim=0).permute(1, 2, 0)
# 计算均值作为预测结果
preds_mean = torch.mean(torch.cat(preds), dim=0).permute(1, 2, 0)
p = p.squeeze(0).permute(1, 2, 0)
t = t.squeeze(0).permute(1, 2, 0)
浙公网安备 33010602011771号