网易首页 > 网易号 > 正文 申请入驻

手把手:基于概率编程Pyro的金融预测,让正则化结果更有趣!

0
分享至

大数据文摘作品

编译:修竹、笪洁琼、夏雅薇

作者用了一种新奇的方法来训练神经网络。更新权重的分布而不是顺序更新静态权重,得到了更有趣和可靠的结果。贝叶斯方法给了我们一个机会,使得我们可以不手动添加正则项的情况下对神经网络进行正则化,理解模型的不确定性,并尽可能使用更少的数据得到更好的结果。

Hi!又见面啦。去年我推出了几篇基于神经网络的金融预测教程,我认为有些结果还是蛮有趣的,值得应用在实际交易中。

如果你读过那些教程,你一定会注意到,当你试图在“随机”数据上用一些机器学习模型并且希望找到隐藏模式时,你其实正逐渐对训练集进行过拟合。

我们使用不同的正则化方法和补充数据来解决这个问题,但是这非常耗时间并且有点盲目搜索了。

今天我想介绍一种稍微不同的方法来用于相同的算法。从概率角度讲,我们可以从数据本身学习正则化方法,在我们预测中估计准确性,使用更少的数据来训练并且在模型中加入概率依赖。

我不会深入到贝叶斯模型或变分推理的技术或者数学细节上,我将给出一些概述,同时也会更加关注如何应用。像往常一样,你可以在下面的链接内查看代码。

代码链接:

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/

概率编程

这个概率性的东西是什么,而且我们为什么要称之为编程呢?首先,我们先回忆一下“正常”的神经网络以及我们能从中获得什么。

我们有参数(权重),这些参数以矩阵表示,输出通常是一些标量值或者向量(例如用于分类时)。比如说,在用SGD训练模型之后,我们有了这些固定矩阵和网络在相同的输入样本上输出相同的向量。完全正确!

但是如果我们认为这些参数和输出都是互相依赖的分布呢?

神经网络中的每个权重都是来自某个分布的样本,输出也一样,每个输入来自整个网络的样本,同时这个网络依赖参数的样本。它给予了我们什么?

我们从最基础的开始讲。

如果我们把网络看成一组彼此依赖的分布,首先定义联合概率分布为p(y, z|x),输出为y,还有一些依赖输入x 的模型“内部”、隐藏参数z(和普通神经网络一样)。

而我们想要找到一种神经网络分布,我们可以对y ~ p(y|x)采样然后把分布作为输出(该分布的样本期望值通常就是输出,标准差用来评估不确定性,如果分布模型的尾部越大,我们对于输出越没有信心)。

这个设置或多或少已经很清楚了,我们只需要记住,现在所有的参数,不管是模型的输入还是输出,都是分布。我们需要的训练是找到这些分布的参数以便在实际任务中获得更高的准确率。

必须要提到的是,参数分布的形状是我们自己设置的(例如,所有的初始权重都是w ~ Normal(0, 1),然后我们将学习正确的均值和方差)。

初始分布称之为先验分布,使用过训练数据拟合参数的分布叫做后验分布。后者用于取样和获得输出数据。

模型的拟合效果怎么样呢?一般的框架叫做变分推理。我们不去深入了解细节,在这里我们需要寻找的模型是可以最大化似然函数log p_w(z|x)的, w 是模型的参数(分布参数),z是隐藏变量(隐藏神经元输出,从参数为 w 的分布中取样得到的),x是输入数据样本。这就是我们的模型。

在Pyro库中我们引入了一个实例作为这个模型的指导,指导中包括一些对所有隐藏变量q_ф(z)的分布,其中 ф叫做变分参数。这个分布必须近似于拟合数据最好的模型参数的“真实”分布。

训练的目的是最小化一个指导中关于输入数据和样本[log(p_w(z|x))—log(q_ф(z))] 的期望。我们这里不讨论训练过程的细节,因为这里面包含好几门大学课程,现在我们就做黑盒优化好了。

哦对了,为什么是编程呢?因为我们通常将这种概率模型(比如神经网络)描述为从一个变量到另一个变量的有向图,这样我们就可以直接表示变量的依赖性:

最初这种概率编程语言被用来定义这些模型并对其进行推断。

为什么用概率编程?

你可以将它认为是一种附加的隐藏变量,从数据中学习模型,而不是采用在模型中注入dropout或L1正则化的方法。

