百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

贝叶斯神经网络:入门(贝叶斯神经网络原理)

toyiye 2024-09-04 20:14 3 浏览 0 评论

贝叶斯神经网络:入门

什么是贝叶斯推断?理解先验、似然和后验

贝叶斯推断是一种统计方法,它涉及随着更多证据或信息的获取而更新假设的概率。这个过程使用贝叶斯定理,这是概率理论中的一个基本原则,它将随机事件的条件概率和边际概率联系起来。

贝叶斯推断使我们能够纳入先验信念,在观察到新数据时更新这些信念,并得出一个反映先验和新数据的后验信念。让我们分解贝叶斯推断的关键组件:先验、似然和后验。

先验、似然和后验:贝叶斯推断的基础构件

1. 先验 p(theta)\ 先验代表我们在看到任何数据之前对参数(theta)的初始信念。它是一个概率分布,概括了我们现有的知识或假设。例如,如果我们估计硬币落地为正面的概率,我们可能假设一个均匀的先验(p(theta) = 0.5),表示公正的硬币。

2. 似然 p(D \theta)\ 似然量化了在给定特定参数值(theta)的情况下观察到数据(D)的概率。它衡量了特定参数解释观察到的数据的程度。在我们的硬币示例中,如果我们在10次掷硬币中观察到7次正面,给定硬币是公平的(theta = 0.5),可以使用二项分布计算数据的似然。

3. 后验 p(theta \D)\ 后验表示在观察到数据 (D) 后关于参数 (theta) 的更新信念。它使用贝叶斯定理结合了先验和似然:\ p(theta\D) = p(D \theta) X p(theta)/p(D)

这里,( p(D)) 是证据,一个归一化项,确保后验分布的总和为 1。后验反映了初始信念和新证据,提供了参数的精确估计。

贝叶斯推断示例:抛硬币

想象一下我们想要估计硬币正面朝上的概率(theta)。我们从对硬币是公正的先验信念开始,因此我们分配 p(theta) = {Uniform}(0, 1)。经过 10 次掷硬币,我们观察到 7 次正面和 3 次反面。

- 先验: p(theta) = {均匀}(0, 1) — 我们假设0到1之间的所有概率是同等可能的。\ - 似然: p(D \theta) = {二项分布}(7次正面, 10次翻转, theta)\ - 后验: 在观察到数据后,后验将我们的先验信念与似然结合,以更新我们对(theta)的信念。

后验分布反映了我们对硬币正面朝上的概率的更新信念,这个信念是基于观察到的数据。

贝叶斯神经网络(BNNs)是什么?

贝叶斯神经网络(BNNs)将贝叶斯推断的概念扩展到神经网络中。在传统的神经网络中,权重被视为在训练过程中学习到的固定参数。然而,在BNNs中,权重被视为具有概率分布的随机变量。这种方法使BNNs能够通过考虑权重的不确定性来对预测中的不确定性建模。

贝叶斯神经网络中的后验

在BNN中,目标是计算给定训练数据的权重后验分布。我们定义:

