利用马尔可夫链蒙特卡洛(MCMC)进行贝叶斯线性回归和非线性回归的python代码(不调包)

本文主要是介绍利用马尔可夫链蒙特卡洛(MCMC)进行贝叶斯线性回归和非线性回归的python代码(不调包),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.利用MCMC进行线性回归

本文的特点是不利用任何市面上的贝叶斯推断的包,将全过程自己实现,利用的是M-H采样算法,从而让读者对整个过程有深刻理解。

本文呢不介绍任何数学原理。

关于线性回归数学原理的解释请看:

  1. 一般的线性回归,最小二乘和最大似然估计、最大后验估计视角:
    https://www.bilibili.com/video/BV1hW41167iL?spm_id_from=333.999.0.0
  2. 贝叶斯线性回归:
    https://www.bilibili.com/video/BV1St411m7XJ?spm_id_from=333.999.0.0

更加详细和全面的推导请看:《PRML》第三章。

关于MCMC的原理,请看我上一篇博文:
https://blog.csdn.net/RSstudent/article/details/122636064?spm=1001.2014.3001.5502
或查阅《PRML》等书籍的相关章节即可。

贝叶斯线性回归得到完整的后验分布,并可以给出后验分布的期望,从而避免了在最大后验估计情形下可能会出现的一些问题。

代码

import numpy as np
import scipy
import seaborn
import matplotlib.pyplot as plt"""
从概率视角来看线性回归,包括频率派视角和贝叶斯视角
本文是贝叶斯视角的,因此用的是MCMC采样,期望得到完整的后验分布而不是点估计
数学细节:bilibili上的机器学习白板推导系列
或者更详细的细节和数学推导参看:《PRML》
视频链接:
https://www.bilibili.com/video/BV1hW41167iL?spm_id_from=333.999.0.0
https://www.bilibili.com/video/BV1St411m7XJ?spm_id_from=333.999.0.0"""
# 高斯分布函数
# 默认参数设置为了二维标准高斯分布,高维也能用,只要维度对就行了
# 按道理应该检查一下用户输入的均值和方差矩阵是不是维度相符合
def guassian(x,mean=np.array([[0],[0]]),covariance = np.array([[1,0],[0,1]])):dimension = x.shape[0]# 高维if dimension > 1:guassian_kernel =\np.exp((-1/2)*np.dot(np.dot((x-mean).T,np.linalg.inv(covariance)),(x-mean)))probability = guassian_kernel/(np.power(2*np.pi,dimension/2)*np.sqrt(np.linalg.det(covariance)))# 一维,这里的协方差其实退化为方差else:guassian_kernel =\np.exp((-1/2)*(1/covariance)*(x-mean)**2)probability = guassian_kernel/(np.sqrt(2*np.pi*covariance))return probability#先验概率密度是高斯
def prior_builder(mean = np.array([[0],[0]]), covariance = np.array([[1,0], [0,1]])):def prior(parameters):if parameters.shape != (2,1):raise Exception("Wrong dimension for parameters.")probability = guassian(parameters, mean, covariance)return probabilityreturn prior# 定义似然函数
# 二维线性回归
def likelihood_builder(x,y):"""返回线性回归模型的似然函数"""def likelihood(theta):def model(x,theta):"""线性回归模型的似然函数y = theta.T*x theta是二维的,也就是有两个参数x也是二维的"""return np.dot(theta.T, x)likelihood_value = 1 # 初始化似然函数的值n_samples = x.shape[0] # 获得样本的个数,也就是数据矩阵的行数# 连乘,log下要取连加,这里不是logfor i in range(n_samples):current_x = x[i,:].reshape(2,1)current_y = y[i]guassian_mean = model(cuurent_x ,theta)probability = guassian(current_y, guassian_mean, 1)likelihood_value = likelihood_value*probabilityreturn likelihood_valuereturn likelihood# 有了似然和先验,可以定义未归一化的后验分布(密度函数)
# 采样只需要未归一化的后验,因为显然概率大的地方样本就会多,
# 只和概率相对大小有关,和绝对大小无关
def posterior_builder(likelihood, prior):# 后验分布~似然x先验,返回后验概率密度函数def posterior(theta):post_prob = likelihood(theta)*prior(theta)return post_probreturn posterior# M-H采样
def metropolis_hastings(prob_func, n_burn_in, n_samplings):"""n_burn_in: 预烧期采样次数n_smaplings: 总采样次数prob_func: 需采样的概率密度"""# 因为是二维的,所以就直接初始化一个二维向量# 这样写不能通用了,但是比较简单theta_old = np.array([[0],[0]]) # 任意初始化一个样本点# 生成一个数组,存放样本点,一共采样10000次,有10000个样本点# 但是最后这10000个样本的前1000个不需要,是预烧期的samples = np.zeros((2,n_samplings), np.float32)for i in range(n_samplings):# 进行一次随机游走# 这里原本是以旧样本为均值,方差为1的高斯分布来采样,模拟随机游走# 等价于在原来的样本上加上一个0均值,方差为1的高斯分布采样theta_new = np.random.normal(loc=theta_old, scale = 1, size = (2,1))# 计算接受率alphaalpha = np.min([prob_func(theta_new)/prob_func(theta_old),1])# 随机生成0-1随机数,小于接受率,则将新样本接收if np.random.rand() < alpha:theta_old = theta_newsamples[:,i] = theta_new.reshape(2,)# 大于接受率,则接受旧样本(注意不是舍弃)else:theta_old = theta_oldsamples[:,i] = theta_old.reshape(2,)return samplesN_BURN_IN = 3000
N_SAMPLINGS = 20000"""
模拟一批真实数据!
假设有100个样本
"""N = 100
# 真实参数
theta_real = np.array([[2.5],[6.5]],np.float32)#模拟数据
simu_x = np.random.rand(N,2) # 模拟数据矩阵x,用均匀分布生成
simu_y = np.dot(simu_x, theta_real) + np.random.randn(N,1)*0.2 #产生模拟的y# 构建在模拟数据上的似然和先验分布函数
likelihood = likelihood_builder(simu_x, simu_y)
# 给了一个方差为100的高斯,表示较弱的先验信息
para_prior = prior_builder(np.array([[3],[3]]), np.array([[100, 0], [0, 100]]))
# 得到后验分布函数
para_posterior = posterior_builder(likelihood, para_prior)# 采样
samples = metropolis_hastings(para_posterior, N_BURN_IN, N_SAMPLINGS)
seaborn.jointplot(samples[0,N_BURN_IN:], samples[1,N_BURN_IN:])# 采样结果均值,根据大数定律是后验分布的均值
print(np.mean(samples[0,N_BURN_IN:]), np.mean(samples[1,N_BURN_IN:]))
plt.show()

