Blitz是一个简单且可扩展的库,可在Pytorch上创建贝叶斯神经网络层(基于神经网络论文中的重量不确定性提议的内容)。通过使用Blitz层和UTILS,您可以以简单的方式添加不稳定性并收集模型的复杂性成本,不会影响图层之间的相互作用,就好像您正在使用标准的Pytorch一样。
通过使用我们的核心重量采样器类,您可以扩展和改进该库,以在更大的层次上添加不稳定范围。也欢迎拉动请求。
要安装Blitz,您可以使用PIP命令:
pip install blitz-bayesian-pytorch
或者,通过conda:
conda install -c conda-forge blitz-bayesian-pytorch
您还可以将其粘合并在本地安装它:
conda create -n blitz python=3.9
conda activate blitz
git clone https://github.com/piEsposito/blitz-bayesian-deep-learning.git
cd blitz-bayesian-deep-learning
pip install .
我们的层,重量(和先前分布)采样器和utils的文档:
(您可以通过在计算机上运行此示例来为自己看到它)。
现在,我们将看到如何将贝叶斯深度学习用于回归,以便在我们的数据点上收集置信区间,而不是涉及的连续价值预测。比低错误估计,为您的预测收集置信区间可能甚至是更有用的信息。
我对以下事实保持了论点:凭借良好/高的置信区间,您可以做出比在某些情况下进行非常近端的估计更可靠的决定:如果您试图从交易行动中获利,例如,拥有良好的置信区间,良好的置信区间可能会导致您至少知道该操作的价值是否会降低(或更高)(或更高)比某些确定的X。
知道一个值是否会在确定的间隔内肯定会(或概率),这可以帮助人们做出明智的决策,而不是一个非常近端的估计,如果较低或高于某些限制值,则可能会导致交易的损失。关键是,有时知道是否有利润可能比测量它更有用。
为了证明这一点,我们将为波士顿-House-DATA玩具数据集创建贝叶斯神经网络回归剂,试图为我们试图预测的价格创建置信区间(CI)。我们将执行一些缩放,CI约为75%。有趣的是,大约90%的顺式预测低于高极限或(包含)高于下限。
尽管通过已知的模块,我们将带来Blitz A The variational_estimator Decorator,这有助于我们处理模块上的贝叶斯利层层,以使其与其余的火炬完全集成在一起, BayesianLinear ,这是我们的层,这是我们的层,具有不稳定的重量。
import torch
import torch . nn as nn
import torch . nn . functional as F
import torch . optim as optim
import numpy as np
from blitz . modules import BayesianLinear
from blitz . utils import variational_estimator
from sklearn . datasets import load_boston
from sklearn . preprocessing import StandardScaler
from sklearn . model_selection import train_test_split 在这里没有新的阳光下,我们正在进口和标准缩放数据以帮助进行培训。
X , y = load_boston ( return_X_y = True )
X = StandardScaler (). fit_transform ( X )
y = StandardScaler (). fit_transform ( np . expand_dims ( y , - 1 ))
X_train , X_test , y_train , y_test = train_test_split ( X ,
y ,
test_size = .25 ,
random_state = 42 )
X_train , y_train = torch . tensor ( X_train ). float (), torch . tensor ( y_train ). float ()
X_test , y_test = torch . tensor ( X_test ). float (), torch . tensor ( y_test ). float ()我们可以像使用任何火炬网络一样从NN.Module中互动创建我们的班级。我们的装饰器介绍了处理贝叶斯特征的方法,因为计算贝叶斯层的复杂性成本并进行许多进料(每种饲料的重量不同),以便采样我们的损失。
@ variational_estimator
class BayesianRegressor ( nn . Module ):
def __init__ ( self , input_dim , output_dim ):
super (). __init__ ()
#self.linear = nn.Linear(input_dim, output_dim)
self . blinear1 = BayesianLinear ( input_dim , 512 )
self . blinear2 = BayesianLinear ( 512 , output_dim )
def forward ( self , x ):
x_ = self . blinear1 ( x )
x_ = F . relu ( x_ )
return self . blinear2 ( x_ )此功能确实为我们试图采样标签值的批次上的每个预测创建了一个置信区间。然后,我们可以通过寻求多少Predicon分布确实包含数据标签的正确标签来衡量预测的准确性。
def evaluate_regression ( regressor ,
X ,
y ,
samples = 100 ,
std_multiplier = 2 ):
preds = [ regressor ( X ) for i in range ( samples )]
preds = torch . stack ( preds )
means = preds . mean ( axis = 0 )
stds = preds . std ( axis = 0 )
ci_upper = means + ( std_multiplier * stds )
ci_lower = means - ( std_multiplier * stds )
ic_acc = ( ci_lower <= y ) * ( ci_upper >= y )
ic_acc = ic_acc . float (). mean ()
return ic_acc , ( ci_upper >= y ). float (). mean (), ( ci_lower <= y ). float (). mean ()在这里请注意,我们会像其他神经网络一样创建BayesianRegressor 。
regressor = BayesianRegressor ( 13 , 1 )
optimizer = optim . Adam ( regressor . parameters (), lr = 0.01 )
criterion = torch . nn . MSELoss ()
ds_train = torch . utils . data . TensorDataset ( X_train , y_train )
dataloader_train = torch . utils . data . DataLoader ( ds_train , batch_size = 16 , shuffle = True )
ds_test = torch . utils . data . TensorDataset ( X_test , y_test )
dataloader_test = torch . utils . data . DataLoader ( ds_test , batch_size = 16 , shuffle = True )我们进行一个训练环,仅通过其Sample_elbo方法对其损失进行损失而与普通火炬训练有所不同。所有其他事情都可以正常地完成,因为我们的闪电战的目的是在毫无麻烦的情况下使用不同的贝叶斯NN迭代数据。
这是我们非常简单的训练循环:
iteration = 0
for epoch in range ( 100 ):
for i , ( datapoints , labels ) in enumerate ( dataloader_train ):
optimizer . zero_grad ()
loss = regressor . sample_elbo ( inputs = datapoints ,
labels = labels ,
criterion = criterion ,
sample_nbr = 3 )
loss . backward ()
optimizer . step ()
iteration += 1
if iteration % 100 == 0 :
ic_acc , under_ci_upper , over_ci_lower = evaluate_regression ( regressor ,
X_test ,
y_test ,
samples = 25 ,
std_multiplier = 3 )
print ( "CI acc: {:.2f}, CI upper acc: {:.2f}, CI lower acc: {:.2f}" . format ( ic_acc , under_ci_upper , over_ci_lower ))
print ( "Loss: {:.4f}" . format ( loss ))一个非常快速的解释,即如何在贝叶斯神经网络中引入不确定性,以及我们如何建模其损失,以客观地提高对预测的信心并减少差异而无需辍学。
如我们所知,在确定性(非贝叶斯)神经网络层上,可训练的参数直接与上一个线性转换的权重(如果是这种情况,则是输入)。它对应于以下等式:
(z对应于i层的激活输出)
贝叶斯层试图通过从每个前馈操作的可训练变量参数的分布中对其进行对重量的不确定性引入不确定性。
这不仅使我们不仅可以优化模型的性能指标,而且还可以通过特定数据点(通过对其进行抽样次数并测量分散体)来收集网络预测的不确定性,并旨在尽可能减少网络差异而不是预测,从而使我们能够了解我们在标签上超过了我们尝试对特定的ITIT ITIN -DATINIT ITINITINITINITINITINIM ITINCONTIM notiboint oblestoint oblotib oblespoint aboint aboint aboint aboint aboint aboint aboint aboint oblotib aboint oblobers obloine noberaint oblober的功能。
为此,在每个进发操作上,我们都使用以下方程式采样线性转换的参数(其中ρ参数为标准偏差, μ参数为样本线性转换参数的平均值):
重量:
其中采样W对应于第n样品上ITH层的线性转换上使用的权重。
偏见:
其中采样B对应于第n个样本上ITH层的线性转换上使用的偏差。
即使很艰难,我们也有一个随机的乘数来适合自己的权重和偏见,可以通过对重量的一些可区分功能进行了优化,并且可以采样和可训练的参数(在我们的情况下为损失),将功能相对于两个功能的导数求和:
所以:
和
众所周知,Crossentropy损失(和MSE)是可区分的。因此,如果我们证明存在可区分的复杂性成本函数,则可以将其保留到我们的框架上,以衍生物为例,并在优化步骤中计算梯度。
每个贝叶斯层都计算出复杂性成本(在前馈操作上)(具有预定的较抽动器Apriori分布及其经验分布)。每层的复杂性成本的总和总结为损失。
正如神经网络论文中的重量不确定性所提出的那样,我们可以通过将kullback-leibler差异从中获得分布的复杂性成本来收集分布的复杂性成本,并通过进行一些近似值来收集分布的分布,并且我们可以将此功能相对于其变量(分布)(分布)区分(分布):
设为手工设置的低透镜分布PDF,将其假定为重量的“先验”分布
鉴于其参数,令我们作为采样权重的A后验经验分布PDF。
因此,对于W采样矩阵上的每个标量:
通过假设n很大,我们可以近似:
因此:
由于Q分布的预期(平均值)仅通过缩放值而结束,因此我们可以将其从方程式中取出(因为不会有框架追踪)。将第n个样本的复杂性成本为:
相对于其所有参数,这是可区分的。
因此,第n个权重样本上的整个成本函数将是:
我们可以通过对蒙特卡洛进行抽样(将Netwok X次并承担全部损失的平均值),然后使用我们的估计值倒流来估算真正的全部成本函数。它适用于每个后退次数少的实验,甚至用于单一实验。
简而言之,我们进入了贝叶斯深度学习的尽头。通过知道这里正在做什么,您可以按照自己的意愿实施BNN模型。
也许您可以通过每次样本进行优化的步骤来优化,或者使用这种蒙特 - 卡洛语方法来收集损失,以均值,然后以优化器来收集损失。你的举动。
仅供参考:我们的贝叶斯层和Utils有助于计算每个进料操作上层的复杂性成本,因此请不要介意太多。
如果您在研究中使用BLiTZ ,则可以如下引用:
@misc { esposito2020blitzbdl ,
author = { Piero Esposito } ,
title = { BLiTZ - Bayesian Layers in Torch Zoo (a Bayesian Deep Learing library for Torch) } ,
year = { 2020 } ,
publisher = { GitHub } ,
journal = { GitHub repository } ,
howpublished = { url{https://github.com/piEsposito/blitz-bayesian-deep-learning/} } ,
}