- 权重 ( W ): 神经网络的参数。  
- 数据 ( D ) : 训练数据集,由输入-输出对组成。  
给定数据的权重的后验分布,p(W \D),使用贝叶斯定理计算:  
p(W \D) = p(D \W) X (p(W)/p(D))  
- 先验 ( p(W) ): 在观察任何数据之前对权重的初始信念。  
- 似然 ( p(D \W): 给定权重的数据的概率。  
- 后验 (p(W \ D) ): 在观察到数据后对权重的更新信念。  

使用MNIST展示贝叶斯神经网络

为了理解BNN在实际中的工作原理,我们将使用MNIST数据集,这是一个流行的数据集,包含28x28像素的手写数字(0-9)的灰度图像。我们的目标是使用贝叶斯卷积神经网络(CNN)对这些数字进行分类。

为什么在MNIST中使用贝叶斯神经网络?

1. 不确定性估计:BNNs 提供了对其预测的不确定性度量,这对于安全关键应用至关重要。\ 2. 抗过拟合能力:贝叶斯框架有助于对模型进行正则化,使其在数据稀缺时不易过拟合。\ 3. 更好的泛化能力:通过考虑权重的不确定性,BNNs 可以更好地泛化到未见过的数据。

代码解释:在MNIST上使用贝叶斯神经网络

我们将使用PyTorch构建一个贝叶斯神经网络,着重于实现BNN于MNIST的关键步骤。

1. 导入库和设置

我们首先导入必要的库并设置超参数。

import torch  
import torch.nn as nn  
import torch.nn.functional as F  
from torch.utils.data import DataLoader  
from torchvision import datasets, transforms  
import numpy as np  
import matplotlib.pyplot as plt  
# 超参数  
batch_size = 64  
learning_rate = 0.001  
epochs = 20  
n_samples = 10 # 用于不确定性估计的后验样本数量  
# 检查GPU  
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')  
print(f'Using device: {device}')

2. 加载 MNIST 数据集

我们加载MNIST数据集并应用标准的预处理转换,例如规范化图像。

# 数据加载与转换  
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])  
train_dataset = datasets.MNIST(root='./data', train=True, transform=transform, download=True)  
test_dataset = datasets.MNIST(root='./data', train=False, transform=transform, download=True)  
train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)  
test_loader = DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)

3. 定义贝叶斯卷积层

我们定义了一个自定义的贝叶斯卷积层(BayesianConv2d),它在每次前向传递中从高斯分布中采样权重。

class BayesianConv2d(nn.Module):  
 def __init__(self, in_channels, out_channels, kernel_size, stride=1, padding=0):  
 super(BayesianConv2d, self).__init__()  
 self.in_channels = in_channels  
 self.out_channels = out_channels  
 self.kernel_size = kernel_size  
 self.stride = stride  
 self.padding = padding  
# 权重参数  
 self.weight_mu = nn.Parameter(torch.Tensor(out_channels, in_channels, kernel_size, kernel_size).uniform_(-0.1, 0.1))  
 self.weight_logvar = nn.Parameter(torch.Tensor(out_channels, in_channels, kernel_size, kernel_size).uniform_(-3, -1))  
   
 # 偏置参数  
 self.bias_mu = nn.Parameter(torch.Tensor(out_channels).uniform_(-0.1, 0.1))  
 self.bias_logvar = nn.Parameter(torch.Tensor(out_channels).uniform_(-3, -1))  
def forward(self, x):  
 # 从正态分布中采样权重和偏置  
 weight = self.sample_weight()  
 bias = self.sample_bias()  
   
 # 卷积操作  
 return F.conv2d(x, weight, bias, stride=self.stride, padding=self.padding)  
def sample_weight(self):  
 # 从高斯后验中采样权重  
 return self.weight_mu + torch.exp(0.5 * self.weight_logvar) * torch.randn_like(self.weight_logvar).to(device)  
   
 def sample_bias(self):  
 # 从高斯后验中采样偏置  
 return self.bias_mu + torch.exp(0.5 * self.bias_logvar) * torch.randn_like(self.bias_logvar).to(device)  
def kl_divergence(self):  
 # 计算变分权重的KL散度  
 kl = 0.5 * torch.sum(  
 self.weight_mu**2 + torch.exp(self.weight_logvar) - 1 - self.weight_logvar  
 ) + 0.5 * torch.sum(  
 self.bias_mu**2 + torch.exp(self.bias_logvar) - 1 - self.bias_logvar  
 )  
 return kl

4. 定义具有CNN架构的贝叶斯神经网络(BNN)

我们使用利用贝叶斯推断的卷积层定义了一个BNN。