采样结果图:
在这里插入图片描述

输出的均值:

2.503646 6.5010796

2. 非线性回归

非线性回归就是非线性模型的回归,因此只需要将likelihood_builder函数中的likelihood函数中的model函数中修改为你所需要进行回归的非线性函数即可。另外后面模拟的数据也需要模拟非线性模型的数据。我们如果使用如下的非线性模型:
y = θ 1 2 x 1 + θ 2 x 2 y = \theta_1^2x_1+\theta_2x_2 y=θ12x1+θ2x2
则采样结果为:
在这里插入图片描述

这篇关于利用马尔可夫链蒙特卡洛(MCMC)进行贝叶斯线性回归和非线性回归的python代码(不调包)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:https://blog.csdn.net/RSstudent/article/details/122705886
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/246382

相关文章

Python基于wxPython和FFmpeg开发一个视频标签工具

《Python基于wxPython和FFmpeg开发一个视频标签工具》在当今数字媒体时代,视频内容的管理和标记变得越来越重要,无论是研究人员需要对实验视频进行时间点标记,还是个人用户希望对家庭视频进行... 目录引言1. 应用概述2. 技术栈分析2.1 核心库和模块2.2 wxpython作为GUI选择的优

Java进行文件格式校验的方案详解

《Java进行文件格式校验的方案详解》这篇文章主要为大家详细介绍了Java中进行文件格式校验的相关方案,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、背景异常现象原因排查用户的无心之过二、解决方案Magandroidic Number判断主流检测库对比Tika的使用区分zip

Java使用Curator进行ZooKeeper操作的详细教程

《Java使用Curator进行ZooKeeper操作的详细教程》ApacheCurator是一个基于ZooKeeper的Java客户端库,它极大地简化了使用ZooKeeper的开发工作,在分布式系统... 目录1、简述2、核心功能2.1 CuratorFramework2.2 Recipes3、示例实践3

Spring Boot 3.4.3 基于 Spring WebFlux 实现 SSE 功能(代码示例)

《SpringBoot3.4.3基于SpringWebFlux实现SSE功能(代码示例)》SpringBoot3.4.3结合SpringWebFlux实现SSE功能,为实时数据推送提供... 目录1. SSE 简介1.1 什么是 SSE?1.2 SSE 的优点1.3 适用场景2. Spring WebFlu

java之Objects.nonNull用法代码解读

《java之Objects.nonNull用法代码解读》:本文主要介绍java之Objects.nonNull用法代码,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录Java之Objects.nonwww.chinasem.cnNull用法代码Objects.nonN

Python如何使用__slots__实现节省内存和性能优化

《Python如何使用__slots__实现节省内存和性能优化》你有想过,一个小小的__slots__能让你的Python类内存消耗直接减半吗,没错,今天咱们要聊的就是这个让人眼前一亮的技巧,感兴趣的... 目录背景:内存吃得满满的类__slots__:你的内存管理小助手举个大概的例子:看看效果如何?1.

Python+PyQt5实现多屏幕协同播放功能

《Python+PyQt5实现多屏幕协同播放功能》在现代会议展示、数字广告、展览展示等场景中,多屏幕协同播放已成为刚需,下面我们就来看看如何利用Python和PyQt5开发一套功能强大的跨屏播控系统吧... 目录一、项目概述:突破传统播放限制二、核心技术解析2.1 多屏管理机制2.2 播放引擎设计2.3 专

Python中随机休眠技术原理与应用详解

《Python中随机休眠技术原理与应用详解》在编程中,让程序暂停执行特定时间是常见需求,当需要引入不确定性时,随机休眠就成为关键技巧,下面我们就来看看Python中随机休眠技术的具体实现与应用吧... 目录引言一、实现原理与基础方法1.1 核心函数解析1.2 基础实现模板1.3 整数版实现二、典型应用场景2

Python实现无痛修改第三方库源码的方法详解

《Python实现无痛修改第三方库源码的方法详解》很多时候,我们下载的第三方库是不会有需求不满足的情况,但也有极少的情况,第三方库没有兼顾到需求,本文将介绍几个修改源码的操作,大家可以根据需求进行选择... 目录需求不符合模拟示例 1. 修改源文件2. 继承修改3. 猴子补丁4. 追踪局部变量需求不符合很

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.