贝叶斯回归#

贝叶斯回归是一种基于贝叶斯统计推断的回归方法。它通过引入先验分布来表达对参数的不确定性,并利用观测数据来更新参数的后验分布。假设我们有一个训练集包含\(N\)个样本,每个样本由输入特征\(X\)和对应的输出标签\(y\)组成。要经过的步骤是参数建模 -> 后验推断 -> 参数估计和预测。

优缺点:

  • 贝叶斯回归引入先验知识。适用于小样本、高噪声以及需要考虑模型不确定性的数据。

  • 计算复杂度较高,需要进行概率推断和参数估计,不适用于高维数据。

下面是使用Python和PyMC3库实现贝叶斯线性回归的示例代码:

import pymc3 as pm
import numpy as np

# 构造训练集
X = np.random.randn(100, 2)
w_true = np.array([3, 5])
y = X.dot(w_true) + np.random.randn(100)

# 创建贝叶斯模型
with pm.Model() as model:
    # 定义参数的先验分布
    w = pm.Normal('w', mu=0, sd=1, shape=2)
    sigma = pm.HalfNormal('sigma', sd=1)
    
    # 定义输出标签的条件分布
    y_obs = pm.Normal('y_obs', mu=pm.math.dot(X, w), sd=sigma, observed=y)
    
    # 进行后验推断
    trace = pm.sample(1000, tune=1000)

# 输出参数估计结果
print("参数估计结果:")
print(pm.summary(trace)['mean'])

# 进行预测
x_new = np.array([[1, 2], [3, 4]])  # 新的输入特征
with model:
    post_pred = pm.sample_posterior_predictive(trace, samples=1000, vars=[y_obs])
    y_pred_mean = np.mean(post_pred['y_obs'], axis=0)

print("预测结果:")
print(y_pred_mean)
/home/runner/.local/lib/python3.10/site-packages/theano/scalar/basic.py:2412: FutureWarning: In the future `np.bool` will be defined as the corresponding NumPy scalar.
  self.ctor = getattr(np, o_type.dtype)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[1], line 1
----> 1 import pymc3 as pm
      2 import numpy as np
      4 # 构造训练集

File ~/.local/lib/python3.10/site-packages/pymc3/__init__.py:23
     20 import platform
     22 import semver
---> 23 import theano
     25 _log = logging.getLogger("pymc3")
     27 if not logging.root.handlers:

File ~/.local/lib/python3.10/site-packages/theano/__init__.py:83
     75 # This is the api version for ops that generate C code.  External ops
     76 # might need manual changes if this number goes up.  An undefined
     77 # __api_version__ can be understood to mean api version 0.
     78 #
     79 # This number is not tied to the release version and should change
     80 # very rarely.
     81 __api_version__ = 1
---> 83 from theano import scalar, tensor
     84 from theano.compile import (
     85     In,
     86     Mode,
   (...)
     93     shared,
     94 )
     95 from theano.compile.function import function, function_dump

File ~/.local/lib/python3.10/site-packages/theano/scalar/__init__.py:1
----> 1 from .basic import *
      2 from .basic_scipy import *

File ~/.local/lib/python3.10/site-packages/theano/scalar/basic.py:2460
   2456         else:
   2457             return s
-> 2460 convert_to_bool = Cast(bool, name="convert_to_bool")
   2461 convert_to_int8 = Cast(int8, name="convert_to_int8")
   2462 convert_to_int16 = Cast(int16, name="convert_to_int16")

File ~/.local/lib/python3.10/site-packages/theano/scalar/basic.py:2412, in Cast.__init__(self, o_type, name)
   2410 super().__init__(specific_out(o_type), name=name)
   2411 self.o_type = o_type
-> 2412 self.ctor = getattr(np, o_type.dtype)

File ~/.local/lib/python3.10/site-packages/numpy/__init__.py:324, in __getattr__(attr)
    319     warnings.warn(
    320         f"In the future `np.{attr}` will be defined as the "
    321         "corresponding NumPy scalar.", FutureWarning, stacklevel=2)
    323 if attr in __former_attrs__:
--> 324     raise AttributeError(__former_attrs__[attr])
    326 if attr == 'testing':
    327     import numpy.testing as testing

AttributeError: module 'numpy' has no attribute 'bool'.
`np.bool` was a deprecated alias for the builtin `bool`. To avoid this error in existing code, use `bool` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.bool_` here.
The aliases was originally deprecated in NumPy 1.20; for more details and guidance see the original release note at:
    https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations

贝叶斯岭回归#

贝叶斯岭回归(Bayesian Ridge Regression)是一种基于贝叶斯统计推断的回归方法,结合了岭回归和贝叶斯推断的思想。

具体步骤如下:


假设模型为:

\(y = Xw + ε\) 其中,\(y\)是目标变量,\(X\)是特征矩阵,\(w\)是待估计的参数向量,\(ε\)是误差项。

输入:特征矩阵 \(X\)(大小为 \(n \times p\)),目标变量向量 \(y\)(长度为 \(n\)

输出:参数估计值 \(w\)


  • 定义先验分布:假设参数 \(w\) 的先验分布为 \(p(w)\)

  • 计算后验分布:根据贝叶斯定理,可以得到参数 \(w\) 的后验分布:

    \( p(w|X, y) = \frac{p(y|X, w) \cdot p(w)}{p(y|X)} \)

    其中,\(p(y|X, w)\) 是给定参数 \(w\) 条件下观测数据 \(y\) 的概率密度函数,\(p(w)\) 是参数 \(w\) 的先验分布,\(p(y|X)\) 是边际似然函数。

  • 参数估计:通过后验分布可以获得参数的点估计或分布估计。

    • 点估计:例如,使用后验分布的均值作为参数的点估计:

    \( \hat{w} = E[w|X, y] = \int w \cdot p(w|X, y) dw \)

    • 分布估计:通过后验分布得到参数的概率分布,用于描述参数的不确定性:

    \( p(w|X, y) \)

通过对后验分布进行采样或使用解析的数学表达式,可以获得对参数 \(w\) 的估计结果,其中包括点估计和不确定性估计。


下面是使用Python和Scikit-learn库实现贝叶斯岭回归的示例代码:

from sklearn import linear_model

X = [[0., 0.], [1., 1.], [2., 2.], [3., 3.]]
Y = [0., 1., 2., 3.]

# 创建贝叶斯岭回归模型
reg = linear_model.BayesianRidge()

# 拟合模型
reg.fit(X, Y)

# 输出参数估计结果
print("参数估计结果:")
print(reg.coef_)

# 进行预测
y_pred = reg.predict([[1, 0.]])
参数估计结果:
[0.49999993 0.49999993]

主动相关决策理论 - ARD#

ARDRegression类似于贝叶斯岭回归(Bayesian Ridge Regression),但具有更强的稀疏性。这是因为ARDRegression引入了不同于贝叶斯岭回归的先验假设,即权重 \(w\) 的分布不再是球形的高斯分布,而是轴对齐的椭圆高斯分布。

ARDRegression中的每个权重 \(wi\) 都有一个单独的标准差 \(λ_i\) 。所有 \(λ_i\) 的先验分布由超参数 \(λ1\)\(λ2\) 等确定,通常使用相同的 \(\gamma\) 分布。

ARDRegression可以用于特征选择,因为它倾向于将不相关或弱相关的特征的权重设为0,从而实现了稀疏性。这使得模型更容易解释,并且可以提高泛化性能。

不过ARD也比较慢。

下面给个sklearn的例子:

from sklearn.datasets import make_regression
from sklearn.linear_model import ARDRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error

# 生成随机回归数据集
X, y = make_regression(n_samples=100, n_features=10, noise=0.1, random_state=42)

# 将数据集拆分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建并拟合ARDRegression模型
model = ARDRegression()
model.fit(X_train, y_train)

# 使用模型进行预测
y_pred = model.predict(X_test)

# 计算均方误差(Mean Squared Error)
mse = mean_squared_error(y_test, y_pred)
print("Mean Squared Error: ", mse)
Mean Squared Error:  0.010270127022996813

参考#