class BayesianCNN(nn.Module):  
 def __init__(self):  
 super(BayesianCNN, self).__init__()  
 self.conv1 = BayesianConv2d(1, 32, kernel_size=3, stride=1, padding=1)  
 self.conv2 = BayesianConv2d(32, 64, kernel_size=3, stride=1, padding=1)  
 self.fc1 = nn.Linear(64 * 7 * 7, 128)  
 self.fc2 = nn.Linear(128, 10)  
def forward(self, x):  
 x = F.relu(self.conv1(x))  
 x = F.max_pool2d(x, 2)  
 x = F.relu(self.conv2(x))  
 x = F.max_pool2d(x, 2)  
 x = x.view(-1, 64 * 7 * 7) # 展平为全连接层  
 x = F.relu(self.fc1(x))  
 x = self.fc2(x)  
 return x  
def kl_divergence(self):  
 # 计算所有贝叶斯层的KL散度总和  
 kl = self.conv1.kl_divergence() + self.conv2.kl_divergence()  
 return kl  

5. 训练贝叶斯神经网络

训练函数使用证据下界(ELBO)损失训练BNN,该损失结合了负对数似然和KL散度。

def elbo_loss(output, target, kl_divergence, beta=1.0):  
 # 交叉熵损失(负对数似然)  
 nll = F.cross_entropy(output, target, reduction='mean')  
 # ELBO损失  
 elbo = nll + beta * kl_divergence / len(train_loader.dataset)  
 return elbo  
model = BayesianCNN().to(device)  
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)  
def train(model, train_loader, optimizer, epochs):  
 model.train()  
 for epoch in range(epochs):  
 total_loss = 0  
 for batch_idx, (data, target) in enumerate(train_loader):  
 data, target = data.to(device), target.to(device)  
   
 optimizer.zero_grad()  
 output = model(data)  
 kl_divergence = model.kl_divergence()  
 loss = elbo_loss(output, target, kl_divergence)  
 loss.backward()  
 optimizer.step()  
   
 total_loss += loss.item()  
print(f"Epoch {epoch+1}/{epochs}, Loss: {total_loss / len(train_loader)}")  
# 训练模型  
train(model, train_loader, optimizer, epochs)  
6. 不确定性估计的推理  
最后,我们通过多次采样权重来进行推理,并估计预测的均值和不确定性。  
def predict_with_sampling(model, data, n_samples):  
 model.eval()  
 output_samples = []  
with torch.no_grad():  
 for _ in range(n_samples):  
 output_samples.append(model(data)) # 在每次前向传递过程中采样权重  
output_samples = torch.stack(output_samples)  
 mean_output = torch.mean(output_samples, dim=0)  
 std_output = torch.std(output_samples, dim=0)  
   
 return mean_output, std_output  
# 示例:获取一批的预测和置信区间  
examples = enumerate(test_loader)  
batch_idx, (example_data, example_targets) = next(examples)  
example_data = example_data.to(device)  
# 使用采样进行推理  
mean_output, std_output = predict_with_sampling(model, example_data, n_samples)  
# 显示一些图像及其预测置信度  
plt.figure(figsize=(10, 5))  
for i in range(6):  
 plt.subplot(2, 3, i+1)  
 plt.imshow(example_data[i].cpu().numpy().squeeze(), cmap='gray')  
 pred_prob = torch.softmax(mean_output[i], dim=0) # 对均值输出应用softmax  
 pred_class = torch.argmax(pred_prob).item() # 选择概率最高的类别  
 plt.title(f'Pred: {pred_class}, Conf: {pred_prob.max():.2f}')  
 plt.axis('off')  
plt.show()

Conclusion

贝叶斯神经网络(BNNs)提供了一种通过将权重视为随机变量来估计神经网络预测中的不确定性的原则方式。通过贝叶斯推断,BNNs不仅可以提供点估计,还可以提供置信区间,使其在不确定性估计至关重要的应用中变得非常有价值。使用MNIST数据集,我们展示了如何使用PyTorch构建和训练BNN,展示了贝叶斯方法在深度学习中的强大能力。

