使用 Python 使用贝叶斯神经网络从理论到实践

一、说明

        在本文中,我们了解了如何构建一个机器学习模型,该模型结合了神经网络的强大功能,并且仍然保持概率方法进行预测。为了做到这一点,我们可以构建所谓的贝叶斯神经网络
        这个想法不是优化神经网络的损失,而是优化无限神经网络的损失。换句话说,我们正在优化给定数据集的模型参数的概率分布。

        我们使用损失函数来做到这一点,该函数包含称为 Kullback-Leibler 背离的指标。这用于计算两个分布之间的距离。

        在优化了损失函数之后,我们能够使用概率模型。 这意味着,如果我们重复这个模型两次,我们会得到两个不同的结果,如果我们重复 10k 次,我们就能提取出结果的稳健统计分布。

        我们使用 torch 和一个名为 torchbnn 的库来实现了这一点。我们构建了简单的回归任务,并使用两层前馈神经网络对其进行了求解。

二、物理学家和工程学家

        物理学和工程学是两门截然不同的科学,它们都渴望了解自然和模拟自然的能力。

        物理学家的方法更具理论性。物理学家观察世界,并试图以最准确的方式对其进行建模。物理学家建模的现实是不完美的,并且有近似值,但一旦我们考虑这些不完美,现实就会变得整洁、完美优雅。

        工程师的方法更实用。工程师意识到物理学家模型的所有局限性,并试图使实验室中的体验尽可能流畅。工程师可能会做更残酷的近似(例如 pi = 3),但它的近似实际上在现实生活中的实验中更有效。

        戈登·林赛·格莱格(Gordon Lindsay Glegg)的这句话总结了工程师的实践方法与物理学家优雅的理论方法之间的这种差异:

科学家可以发现一颗新星,但他不能制造一颗新星。他必须请工程师为他做这件事。

        在研究人员的日常生活中,它有点像这样工作。物理学家是对特定现象有理论的人。工程师是科学家,可以设置实验并查看理论是否有效。

        实际上,当我开始从物理学家到工程师的转变时,我经常被问到的一个问题是

“好的,你的模型似乎有效......但它有多强大呢?

这是一个典型的工程师问题。

当你有一个物理模型时,在一定条件下,这个模型在理论上是完美的


皮耶罗·帕亚伦加 

 

        尽管如此,当你进行实验时,存在一定程度的误差,你必须能够正确地估计它。

