优化贝叶斯线性回归的起始参数?

机器算法验证 回归 机器学习 贝叶斯 Python pymc
2022-04-07 20:39:36

我正在使用PyMC3Python 3但我不确定如何优化我的起始参数。该示例使用附带的回归数据集scikit-learn糖尿病数据的属性最少。通过仅查看数据(即 [samples x attributes] 矩阵和目标向量),我如何知道哪些参数用于我的系数mu以及std我的系数Normal分布beta

这两个模型都可以预测,我可以计算预测值和实际值之间的差异(例如均方根、绝对误差等),但是贝叶斯有没有办法优化先验的参数默认值我不能用sklearn.grid_search.GridSearchCV从字面上看,我有无数种可能性可供我选择,mu所以std我不知道如何知道我的先验应该从哪些参数开始。

使用目标向量的分布并从那里向后工作以揭示有关先验分布的信息是否有用?

我使用的模块:

import pymc3 as pm
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import theano as th
import seaborn as sns; sns.set()
from scipy import stats, optimize
from sklearn.datasets import load_diabetes
from sklearn.cross_validation import train_test_split
from collections import *
np.random.seed(9)

%matplotlib inline

以下是如何加载和获取数据的统计信息:

#Load the Data
diabetes_data = load_diabetes()
X, y_ = diabetes_data.data, diabetes_data.target

#Assign Labels
sample_labels = ["patient_%d" % i for i in range(X.shape[0])]
attribute_labels = ["att_%d" % j for j in range(X.shape[1])]

#Create Data Objects
DF_X = pd.DataFrame(X, index=sample_labels, columns=attribute_labels)
SR_y = pd.Series(y_, index=sample_labels, name="Targets") 

#Split Data (_tr denotes training set, _te is test set)
DF_X_tr, DF_X_te, SR_y_tr, SR_y_te = train_test_split(DF_X,SR_y,test_size=0.25, random_state=0)

#Convert to array for faster indexing
X_tr, X_te, y_tr, y_te = DF_X_tr.as_matrix(), DF_X_te.as_matrix(), SR_y_tr.as_matrix(), SR_y_te.as_matrix()

#Describe Attributes
DF_describe = DF_X_tr.describe()
DF_describe

在此处输入图像描述

以下是我创建回归模型的方式:

#Preprocess data for Modeling
shA_X = th.shared(X_tr) #I use `shared` for predicion later . http://pymc-devs.github.io/pymc3/notebooks/posterior_predictive.html?highlight=sample_ppc

#Generate Model
linear_model = pm.Model()
with linear_model: 
    # Priors for unknown model parameters    
    alpha = pm.Normal("alpha", mu=y_tr.mean(),sd=10)
    betas = pm.Normal("betas", mu=0,
                               sd=10, #I use 10000 for this one in the left panel
                               shape=X.shape[1])
    sigma = pm.HalfNormal("sigma", sd=10)

    # Expected value of outcome
    mu = alpha + pm.dot(betas, shA_X.T) #mu = alpha + np.array([betas[j]*shA_X[:,j] for j in range(X.shape[1])]).sum(axis=0)

    # Likelihood (sampling distribution of observations)
    likelihood = pm.Normal("likelihood", mu=mu, sd=sigma, observed=y_tr)

    # Obtain starting values via Maximum A Posteriori Estimate
    map_estimate = pm.find_MAP(model=linear_model, fmin=optimize.fmin_powell)

    # Instantiate Sampler
    step = pm.NUTS(scaling=map_estimate)

    # Burn-in
    trace = pm.sample(10000, step, start=map_estimate, progressbar=True, njobs=1)

#Traceplot
pm.traceplot(trace, lines={k: v['mean'] for k, v in pm.df_summary(trace).iterrows()})

左边有一个较大std的用于测试版。 我怎么能通过查看数据知道为我的默认参数设置什么?

在此处输入图像描述

这就是我的整个数据集的目标向量的样子,我应该用它来提示我在之前的分布中使用什么?

sns.distplot(y_, bins=25)

在此处输入图像描述

2个回答

我将用一个简单的例子来说明我的答案。想象一下你的数据X1,,Xn是遵循泊松分布的计数。使用单个参数描述泊松分布λ给定我们拥有的数据,我们想要估计。为了建立贝叶斯模型,我们使用贝叶斯定理

p(λ|X)posteriorp(X|λ)likelihoodp(λ)prior

我们将似然函数定义为泊松分布,参数化为λ我们使用超参数参数化的另一个泊松分布作为先验θ

XiPoisson(λ)λPoisson(θ)

您的问题基本上是关于如何找到“最佳”θ. 回想一下,泊松分布参数也是平均值。它的最大似然估计是样本均值,因此“最佳”值θ 查看数据后将使用样本均值如果你这样做了,那么你要计算的是先验平均值是θ找到最优值λ这样它就最大化了可能性——你能看到循环吗?θ考虑到我们拥有的数据,它已经是一个最优值,然后我们用它来找到最优值......在这种情况下,最大似然估计不是更诚实的方法吗?

要了解有关选择先验的更多信息,请查看如何在贝叶斯参数估计中选择先验,其中详细介绍了有关选择信息先验的更多细节,即基于我们在看到数据之前所拥有的一些知识的先验。如果我们没有这样的信息,我们会使用每周信息先验,这些信息很少说明我们对感兴趣参数的假设(例如,在某个合理范围内的均匀分布)。最后,如果您对先验的参数一无所知,您可以使用超先验,即先验参数的先验,然后贝叶斯机器将为您找到先验的“最佳”参数(但是,是的,您需要确定超先验的值,这并不总是那么明显)。

最后,有一种称为经验贝叶斯方法的方法,但正如您从示例中看到的那样,这里的风险是我们最终可能会得到过度自信的估计,因为我们使用了两次相同的数据。

查看Andrew Gelman、John Carlin、Hal Stern、David Dunson、Aki Vehtari 和 Donald Rubin 的“贝叶斯数据分析”以获得关于选择先验的精彩介绍和多个示例。John K. Kruschke 的“Doing Bayesian Data Analysis ”很好地介绍了分层模型和超先验。最后,Devinderjit Sivia 和 John Skilling 的“数据分析:贝叶斯教程”对“使用相同的数据两次”进行了一些讨论。

直觉上,左边的那个似乎给了你不合理的大系数。

为了更量化,你可以做模型比较。交叉验证是比较它们的一种方法,但还有各种其他措施可以估计您在交叉验证中获得的结果。PyMC3有多种模型对比措施,包括DIC、WAIC和LOO:http ://pymc-devs.github.io/pymc3/api.html#pymc3.stats.loo