通过理解和利用贝叶斯技术,我们可以创造出更稳健和可解释的机器学习模型,使其更好地应对现实世界场景中的不确定性。

相关推荐

# Python 3 # Python 3字典Dictionary(1)

Python3字典字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({})中,格式如...

Python第八课:数据类型中的字典及其函数与方法

Python3字典字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值...

Python中字典详解(python 中字典)

字典是Python中使用键进行索引的重要数据结构。它们是无序的项序列(键值对),这意味着顺序不被保留。键是不可变的。与列表一样,字典的值可以保存异构数据,即整数、浮点、字符串、NaN、布尔值、列表、数...

Python3.9又更新了:dict内置新功能,正式版十月见面

机器之心报道参与:一鸣、JaminPython3.8的热乎劲还没过去,Python就又双叒叕要更新了。近日,3.9版本的第四个alpha版已经开源。从文档中,我们可以看到官方透露的对dic...

Python3 基本数据类型详解(python三种基本数据类型)

文章来源:加米谷大数据Python中的变量不需要声明。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建。在Python中,变量就是变量,它没有类型,我们所说的"类型"是变...

一文掌握Python的字典(python字典用法大全)

字典是Python中最强大、最灵活的内置数据结构之一。它们允许存储键值对,从而实现高效的数据检索、操作和组织。本文深入探讨了字典,涵盖了它们的创建、操作和高级用法,以帮助中级Python开发...

超级完整|Python字典详解(python字典的方法或操作)

一、字典概述01字典的格式Python字典是一种可变容器模型,且可存储任意类型对象,如字符串、数字、元组等其他容器模型。字典的每个键值key=>value对用冒号:分割,每个对之间用逗号,...

Python3.9版本新特性:字典合并操作的详细解读

处于测试阶段的Python3.9版本中有一个新特性:我们在使用Python字典时,将能够编写出更可读、更紧凑的代码啦!Python版本你现在使用哪种版本的Python?3.7分?3.5分?还是2.7...

python 自学,字典3(一些例子)(python字典有哪些基本操作)

例子11;如何批量复制字典里的内容2;如何批量修改字典的内容3;如何批量修改字典里某些指定的内容...

Python3.9中的字典合并和更新,几乎影响了所有Python程序员

全文共2837字,预计学习时长9分钟Python3.9正在积极开发,并计划于今年10月发布。2月26日,开发团队发布了alpha4版本。该版本引入了新的合并(|)和更新(|=)运算符,这个新特性几乎...

Python3大字典:《Python3自学速查手册.pdf》限时下载中

最近有人会想了,2022了,想学Python晚不晚,学习python有前途吗?IT行业行业薪资高,发展前景好,是很多求职群里严重的香饽饽,而要进入这个高薪行业,也不是那么轻而易举的,拿信工专业的大学生...

python学习——字典(python字典基本操作)

字典Python的字典数据类型是基于hash散列算法实现的,采用键值对(key:value)的形式,根据key的值计算value的地址,具有非常快的查取和插入速度。但它是无序的,包含的元素个数不限,值...

324页清华教授撰写【Python 3 菜鸟查询手册】火了,小白入门字典

如何入门学习python...

Python3.9中的字典合并和更新,了解一下

全文共2837字,预计学习时长9分钟Python3.9正在积极开发,并计划于今年10月发布。2月26日,开发团队发布了alpha4版本。该版本引入了新的合并(|)和更新(|=)运算符,这个新特性几乎...

python3基础之字典(python中字典的基本操作)

字典和列表一样,也是python内置的一种数据结构。字典的结构如下图:列表用中括号[]把元素包起来,而字典是用大括号{}把元素包起来,只不过字典的每一个元素都包含键和值两部分。键和值是一一对应的...

取消回复欢迎 发表评论:

请填写验证码