考虑到所有权重都是分布,你可以从中进行N次抽样然后得到输出的分布,通过标准差可以估算你的模型对于结果的准确性。

而且还有个不错的赠礼就是我们只需要用更少的数据来训练模型,并且我们可以在变量间灵活的增加不同的依赖关系。

为什么不用概率编程呢?

我对于使用贝叶斯模型没有太多经验,但就我从Pyro和PyMC3学习中可以知道,训练过程耗时很长而且很难定义准确的先验分布。此外,处理分布的多个样本会导致误解和歧义。

数据展示

我获取了以太坊每日价格。这里面包括典型OHLCV(高开低走)元组以及每天关于以太坊推特的数量。

以太坊价格来源:

https://bitinfocharts.com/

我们将使用7天的价格、交易量和推特数量变化的百分比来预测下一天变化的百分比。

价格、推特数量和交易量变化

上图所示是数据的样本——蓝色表示价格变化,黄色表示推特数量变化,绿色表示交易量变化。这些值(0.1-0.2)之间有一些正相关,所以我们希望利用一些数据训练模型。

贝叶斯线性回归

首先我想了解简单线性回归在我们任务中的表现。

Pyro官方教程:

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

我们在PyTorch中定义了我们模型(详细解释请看官方教程):

class RegressionModel(nn.Module):
def __init__(self, p):
super(RegressionModel, self).__init__()
self.linear = nn.Linear(p, 1)
def forward(self, x):
# x * w + b
return self.linear(x)

这只是我们曾经用过的一个简单确定性模型,但是这也是在Pyro中定义概率的方法。

def model(data):
# Create unit normal priors over the parameters
mu = Variable(torch.zeros(1, p)).type_as(data)
sigma = Variable(torch.ones(1, p)).type_as(data)
bias_mu = Variable(torch.zeros(1)).type_as(data)
bias_sigma = Variable(torch.ones(1)).type_as(data)
w_prior, b_prior = Normal(mu, sigma), Normal(bias_mu, bias_sigma)
priors = {'linear.weight': w_prior, 'linear.bias': b_prior}
lifted_module = pyro.random_module("module", regression_model, priors)
lifted_reg_model = lifted_module()
with pyro.iarange("map", N, subsample=data):
x_data = data[:, :-1]
y_data = data[:, -1]
# run the regressor forward conditioned on inputs
prediction_mean = lifted_reg_model(x_data).squeeze()
pyro.sample("obs",
Normal(prediction_mean, Variable(torch.ones(data.size(0))).type_as(data)),
obs=y_data.squeeze())

上述代码中我们为参数W和b设置了一般线性回归模型分布,均为 ~Normal(0, 1)。我们称之为先验,创建了Pyro的随机函数(在我们例子中,是PyTorch的回归模型),将先验概率加到({‘linear.weight’: w_prior, ‘linear.bias’: b_prior})并且基于输入数据x从模型p(y|x)中采样。

这个模型的指导如下所示:

def guide(data):
w_mu = Variable(torch.randn(1, p).type_as(data.data), requires_grad=True)
w_log_sig = Variable(0.1 * torch.ones(1, p).type_as(data.data), requires_grad=True)
b_mu = Variable(torch.randn(1).type_as(data.data), requires_grad=True)
b_log_sig = Variable(0.1 * torch.ones(1).type_as(data.data), requires_grad=True)
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", regression_model, dists)
return lifted_module()

这里我们定义了我们想要“训练”的分布的变分分布。就像你看到的,我们为W和b定义了相同形状的分布,但是尽量使他们更接近实际(只要我们能想到的)。在这个例子里,我选择让这个分布形状更窄一些。

(~Normal(0, 0.1))

我们以这种方式训练模型:

for j in range(3000):
epoch_loss = 0.0
perm = torch.randperm(N)
# shuffle data
data = data[perm]
# get indices of each batch
all_batches = get_batch_indices(N, 64)
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)

之后我们想从模型中取样y。重复取样100次然后计算每一次取样预测的均值和标准差(标准差越大,我们对预测准确的信心越低)。

preds = []
for i in range(100):
sampled_reg_model = guide(X_test)
pred = sampled_reg_model(X_test).data.numpy().flatten()
preds.append(pred)

我们应该记得,金融预测中MSE,MAE或者MAPE等经典指标可能会让人很困惑——相对较小的错误率并不意味着你的模型运行良好,所以在样本外的数据上查看性能是非常重要的,这也是我们要做的:

30天的贝叶斯模型预测

如上图所示,结果并不是很好,但是最后一条的预测形状很好,这给了我们一点信心。让我们继续吧!

普通神经网络

在这个非常简单的模型之后,我们想试着尝试些更有趣的东西,比如神经网络。首先让我们先了解一个简单的MLP,只有一个隐藏层,包括含有25个神经元以及线性激活模型。

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

然后训练100次。

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)

得到以下结果:

30天的Keras神经网络预测

这个结果甚至比简单贝叶斯回归还糟糕,而且这个模型不能得到确定性估计,更重要的是,这个模型甚至不能正则化。

贝叶斯神经网络

现在我想在PyTorch中定义一个和我们在Keras中训练的相同的神经网络。

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

与贝叶斯回归模型相比,我们现在有两组参数(从输入到隐藏层以及从隐藏层到输出),所以我们稍微改变一下模型分布和先验:

priors = {'hidden.weight': w_prior,
'hidden.bias': b_prior,
'predict.weight': w_prior2,
'predict.bias': b_prior2}

以及这个指导:

dists = {'hidden.weight': w_dist,
'hidden.bias': b_dist,
'predict.weight': w_dist2,
'predict.bias': b_dist2}

不要忘记为模型中所有的分布设置不同的名字,因为不能有任何的歧义和重复!可以在源代码中查看更多细节。

源代码:

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

在拟合模型和采样后,让我们直接看最终结果:

30天的Pyro神经网络预测

这个结果看上去比之前的结果都要好!

考虑下从贝叶斯模型中学到的正则化或者权重的性质,与普通神经网络做比较,我还会看一下权重统计。下面是我在Pryo模型中如何检查参数的:

for name in pyro.get_param_store().get_all_param_names():
print name, pyro.param(name).data.numpy()

在Keras模型中我是这么做的:

import tensorflow as tf
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()

举个例子,对于Keras模型中,最后一层的权重平均值和标准差分别是-0.0025901748,0.30395034,对于Pyro模型分别是0.0005974418和0.0005974418,数值更小,模型性能更好!

就像许多L2或者dropout这种正则化方法做的那样,让参数尽可能接近0,然后我们可以用变分推理来实现!对于隐藏层权重的情况就更有趣了。

我们把一些权重向量画出来,蓝色代表Keras的权重,橙色代表Pyro的权重:

输入和隐藏层间的一些权重

有趣的是,事实上不仅权重的均值和标准差很小,而且权重变得更加稀疏,所以基本上我们对于第一组权重用到了稀疏表示(类似L1正则),对第二组用到了类似L2正则表示,简直不可思议!不要忘记试一下代码哦!

结论

我们用了一种新奇的方法来训练神经网络。我们更新权重的分布而不是顺序更新静态权重。所以我们得到更有趣和可靠的结果。

我想要强调的是,贝叶斯方法给了我们一个机会,使得我们可以不手动添加正则项的情况下对神经网络进行正则化,理解模型的不确定性,并尽可能使用更少的数据得到更好的结果。欢迎继续关注!:)

原文链接:

https://medium.com/@alexrachnog/financial-forecasting-with-probabilistic-programming-and-pyro-db68ab1a1dba

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
老年人的性生活多久一次合理?要戴套吗?答案颠覆认知

老年人的性生活多久一次合理?要戴套吗?答案颠覆认知

贱议你读史
2026-03-06 23:28:50
正在拆除!陪伴无锡人 40年了!

正在拆除!陪伴无锡人 40年了!

无锡eTV全媒体
2026-03-11 20:22:08
全网沸腾!委员重磅提议:所有职工退休待遇一视同仁,网友吵翻了

全网沸腾!委员重磅提议:所有职工退休待遇一视同仁,网友吵翻了

今朝牛马
2026-03-11 22:17:37
不被任何人拿捏的顶级思维:不要回答别人的问题,要回答别人的目的

不被任何人拿捏的顶级思维:不要回答别人的问题,要回答别人的目的

古代经典
2026-02-25 15:40:12
66岁山口百惠的残酷家规:儿子40岁,仍在挤电车。

66岁山口百惠的残酷家规:儿子40岁,仍在挤电车。

果妈聊军事
2026-02-05 15:31:06
伊朗今天的灾难,是白左当年种下的祸根

伊朗今天的灾难,是白左当年种下的祸根

难得君
2026-03-11 00:16:06
75岁刘晓庆和年轻演员拍摄宣传照,一身大红再扮少女,她太执着了

