贝叶斯神经网络bnn pyro 包 bayesian-neural-network在人工智能领域应用,预测金融市场价格

在人工智能领域,预测金融市场价格一直是一个热门话题。本文将介绍一种新颖的方法——贝叶斯神经网络,用于预测市场动态,以虚拟货币“以太币”为例进行说明。

### 贝叶斯神经网络:一种新视角

对于希望深入了解贝叶斯神经网络的读者,以下是一些推荐的资源:

- [PyMC3](https://github.com/pymc-devs/pymc3):一个Python库,用于贝叶斯统计建模和概率机器学习。

PyMC3视频教程 space.bilibili.com/259953362/channel/seriesdetail?sid=2637173

银色狮子巴壁虎的个人空间-银色狮子巴壁虎个人主页-哔哩哔哩视频


- [Edward](http://edwardlib.org/):一个用于概率建模、推断和深度学习的库。
- [Pyro](http://pyro.ai/):一个灵活的通用概率编程框架。

pypro 镜像

GitCode - 全球开发者的开源社区,开源代码托管平
gitcode.com/gh_mirrors/py/pyro/tree/dev/pyro/contrib/bnn

教程和实例

【注意这里的代码是python2.7 对应的pyro都版本也比较低】

可以在[这个GitHub仓库](https://github.com/Rachnog/Deep-Trading/tree/master/bayesian)找到相关的代码示例和教程。通过这些资源,读者可以更深入地理解贝叶斯方法,并将其应用于自己的项目

其他一些人资源 

atomgit.com

AtomGit_开放原子开源基金会代码托管平台-AtomGit

开源项目 - 开放原子开源基金会 www.openatom.cn/projects

使用Pytorch和Pyro实现贝叶斯神经网络(Bayesian Neural Network)_gang_akarui-开放原子开发者工作坊


入门|文档|社区|贡献

Pyro是基于PyTorch构建的一个灵活、可伸缩的深层概率编程库。值得注意的是,它的设计考虑了以下原则:

  • 通用:Pyro是一个通用的PPL-它可以表示任何可计算的概率分布。
  • 可伸缩性:与hand-written代码相比,Pyro可以以很少的开销扩展到大型数据集。
  • 最小:Pyro是敏捷的,可维护的。它是用一个强大的、可组合的抽象的小核心实现的。
  • 灵活:Pyro的目标是在需要时实现自动化,在需要时进行控制。这是通过high-level抽象来表达生成和推理模型的,同时允许专家easy-access定制推理。

Pyro由Uber人工智能实验室和社区贡献者开发和维护。更多信息,请查看我们的博客文章。

Installing

安装稳定的Pyro释放装置

使用pip安装:

Pyro支持python3.4+。

pip install pyro-ppl

从源安装:

git clone git@github.com:pyro-ppl/pyro.git
cd pyro
git checkout master  # master is pinned to the latest release
pip install .

使用额外的软件包安装:

要安装运行examples/tutorials目录中包含的概率模型所需的依赖项,请使用以下命令:

pip install pyro-ppl[extras]

请确保这些模型与您安装的Pyro源代码版本相同。

安装Pyro dev分支

对于最近的特性,您可以从源代码安装Pyro。

使用pip安装:

pip install git+https://github.com/pyro-ppl/pyro.git

或者,使用extras依赖关系来运行examples/tutorials目录中包含的概率模型:

pip install git+https://github.com/pyro-ppl/pyro.git#egg=project[extras]

从源安装:

git clone https://github.com/pyro-ppl/pyro
cd pyro
pip install .  # pip install .[extras] for running models in examples/tutorials

从Docker容器运行Pyro

请参阅此处的说明。

Citation

如果您使用Pyro,请考虑引用:

@article{bingham2019pyro,
  author    = {Eli Bingham and
               Jonathan P. Chen and
               Martin Jankowiak and
               Fritz Obermeyer and
               Neeraj Pradhan and
               Theofanis Karaletsos and
               Rohit Singh and
               Paul A. Szerlip and
               Paul Horsfall and
               Noah D. Goodman},
  title     = {Pyro: Deep Universal Probabilistic Programming},
  journal   = {J. Mach. Learn. Res.},
  volume    = {20},
  pages     = {28:1--28:6},
  year      = {2019},
  url       = {http://jmlr.org/papers/v20/18-403.html}
}


传统的神经网络通过确定性的权重来学习模式,但这种方法在面对金融市场这种高度随机和动态的环境时可能会遇到过拟合的问题。贝叶斯神经网络通过引入概率分布来定义权重,从而为模型提供了一种内在的正则化机制。

#### 概率编程基础

概率编程是一种定义和操作概率模型的方法。它允许我们将模型中的参数视为随机变量,而不是固定的数值。这样,模型的输出就不再是单一的确定性值,而是一个概率分布,我们可以从中抽取样本来估计预测的不确定性。

#### 贝叶斯线性回归:一个简单示例

以太币价格预测的初步尝试是使用贝叶斯线性回归模型。这种模型将权重视为服从正态分布的随机变量,并通过变分推断来估计这些权重的后验分布。

#### 贝叶斯神经网络的构建

进一步,我们构建了一个包含隐藏层的贝叶斯神经网络。这个网络使用PyTorch框架,并通过Pyro库来定义概率模型。网络的每个层都有其对应的先验分布,这些分布定义了权重的初始状态。

#### 训练与预测

训练过程中,我们不仅更新网络的权重,还更新了权重的分布参数。预测时,我们可以从这些分布中抽取多个样本,计算预测结果的均值和标准差,从而得到预测的不确定性估计。

#### 结果分析

与传统的确定性神经网络相比,贝叶斯神经网络在预测以太币价格时显示出了更好的性能。更重要的是,它提供了对预测不确定性的量化,这对于金融决策至关重要。

#### 权重的稀疏性和正则化

贝叶斯方法的一个有趣特性是它能够在训练过程中自然地导致权重的稀疏性,这类似于L1正则化的效果。此外,权重的分布参数(如均值和方差)也为我们提供了对模型复杂度的控制。

#### 结论

贝叶斯神经网络为金融市场预测提供了一种强大的工具。它不仅能够处理数据的不确定性,还能够通过概率分布来自然地实现正则化,从而提高模型的泛化能力。随着人工智能技术的不断进步,这种方法有望在金融领域发挥更大的作用。

### 进一步探索

对于希望深入了解贝叶斯神经网络的读者,以下是一些推荐的资源:

- [PyMC3](https://github.com/pymc-devs/pymc3):一个Python库,用于贝叶斯统计建模和概率机器学习。
- [Edward](http://edwardlib.org/):一个用于概率建模、推断和深度学习的库。
- [Pyro](http://pyro.ai/):一个灵活的通用概率编程框架。

此外,对于想要实践贝叶斯神经网络的读者,可以在[这个GitHub仓库](https://github.com/Rachnog/Deep-Trading/tree/master/bayesian)找到相关的代码示例和教程。通过这些资源,读者可以更深入地理解贝叶斯方法,并将其应用于自己的项目中。

注意啊,pyro代码是2018年的代码,pyro 是0.318 左右,现在是1.8.

这里的pyro代码 已经不能在最新版本中运行了

最新的教程和资料看这个

  Pyro简介

镜像GitCode - 全球开发者的开源社区,开源代码托管平台

gitcode.com/gh_mirrors/py/pyro/blob/dev/tutorial/source/bayesian_regression_ii.ipynb

官方英文文档

Introduction to Pyro — Pyro Tutorials 1.9.1 documentation

pyro.ai/examples/intro_long.html#Example-model:-Maximum-likelihood-linear-regression

 Heyang Gong 汉化版本的文档 


causalai.github.io/pyro_zh_tutorial/tensor_shapes.html


这个是pyro的官方中文文档
 

阿姆斯特丹大学教程

notebooks-master\docs\tutorial_notebooks\DL2\Bayesian_Neural_Networks

pyro英语带中文字幕的介绍,

用Ubers Pyro介绍概率编程_哔哩哔哩_bilibili

其他资料 视频 教程 基于Pyro和Pytorch的概率编程入门01——简单线性回归的实现

银色狮子巴壁虎

基于Pyro和Pytorch的概率编程入门01——简单线性回归的实现_哔哩哔哩_bilibili

基于Pyro和Pytorch的概率编程入门02——pytorch的结构化数据加载与预处理_哔哩哔哩_bilibili

 基于Pyro和Pytorch的概率编程入门02——pytorch的结构化数据加载与预处理_哔哩哔哩_bilibili

还有pymc3 视频合集

银色狮子巴壁虎的个人空间-银色狮子巴壁虎个人主页-哔哩哔哩视频

概率模块包
Uber的Pyro基于Pytorch

Google的Edward基于TensorFlow

还有一些独立的像

PyMC3,

Stan,

Pomegranate等等

其他代码链接(python2.7 和pyro比较老的版本):

https://github.com/Rachnog/Deep-Trading/tree/master/bayesian

为了更深入了解概率编程、贝叶斯模型及其应用,我推荐以下资源给大家:

模式识别和机器学习:

http://www.springer.com/us/book/9780387310732

为黑客设计的贝叶斯方法:

https://www.amazon.com/Bayesian-Methods-Hackers-Probabilistic-Addison-Wesley/dp/0133902838

同时推荐以下python库:

PyMC3:

https://github.com/pymc-devs/pymc3

Edward:

http://edwardlib.org/

Pyro:

http://pyro.ai/


import torch
import pyro
from pyro.distributions import Normal
from pyro.infer import SVI, Trace_ELBO
from pyro.optim import Adam
from pyro.infer import Predictive
import pyro.distributions as dist
from pyro.infer import SVI, Trace_ELBO
from pyro.optim import Adam
from pyro.infer import Predictive
from pyro.nn import PyroModule, pyro_method, pyro_sample
from pyro.infer.autoguide import AutoDiagonalNormal
import pyro.distributions as dist
from pyro.infer import SVI, Trace_ELBO
from pyro.optim import Adam
from pyro.infer import Predictive
from pyro.nn import PyroModule, pyro_method, pyro_sample
from pyro.infer.autoguide import AutoDiagonalNormal
from pyro.infer import Predictive

# 定义 PyTorch 模型
class RegressionModel(torch.nn.Module):
    def __init__(self, p):
        super(RegressionModel, self).__init__()
        self.linear = torch.nn.Linear(p, 1)

    def forward(self, x):
        return self.linear(x)

# 定义 Pyro 概率模型
def model(data):
    p = data.shape[1] - 1  # 特征数量
    # 创建参数的单位正态先验
    mu = torch.zeros(1, p)
    sigma = torch.ones(1, p)
    bias_mu = torch.zeros(1)
    bias_sigma = torch.ones(1)
    w_prior = Normal(mu, sigma)
    b_prior = Normal(bias_mu, bias_sigma)
    priors = {'linear.weight': w_prior, 'linear.bias': b_prior}
    lifted_module = pyro.random_module("module", RegressionModel, priors)
    lifted_reg_model = lifted_module()
    with pyro.iarange("map", data.size(0)):
        x_data = data[:, :-1]
        y_data = data[:, -1]
        # 运行回归模型前向传播
        prediction_mean = lifted_reg_model(x_data).squeeze()
        pyro.sample("obs", Normal(prediction_mean, torch.ones(data.size(0))), obs=y_data.squeeze())

# 定义 guide 函数
def guide(data):
    p = data.shape[1] - 1  # 特征数量
    w_mu = torch.randn(1, p).type_as(data.data)
    w_log_sig = 0.1 * torch.ones(1, p).type_as(data.data)
    b_mu = torch.randn(1).type_as(data.data)
    b_log_sig = 0.1 * torch.ones(1).type_as(data.data)
    mw_param = pyro.param("guide_mean_weight", w_mu)
    sw_param = softplus(pyro.param("guide_log_sigma_weight", w_log_sig))
    mb_param = pyro.param("guide_mean_bias", b_mu)
    sb_param = softplus(pyro.param("guide_log_sigma_bias", b_log_sig))
    w_dist = Normal(mw_param, sw_param)
    b_dist = Normal(mb_param, sb_param)
    dists = {'linear.weight': w_dist, 'linear.bias': b_dist}
    lifted_module = pyro.random_module("module", RegressionModel, dists)
    return lifted_module()

# 定义软加函数
def softplus(x):
    return torch.log(1 + torch.exp(x))

# 定义训练循环
def train(data, n_steps=3000, batch_size=64):
    svi = SVI(model, guide, Adam({"lr": 0.01}), loss=Trace_ELBO())
    for j in range(n_steps):
        epoch_loss = 0.0
        perm = torch.randperm(data.size(0))
        data = data[perm]
        all_batches = get_batch_indices(data.size(0), batch_size)
        for ix, batch_start in enumerate(all_batches[:-1]):
            batch_end = all_batches[ix + 1]
            batch_data = data[batch_start: batch_end]
            epoch_loss += svi.step(batch_data)
        print("Epoch %d \t Loss: %.4f" % (j + 1, epoch_loss / len(all_batches[:-1])))

# 定义获取批次索引的函数
def get_batch_indices(N, batch_size):
    return [i for i in range(0, N, batch_size)]

# 假设 X_test 和 Y_test 是测试数据
# 训练模型
# train(X_train, Y_train)

# 预测并计算预测值的均值和标准差
preds = []
for i in range(100):
    sampled_reg_model = guide(X_test)
    pred = sampled_reg_model(X_test).data.numpy().flatten()
    preds.append(pred)

# 计算预测的均值和标准差
mean_preds = np.mean(preds, axis=0)
std_preds = np.std(preds, axis=0)

现在有很多经典的经济预测度量方法,例如 MSE、MAE 或 MAPE,它们都可能会让人困惑——错误率低并不意味着你的模型表现得好,验证它在测试集上的表现也十分重要,而这就是我们做的工作。

使用贝叶斯模型进行为期 30 天的预测

从图中我们可以看到,预测效果并不够好。但是预测图中最后的几个跳变的形状很不错,这给了我们一线希望。继续加油!

常规神经网络

在这个非常简单的模型进行实验后,我们想要尝试一些更有趣的神经网络。首先让我们利用 25 个带有线性激活的神经元的单隐层网络训练一个简单 ML

以下是格式化后的代码:

```python
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.callbacks import ReduceLROnPlateau, ModelCheckpoint

def get_model(input_size):
    main_input = Input(shape=(input_size,), name='main_input')
    x = Dense(25, activation='linear')(main_input)
    output = Dense(1, activation='linear', name='out')(x)
    final_model = Model(inputs=[main_input], outputs=[output])
    final_model.compile(optimizer='adam', loss='mse')
    return final_model

# 定义学习率衰减回调函数
reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.2, patience=5, min_lr=0.001)

# 定义模型检查点回调函数
checkpointer = ModelCheckpoint(filepath='model.h5', monitor='val_loss', save_best_only=True)

# 训练模型
model = get_model(len(X_train[0]))
history = model.fit(X_train, Y_train,
                    epochs=100,
                    batch_size=64,
                    verbose=1,
                    validation_data=(X_test, Y_test),
                    callbacks=[reduce_lr, checkpointer],
                    shuffle=True)
```

这段代码使用了 TensorFlow 和 Keras 库来构建和训练一个简单的神经网络模型。`get_model` 函数定义了模型的结构,包括输入层、一个隐藏层和一个输出层。模型使用均方误差(MSE)作为损失函数,并使用 Adam 优化器进行训练。

在训练过程中,使用了两个回调函数:

1. `ReduceLROnPlateau`:当验证集上的损失在一定数量的周期(`patience`)内没有改善时,减少学习率。
2. `ModelCheckpoint`:在每个周期结束时,如果验证集上的损失有所改善,则保存模型。

请确保在运行此代码之前已经安装了 TensorFlow 库,并且有适当的数据集 `X_train`, `Y_train`, `X_test`, `Y_test` 用于训练和验证模型。此外,`model.h5` 是用于保存最佳模型的文件路径,你可以根据需要修改这个路径。
 

其结果如下:

使用 Keras 神经网络进行为期 30 天的预测

我觉得这比简单的贝叶斯回归效果更差,此外这个模型不能得到确定性的估计,更重要的是,这个模型甚至没有正则化。

贝叶斯神经网络

现在我们用 PyTorch 来定义上文在 Keras 上训练的模型:

以下是格式化后的代码:

```python
import torch
import torch.nn as nn

class Net(nn.Module):
    def __init__(self, n_feature, n_hidden):
        super(Net, self).__init__()
        self.hidden = nn.Linear(n_feature, n_hidden)  # hidden layer
        self.predict = nn.Linear(n_hidden, 1)  # output layer

    def forward(self, x):
        x = self.hidden(x)
        x = self.predict(x)
        return x
```

这段代码定义了一个简单的神经网络类 `Net`,它继承自 `torch.nn.Module`。网络包含一个隐藏层和一个输出层:

- `self.hidden` 是一个线性层,它将输入特征从 `n_feature` 维映射到 `n_hidden` 维。
- `self.predict` 是另一个线性层,它将隐藏层的输出映射到一个输出值。

`forward` 方法定义了数据通过网络的前向传播路径。当给网络一个输入 `x` 时,它首先通过隐藏层,然后通过输出层,最终返回预测结果。
 

相比于贝叶斯回归模型,我们现在有两个参数集(从输入层到隐藏层的参数和隐藏层到输出层的参数),所以我们需要对分布和先验知识稍加改动,以适应我们的模型:

请不要忘记为模型中的每一个分布起一个不同的名字,因为模型中不应存在任何歧义和重复。更多代码细节请参见源代码:https://github.com/Rachnog/Deep-Trading/tree/master/bayesian

以下是格式化后的代码:

```python
# 定义先验分布
priors = {
    'hidden.weight': w_prior,
    'hidden.bias': b_prior,
    'predict.weight': w_prior2,
    'predict.bias': b_prior2
}
以及 guide 部分:

# 定义 guide 部分的分布
dists = {
    'hidden.weight': w_dist,
    'hidden.bias': b_dist,
    'predict.weight': w_dist2,
    'predict.bias': b_dist2
}
```

这段代码展示了如何在 Pyro 模型中为不同的网络层设置先验分布和变分后验分布。`priors` 字典用于定义模型参数的先验分布,而 `dists` 字典用于定义 guide 函数中参数的分布。每个键对应网络中的一个参数(例如层的权重或偏置),每个值是对应参数的分布对象。
 

训练之后,让我们看看最后的结果:

使用 Pyro 神经网络进行为期 30 天的预测

它看起来比之前的结果都好得多!

比起常规贝叶斯模型,考虑到贝叶斯模型所中习得的权重特征或正则化,我还希望看到权重的数据。我按照以下方法查看 Pyro 模型的参数:

以下是格式化后的代码:

```python
import pyro
import tensorflow as tf

# Pyro 参数打印
for name in pyro.get_param_store().get_all_param_names():
    print(name, pyro.param(name).data.numpy())

# Keras 模型权重提取
sess = tf.Session()
with sess.as_default():
    tf.global_variables_initializer().run()
    dense_weights, out_weights = None, None
    with sess.as_default():
        for layer in model.layers:
            if len(layer.weights) > 0:
                weights = layer.get_weights()
                if 'dense' in layer.name:
                    dense_weights = layer.weights[0].eval()
                if 'out' in layer.name:
                    out_weights = layer.weights[0].eval()
```

这段代码分为两部分:

1. **Pyro 参数打印**:这部分代码遍历 Pyro 的参数存储,打印出每个参数的名称和值。`pyro.get_param_store().get_all_param_names()` 获取所有参数的名称,`pyro.param(name).data.numpy()` 获取参数的值并转换为 NumPy 数组。

2. **Keras 模型权重提取**:这部分代码使用 TensorFlow 会话(Session)来初始化模型的全局变量,并遍历模型的每一层。对于每一层,如果层有权重,它会检查层的名称是否包含 'dense' 或 'out'。如果是,它会评估(获取)相应的权重。

请注意,这段代码假设你已经定义了一个名为 `model` 的 Keras 模型。此外,由于 TensorFlow 2.x 版本中默认启用了 Eager Execution,你可能需要使用 TensorFlow 1.x 版本或者在 TensorFlow 2.x 中使用 `tf.compat.v1.Session` 来运行这段代码。如果你使用的是 TensorFlow 2.x,建议使用 Eager Execution 的方式来获取权重,而不是使用会话。
 

例如,Keras 模型最后一层的权重的均值和标准差分别为 -0.0025901748 和 0.30395043,Pyro 模型对应值为 0.0005974418 和 0.0005974418。数字小了很多,但效果真的不错!其实这就是 L2 或 Dropout 这种正则化算法要做的——把参数逼近到零,而我们可以用变分推理来实现它!隐藏层的权重变化更有趣。我们将一些权重向量绘制成图,蓝线是 Keras 模型的权重,橙线是 Pyro 模型的权重:

输入层与隐藏层之间的部分权重

真正有意思的不止是权重的均值与标准差变得小,还有一点是权重变得稀疏,所以基本上在训练中完成了第一个权重集的稀疏表示,以及第二个权重集的 L2 正则化,多么神奇!别忘了自己跑跑代码感受一下:https://github.com/Rachnog/Deep-Trading/tree/master/bayesian

小结

我们在文中使用了新颖的方法对神经网络进行训练。不同于顺序更新静态权重,我们是更新的是权重的分布。因此,我们可能获得有趣又有用的结果。我想强调的是,贝叶斯方法让我们在调整神经网络时不需要手动添加正则化,了解模型的不确定性,并尽可能使用更少的数据来获得更好的结果。感谢阅读:)

教程

http://pyro.ai/examples/bayesian_regression.html

Bayesian Regression - Introduction (Part 1) — Pyro Tutorials 1.9.1 documentation

入门教程

实用烟火和PYTORCH

深度生成模型

离散潜在变量

定制推理

应用:时间序列

应用:高斯过程

应用:流行病学

应用:生物序列

应用:实验设计

应用:对象跟踪

其他推理算法

了解PYRO的内部结构

反对

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值