图片由作者提供

        在我们正在做的这个具体例子中,我们如何估计理论输出和实验结果之间的能量差异?

        两个选项:

        一个。如果模型是确定性的,则可以按某个增量更改初始条件(例如,将该确定性规则应用于输入的嘈杂版本)

        B.如果模型是概率的,对于某些给定的输入,您可以从输出中提取一些统计信息(例如平均值、标准差、不确定性边界......

        现在让我们进入机器学习的语言。 在此特定情况下:

        一个。如果机器学习模型是确定性的,我们可以通过打乱训练集和验证集来测试其鲁棒性。

        B.如果机器学习模型是概率的,对于某些给定的输入,你可以从输出中提取一些统计信息(例如平均值、标准差、不确定性边界......

        现在,假设我们要使用的模型是神经网络。
        第一个问题:你需要神经网络吗?如果答案是肯定的,那么你必须使用它(你不说)。问题:

“你的机器学习模型健壮吗?”

        神经网络的原始定义是“纯确定性”。
        我们可以对训练集、验证集和测试集进行洗牌,但我们需要考虑到神经网络可能需要很长时间来训练,如果我们想进行多个测试(假设 CV = 10,000),那么,您可能需要等待一段时间。

        我们需要考虑的另一件事是,神经网络使用一种称为梯度下降的算法进行优化。这个想法是,我们从参数空间中的一个点开始,顾名思义,沿着损失的负梯度指示的方向下降。理想情况下,这将把我们带到一个全局最小值(剧透:它实际上从来都不是全局的)。

        对于不切实际的简单一维损失函数,理想的情况如下:

        现在,在这种情况下,如果我们改变起点,我们仍然收敛到唯一的全局最小值。

        更现实的情况是这样的:

        因此,如果我们从不同的起点随机重启训练算法,我们会收敛到不同的局部最小值

        因此,如果我们从点 1 或点 3 开始,我们得到的点比起点 2 低。

        损失函数可能充满局部最小值,因此找到真正的全局最小值可能是一项艰巨的任务。我们可以做的另一件事是从不同的起点重新开始训练,并比较损失函数值。这种方法和以前一样,我们遇到了同样的问题:我们只能做这么多次。

        有一种更强大、更严格、更优雅的方法可以以概率的方式使用神经网络的相同计算能力;它称为贝叶斯神经网络。

        在本文中,我们将学习:

  1. 贝叶斯神经网络背后的理念
  2. 贝叶斯神经网络背后的数学公式
  3. 使用 Python 实现贝叶斯神经网络(更具体地说是 Pytorch)
  4. 如何使用贝叶斯神经网络解决回归问题

让我们开始吧!

三、什么是贝叶斯神经网络?

        正如我们之前所说,贝叶斯神经网络的思想是向典型的神经网络添加概率“感觉”。我们是怎么做到的?

        在理解贝叶斯神经网络之前,我们可能应该回顾一下贝叶斯定理。

        查看贝叶斯定理的一个非常有效的方法如下:

“贝叶斯定理是一个数学定理,它解释了为什么如果世界上所有的汽车都是蓝色的,那么我的车一定是蓝色的,但仅仅因为我的车是蓝色的,并不意味着世界上所有的汽车都是蓝色的。

        在数学术语中,给定事件“A”和“B”,给定事件“B”发生,事件“A”发生的概率如下:

        鉴于事件“A”已发生,事件“B”发生的概率如下:

链接第一个表达式和最后一个表达式的公式如下:

明白了?伟大。现在,假设你有你的神经网络模型。这个神经网络只不过是一组参数,用于将给定的输入转换为所需的输出。

前馈神经网络(最简单的深度学习结构)通过将输入乘以参数矩阵来处理您的输入。然后,将非线性激活函数(这是神经网络的真正功能)应用于该矩阵乘法的结果。结果是下一层的输入,其中应用了相同的过程。

现在,我们将模型的参数集称为 w。现在我们可以问自己这个棘手的问题。

假设我有一个数据集 D,它是一组输入x_i和输出y_i对,例如,动物的第 i 张图像和第 i 张标签(猫或狗):

给定某个数据集 D,拥有一组参数的概率是多少?

您可能需要阅读这个问题 3 或 4 遍才能掌握它,但这个想法就在那里。如果输入和输出之间有一定的映射,则在极端确定性情况下,只有一组参数能够处理输入并带来所需的输出。以概率方式,将存在一组参数,该参数集比另一个参数更可能。

所以我们感兴趣的是数量。

现在,有三件事很酷:

  1.    当您考虑给定该分布的平均值时,您仍然可以将其视为标准神经网络模型。例如:

        方程的左手表示计算出的平均输出,右手表示所有可能的参数结果集的平均值 (N),概率分布为每个结果提供权重。

        2. 虽然 p(w|D)显然是一个谜,p(D|w)是我们总是可以研究的东西。如果我们将上面的等式用于一个巨大的 N,则不需要机器学习。你可以简单地说:“在给定某个神经网络的情况下尝试所有可能的模型,并使用上面的等式权衡所有可能的结果”

        3. 当我们得到 p 时,我们得到的不仅仅是一个机器学习模型;我们实际上得到了无限的机器学习模型。这意味着我们可以从您的预测中提取一些不确定性边界和统计信息。结果不仅是“10.23”,而且更像是“10.23,可能的误差为 0.50”。

我希望我炒作了你。让我们进入下一章

四、一些数学

我不希望这篇文章是闲聊,但我不希望它成为痛苦。如果您了解贝叶斯神经网络的概念,或者您已经知道它们背后的数学原理,请随时跳过本章。如果你想有一个参考,一个好的参考是以下。(动手贝叶斯神经网络 — 深度学习用户教程)

        现在这一切看起来很酷,但我认为,如果你是一个机器学习用户,你就会有这样的想法:

“我怎么能优化这么奇怪的生物呢?”

简短的回答是,“通过最大化:

        但我不认为这是不言自明的。

        在这种情况下,优化原则是找到分布 p(w|我们将这个分布称为 q,我们想要一个两个分布函数之间距离的度量。

我们将使用的指标称为 Kullback-Leibler 背离

        关于它的一些有趣的事实:

  1. 对于两个相等的分布,它是 0
  2. 如果两个分布的分母趋于零,而分子仍非零,则它是无穷大的
  3. 它是不对称的。

现在,您在上面看到的损失函数是 Kullback-Leibler 散度的代理量,它被称为证据下界 (ELBO)。

权重 q 的分布被认为是具有均值 mu 和方差 sigma2 的正态分布:

        因此,优化是关于确定该分布的最佳 mu 和 sigma 值。

        在实际的 PyTorch 实现中,分布均值和目标之间的 MSE 也被添加到我们的 L (mu, sigma) 中。

五、pyt(orch)hon 实现

        借助名为 torchbnn 的库,使用 PyTorch 在 Python 中实现贝叶斯神经网络非常简单。

安装它非常容易:

pip install torchbnn

正如我们将看到的,我们将构建一些与标准 Tor 神经网络非常相似的东西:

model = nn.Sequential(bnn.BayesLinear(prior_mu=0, prior_sigma=0.1, in_features=1, out_features=1000),nn.ReLU(),bnn.BayesLinear(prior_mu=0, prior_sigma=0.1, in_features=1000, out_features=1),
)

实际上,有一个库可以将您的火炬模型转换为其贝叶斯代理项:

transform_model(model, nn.Conv2d, bnn.BayesConv2d, args={"prior_mu":0, "prior_sigma":0.1, "in_channels" : ".in_channels","out_channels" : ".out_channels", "kernel_size" : ".kernel_size","stride" : ".stride", "padding" : ".padding", "bias":".bias"}, attrs={"weight_mu" : ".weight"})

但是,让我们做一个动手的详细示例:

六、动手回归任务

首先要做的是导入一些库:

import numpy as np
from sklearn import datasets
import torch
import torch.nn as nn
import torch.optim as optim
import torchbnn as bnn
import matplotlib.pyplot as plt

之后,我们将制作非常简单的二维数据集:

x = torch.linspace(-2, 2, 500)
y = x.pow(5) -10* x.pow(1) + 2*torch.rand(x.size())
x = torch.unsqueeze(x, dim=1)
y = torch.unsqueeze(y, dim=1)plt.scatter(x.data.numpy(), y.data.numpy())
plt.show()

因此,给定我们的 1D 输入 x(范围从 -2 到 2),我们希望找到我们的 y。

def clean_target(x):return x.pow(5) -10* x.pow(1)+1
def target(x):return x.pow(5) -10* x.pow(1) + 2*torch.rand(x.size())

Clean_target 是我们的地面实况生成器,Target 是嘈杂的数据生成器。

现在我们将定义贝叶斯前馈神经网络:

model = nn.Sequential(bnn.BayesLinear(prior_mu=0, prior_sigma=0.1, in_features=1, out_features=1000),nn.ReLU(),bnn.BayesLinear(prior_mu=0, prior_sigma=0.1, in_features=1000, out_features=1),
)

正如我们所看到的,它是一个具有贝叶斯层的两层前馈神经网络。这将使我们能够获得概率输出。

现在我们将定义我们的 MSE 损失和剩余的 Kullback-Leibler 背离:

mse_loss = nn.MSELoss()
kl_loss = bnn.BKLLoss(reduction='mean', last_layer_only=False)
kl_weight = 0.01optimizer = optim.Adam(model.parameters(), lr=0.01)

这两个损失都将用于我们的优化步骤:

for step in range(2000):pre = model(x)mse = mse_loss(pre, y)kl = kl_loss(model)cost = mse + kl_weight*kloptimizer.zero_grad()cost.backward()optimizer.step()print('- MSE : %2.2f, KL : %2.2f' % (mse.item(), kl.item()))

已经使用了 2000 个 epoch。

让我们定义我们的测试集:

x_test = torch.linspace(-2, 2, 300)
y_test = target(x_test)x_test = torch.unsqueeze(x_test, dim=1)
y_test = torch.unsqueeze(y_test, dim=1)

现在,模型类的结果是概率性的。这意味着,如果我们运行模型 10,000 次,我们将得到 10,000 个略有不同的值。对于从 -2 到 2 的每个数据点,我们将得到平均值和标准差,

models_result = np.array([model(x_test).data.numpy() for k in range(10000)])
models_result = models_result[:,:,0]    
models_result = models_result.T
mean_values = np.array([models_result[i].mean() for i in range(len(models_result))])
std_values = np.array([models_result[i].std() for i in range(len(models_result))])

我们将绘制我们的置信区间。

plt.figure(figsize=(10,8))
plt.plot(x_test.data.numpy(),mean_values,color='navy',lw=3,label='Predicted Mean Model')
plt.fill_between(x_test.data.numpy().T[0],mean_values-3.0*std_values,mean_values+3.0*std_values,alpha=0.2,color='navy',label='99.7% confidence interval')
#plt.plot(x_test.data.numpy(),mean_values,color='darkorange')
plt.plot(x_test.data.numpy(),y_test.data.numpy(),'.',color='darkorange',markersize=4,label='Test set')
plt.plot(x_test.data.numpy(),clean_target(x_test).data.numpy(),color='green',markersize=4,label='Target function')
plt.legend()
plt.xlabel('x')
plt.ylabel('y')

七、参考地址

         A. 在 LinkedIn  
        B. 订阅我的时事通讯。 

      From Theory to Practice with Bayesian Neural Network, Using Python | by Piero Paialunga | Towards Data Science

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/284205.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

zkSend — — 在Sui上发红包像发电子邮件一样简单

*12月14日,知名区块链媒体平台The Block发表了这篇关于对Mysten Labs联合创始人Adeniyi Abiodun的采访,文中“我们”指代该媒体,数据均为截止撰写文章时数据,以下是正文。 两年前,当五名前Facebook工程师创立Mysten L…

鸿海携手Porotech共同开启Micro LED新篇章 | 百能云芯

近日,鸿海集团决定进一步强化其在Micro LED(微发光二极体)技术领域的实力。为此,鸿海宣布将与英国半导体企业Porotech展开战略合作,旨在共同开发MicroLED微显示器,并在AR(扩增实境)应…

如何使用Promethues监控系统指标并进行告警

公众号「架构成长指南」,专注于生产实践、云原生、分布式系统、大数据技术分享。 前言 从零开始:使用Prometheus与Grafana搭建监控系统 克服网络障碍:Prometheus如何通过间接方式采集目标服务数据 在以上二节,我们介绍了如何使…

股东来了投资者权益知识竞赛规则

股东来了投资者权益知识竞赛是中证中小投资者服务中心在中国证监会指导下,围绕中小投资者需求创办的全国性投教活动。《股东来了》(2023)由投资者服务中心联合北京、浙江、甘肃、新疆四地证监局共同举办,活动覆盖全国36个赛区及港…

【Python】__init__.py文件的使用

原文作者:我辈李想 版权声明:文章原创,转载时请务必加上原文超链接、作者信息和本声明。 文章目录 前言一、__init__.py文件1.不创建__init__.py文件2.创建__init__.py文件 二、使用1.设置公共参数2.写from .** import **3.__all__ import * …

PyQt6 简单介绍与安装

前言,主要由这两篇文章参考并总结部分内容而成,参考文章一 && 参考文章二 PyQt6 简单介绍与安装 1、简单介绍2、PyQt6安装3、PyQt6版本查看4、PyQt6模块4.1 界面承载部分( 控件 )4.2 界面框架部分(布局)4.3 界面组件部分&…

IDEA的debug调用(超详细)

借鉴链接:IDEA中的debug断点调试技巧 简述:会F8和F9就够吃饭了~ debug顶部栏 :::tips Show Execution Point (Alt F10):如果你的光标在其它行或其它页面,点击这个按钮可跳转到当前代码执行的行,即断点的位置&#…

JDBC 数据库连接池

目录 一、什么是数据库连接池二、为什么需要数据库连接池?三、JDBC 数据库连接池的实现四、C3P0的使用1、加入c3p0 jar包2、配置xml文件3、c3p0-config.xml模板4、C3P0的使用 五、Druid的使用1、加入Druid jar包2、定义配置文件:3、Druid连接池的使用 六、HikariCP的…

瑞安籍侨领池万进荣任意大利瑞安同乡总会第五届会长

浙江温州瑞安是全国重点侨乡,拥有海外侨胞16万人、侨领2100多名、归侨侨眷近12万人,在世界100多个国家和地区建有70多个侨团组织。 意大利瑞安同乡总会第五届理事会会长团全体成员 青年部全体成员 各兄弟会长及代表 12月10日,意大利瑞安同乡…

【海报】新年海报 制作

准备一张写好文字的图片。 模型&#xff1a; 电商\lofi_v4.safetensors [9462506675] best quality,masterpiece,8k,(soft lighting:1.2),firecrackers,Chinese new year,<lora:全网首发丨新年红包封面_v1.0:1>, 虚假&#xff0c;不真实&#xff0c;绘画&#xff0c;线条…

关于“Python”的核心知识点整理大全27

目录 10.5 小结 第&#xff11;1 章 测试代码 11.1 测试函数 name_function.py 函数get_formatted_name()将名和姓合并成姓名&#xff0c;在名和姓之间加上一个空格&#xff0c;并将它们的 首字母都大写&#xff0c;再返回结果。为核实get_formatted_name()像期望的那样工…

企业常用的高速数据传输方式

数据传输是指在计算机系统或网络中&#xff0c;将数据从一个设备或节点发送到另一个设备或节点的过程。数据传输的速度和质量直接影响企业的业务效率、竞争力和安全性。随着信息技术的不断发展&#xff0c;企业面临着越来越多的数据传输需求&#xff0c;因此需要选择适用的高速…