75岁刘晓庆和年轻演员拍摄宣传照,一身大红再扮少女,她太执着了

阿废冷眼观察所
2026-03-11 08:42:17
中国女篮A组出现最强对手!29分狂胜巴西,希望明天中国队挺住!

中国女篮A组出现最强对手!29分狂胜巴西,希望明天中国队挺住!

南海浪花
2026-03-11 19:18:12
贬低小米宝马女主播是门店头牌,门店账号全部都是她的视频

贬低小米宝马女主播是门店头牌,门店账号全部都是她的视频

映射生活的身影
2026-03-11 15:50:23
伊朗外长称“绝不投降”,翻完历史才发现:历史课真没及格

伊朗外长称“绝不投降”,翻完历史才发现:历史课真没及格

老马拉车莫少装
2026-02-23 08:18:44
突发:美空军一架C-17 “环球霸王III”运输机在阿联酋上空失去联系!

突发:美空军一架C-17 “环球霸王III”运输机在阿联酋上空失去联系!

胜研集
2026-03-11 00:02:58
欧尔班竟称乌克兰是匈牙利和俄罗斯的缓冲区!试图取消对俄制裁

欧尔班竟称乌克兰是匈牙利和俄罗斯的缓冲区!试图取消对俄制裁

项鹏飞
2026-03-10 16:58:21
江苏特大级建工集团崩了!

江苏特大级建工集团崩了!

新浪财经
2026-03-11 14:52:58
离谱?国安29岁外援遭不可明说的伤病 回国做手术感染+现已不能动

离谱?国安29岁外援遭不可明说的伤病 回国做手术感染+现已不能动

我爱英超
2026-03-11 17:46:18
3月11日精选热点:6G取得重大突破商业化可期  这3家龙头受益

3月11日精选热点:6G取得重大突破商业化可期 这3家龙头受益

元芳说投资
2026-03-10 20:19:39
霍尔木兹替代路线:中东战火纷飞,全球油市全靠这两条管道“续命“!

霍尔木兹替代路线:中东战火纷飞,全球油市全靠这两条管道“续命“!

华尔街见闻官方
2026-03-11 20:20:25
碎三观!一河南网友哭诉长期被妻子身体“冷暴力”,评论区炸锅…

碎三观!一河南网友哭诉长期被妻子身体“冷暴力”,评论区炸锅…

火山詩话
2026-03-09 05:29:27
两会新华解码·“十五五”规划纲要草案丨规划纲要草案里,藏着人才成长新机遇

两会新华解码·“十五五”规划纲要草案丨规划纲要草案里,藏着人才成长新机遇

新华社
2026-03-10 20:50:11
在恒大贷款违约9个月后,许家印前妻曾花5亿,在伦敦买了33套豪宅

在恒大贷款违约9个月后,许家印前妻曾花5亿,在伦敦买了33套豪宅

网络易不易
2026-03-09 11:16:58
Lisa现身巴黎时装周,三角区凸起惹争议,她是变性人的瓜又被挖出

Lisa现身巴黎时装周,三角区凸起惹争议,她是变性人的瓜又被挖出

花哥扒娱乐
2026-03-11 18:31:42
2026-03-12 04:51:00
大数据文摘 incentive-icons
大数据文摘
专注大数据,每日有分享!
6834文章数 94534关注度
往期回顾 全部

科技要闻

腾讯"养虾"暴涨后,百度急得在门口"装虾"

头条要闻

特朗普再次威胁将切断与西班牙贸易往来:非常糟糕

头条要闻

特朗普再次威胁将切断与西班牙贸易往来:非常糟糕

体育要闻

郭艾伦重伤,CBA下半赛季还能期待些什么

娱乐要闻

蔡少芬晒全家福照,两女儿成最大亮点

财经要闻

唤醒10万亿存量资金 公积金改革大潮来了

汽车要闻

莲花纠偏, 冯擎峰的“收”与“守”

态度原创

房产
时尚
本地
亲子
健康

房产要闻

最低杀到7800元/㎡!海口2026第一波房价大调整来了!

衣服不用买太多!初春多穿短大衣和针织衫,简单舒适又显高

本地新闻

这档韩国玄学综艺,让多少人看得头皮发麻

亲子要闻

父母都是清华大学毕业,孩子却休学了…

转头就晕的耳石症,能开车上班吗?

无障碍浏览 进入关怀版