Gibbs sampling based on linear regression

Bayesian linear regression

此实例为吉布斯采样基于线性回归的实现。假设我们已经知道实数对 (yi,xi),i=1,,N ( y i , x i ) , i = 1 , ⋯ , N ,以及 yiN(β0+β1xi,1/τ) y i ∼ N ( β 0 + β 1 x i , 1 / τ ) ,根据分布的性质,也可以写成另外一种形式, yi=β0+β1xi+ϵ,ϵN(0,1/τ) y i = β 0 + β 1 x i + ϵ , ϵ ∼ N ( 0 , 1 / τ ) ,假设观察到的实数对相互独立的产生于同一个分布,其似然函数可以写成:

L(y1,,yn,x1,,xnβ0,β1,τ)=i=1NN(β0+β1xi,1/τ) L ( y 1 , ⋯ , y n , x 1 , ⋯ , x n ∖ β 0 , β 1 , τ ) = ∏ i = 1 N N ( β 0 + β 1 x i , 1 / τ )

为了便于计算,我们对参数取共轭先验:
β0N(μ0,1/τ0)β1N(μ1,1/τ1)τGamma(α,β) β 0 ∼ N ( μ 0 , 1 / τ 0 ) β 1 ∼ N ( μ 1 , 1 / τ 1 ) τ ∼ G a m m a ( α , β )

这里有详细的slices推导, 请点击

Gibbs基本方法介绍

我们有两个参数 θ1,θ2 θ 1 , θ 2 ,以及观测数据 x x ,为了找到后验概率p(θ1,θ2x),我们做以下操作:

1.以一定方法初始化 θi2 θ 2 i (比如随机初始化)

2.此时根据已知采样 θi+11p(θ1θi2,x) θ 1 i + 1 ∼ p ( θ 1 ∖ θ 2 i , x )

3.根据最新的值再采样 θi+12p(θ2θi+11,x) θ 2 i + 1 ∼ p ( θ 2 ∖ θ 1 i + 1 , x )

需要注意的是,需要交替的以最新值就行采样更新。

程序实现

导入包

import numpy as np
import matplotlib as plt
%matplotlib inline
import seaborn as sns
import pandas as pd

根据推导公式定义更新参数的函数

def sample_beta_0(y, x, beta_1, tau, mu_0, tau_0):
    N = len(y)
    assert len(x) == N
    precision = tau_0 + tau * N
    mean = tau_0 * mu_0 + tau * np.sum(y - beta_1 * x)
    mean /= precision
    return np.random.normal(mean, 1 / np.sqrt(precision))
def sample_beta_1(y, x, beta_0, tau, mu_1, tau_1):
    N = len(y)
    assert len(x) == N
    precision = tau_1 + tau * np.sum(x * x)
    mean = tau_1 * mu_1 + tau * np.sum( (y - beta_0) * x)
    mean /= precision
    return np.random.normal(mean, 1 / np.sqrt(precision))
def sample_tau(y, x, beta_0, beta_1, alpha, beta):
    N = len(y)
    alpha_new = alpha + N / 2
    resid = y - beta_0 - beta_1 * x
    beta_new = beta + np.sum(resid * resid) / 2
    return np.random.gamma(alpha_new, 1 / beta_new)

产生数据

##设置数据参数的真实参数
beta_0_true = -1
beta_1_true = 2
tau_true = 1
##根据真实参数生成数据
N = 50
x = np.random.uniform(low = 0, high = 4, size = N)
y = np.random.normal(beta_0_true + beta_1_true * x, 1 / np.sqrt(tau_true))
sns.stripplot(x,y)#画出数据

这里写图片描述

<matplotlib.axes._subplots.AxesSubplot at 0x27826bb4c50>
## specify initial values
init = {"beta_0": 0,
        "beta_1": 0,
        "tau": 2}

## specify hyper parameters
hypers = {"mu_0": 0,
         "tau_0": 1,
         "mu_1": 0,
         "tau_1": 1,
         "alpha": 2,
         "beta": 1}
##定义Gibbs采样的主函数,把上面定义的几个函数按照逻辑组合起来形成一个采样过程
def gibbs(y, x, iters, init, hypers):
    assert len(y) == len(x)
    beta_0 = init["beta_0"]
    beta_1 = init["beta_1"]
    tau = init["tau"]

    trace = np.zeros((iters, 3)) ## trace to store values of beta_0, beta_1, tau
##按照更新过程进行参数逐一更新
    for it in range(iters):
        beta_0 = sample_beta_0(y, x, beta_1, tau, hypers["mu_0"], hypers["tau_0"])
        beta_1 = sample_beta_1(y, x, beta_0, tau, hypers["mu_1"], hypers["tau_1"])
        tau = sample_tau(y, x, beta_0, beta_1, hypers["alpha"], hypers["beta"])
        trace[it,:] = np.array((beta_0, beta_1, tau))

    trace = pd.DataFrame(trace)
    trace.columns = ['beta_0', 'beta_1', 'tau']

    return trace
iters = 1000##采样次数
trace = gibbs(y, x, iters, init, hypers)
trace.plot()##采样得到的数据可视化
<matplotlib.axes._subplots.AxesSubplot at 0x27826c3c908>

这里写图片描述

trace_burnt = trace[500:999]##取后面500个采样
hist_plot = trace_burnt.hist(bins = 30, layout = (1,3))

这里写图片描述

print(trace_burnt.median())
print(trace_burnt.std())
beta_0 -1.077110 beta_1 1.903947 tau 1.384544 dtype: float64 beta_0 0.229955 beta_1 0.093329 tau 0.288980 dtype: float64
trace[1:10]
.dataframe thead tr:only-child th { text-align: right; } .dataframe thead th { text-align: left; } .dataframe tbody tr th { vertical-align: top; }
beta_0beta_1tau
11.3171671.0517280.445828
20.5949401.2560170.513077
30.1344361.4150970.769414
4-0.1231971.5190840.968624
5-0.0730991.5673000.633794
6-0.5251611.7575520.974104
7-0.8436141.8789841.751914
8-0.8763591.7706351.376143
9-0.8905581.8391911.723694

此为纯翻译摘抄版本,英文参见Gibbs sampling for Bayesian linear regression in Python

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值