【python因果推断库16】使用 PyMC 模型进行回归拐点设计

目录

[例子 1 - 连续分段线性函数](#例子 1 - 连续分段线性函数)


python 复制代码
import arviz as az
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

import causalpy as cp
%load_ext autoreload
%autoreload 2
%config InlineBackend.figure_format = 'retina'
seed = 42
rng = np.random.default_rng(seed)

回归拐点设计应当通过分段连续函数来进行分析。具体来说:

  • 我们想要一个函数能够捕捉拐点左边和右边的数据。
  • 我们想要一个具有一个断点或拐点的分段函数。
  • 该函数应在拐点处连续。

一个这样的函数的例子是一个分段连续多项式:

其中:

  • 是未知参数,

  • x 是连续变量,

  • t 是一个指示变量,如果 x>=k 则取值为1,否则为 0

  • k 是 x 在拐点处的值。

我们可以通过绘制一系列随机选择的 系数的函数图像来直观地展示这些函数的样子,但所有这些函数都具有相同的拐点在0.5。

python 复制代码
def f(x, beta, kink):
    return (
        beta[0]
        + beta[1] * x
        + beta[2] * x**2
        + beta[3] * (x - kink) * (x >= kink)
        + beta[4] * (x - kink) ** 2 * (x >= kink)
    )


def gradient_change(beta, kink, epsilon=0.01):
    gradient_left = (f(kink, beta, kink) - f(kink - epsilon, beta, kink)) / epsilon
    gradient_right = (f(kink + epsilon, beta, kink) - f(kink, beta, kink)) / epsilon
    gradient_change = gradient_right - gradient_left
    return gradient_change


x = np.linspace(-1, 1, 1000)
kink = 0.5
cols = 5

fig, ax = plt.subplots(2, cols, sharex=True, sharey=True, figsize=(15, 5))

for col in range(cols):
    beta = rng.random(5)
    ax[0, col].plot(x, f(x, beta, kink), lw=3)
    ax[1, col].plot(x, np.gradient(f(x, beta, kink), x), lw=3)
    ax[0, col].set(title=f"Random  {col+1}")
    ax[1, col].set(xlabel="x")

ax[0, 0].set(ylabel="$y = f(x)$")
ax[1, 0].set(ylabel=r"$\frac{dy}{dx}$");

回归拐点分析的思想是拟合一个合适的函数到数据上,并估计在拐点处函数梯度是否有变化。

下面我们将生成一些数据集并演示如何进行回归拐点分析。我们将使用一个函数来生成具有所需特性的模拟数据集。

python 复制代码
def generate_data(beta, kink, sigma=0.05, N=50):
    if beta is None:
        beta = rng.random(5)
    x = rng.uniform(-1, 1, N)
    y = f(x, beta, kink) + rng.normal(0, sigma, N)
    df = pd.DataFrame({"x": x, "y": y, "treated": x >= kink})
    return df

例子 1 - 连续分段线性函数

在这个例子中,我们将坚持使用一个简单的连续分段函数。

python 复制代码
kink = 0.5
# linear function with gradient change of 2 at kink point
beta = [0, -1, 0, 2, 0]
sigma = 0.05
df = generate_data(beta, kink, sigma=sigma)

fig, ax = plt.subplots()
ax.scatter(df["x"], df["y"], alpha=0.5)
ax.axvline(kink, color="red", linestyle="--")
ax.set(title=f"Change in gradient at kink point: {gradient_change(beta, kink):.2f}");

我们可以使用常规的 cp.pymc_models.LinearRegression 模型,并通过巧妙地通过 formula 输入指定设计矩阵来强制执行连续分段特性。

在这个例子中,将公式设置为 "y ~ 1 + x + I((x-0.5)*treated)"(其中 0.5 是拐点)等同于以下模型:

拐点两侧的梯度变化是通过数值方法评估的。epsilon 参数决定了用于计算梯度变化的拐点两侧的距离。

python 复制代码
result1 = cp.pymc_experiments.RegressionKink(
    df,
    formula=f"y ~ 1 + x + I((x-{kink})*treated)",
    model=cp.pymc_models.LinearRegression(sample_kwargs={"random_seed": seed}),
    kink_point=kink,
    epsilon=0.1,
)

fig, ax = result1.plot()

如果你想绘制推断出的梯度变化的后验分布,你可以按照以下方式进行。

python 复制代码
ax = az.plot_posterior(result1.gradient_change, ref_val=gradient_change(beta, kink))
ax.set(title="Gradient change");
相关推荐
寻星探路2 分钟前
【Python 全栈测开之路】Python 进阶:库的使用与第三方生态(标准库+Pip+实战)
java·开发语言·c++·python·ai·c#·pip
子夜江寒2 小时前
基于 OpenCV 的图像形态学与边缘检测
python·opencv·计算机视觉
SmartRadio8 小时前
CH585M+MK8000、DW1000 (UWB)+W25Q16的低功耗室内定位设计
c语言·开发语言·uwb
rfidunion8 小时前
QT5.7.0编译移植
开发语言·qt
少林码僧8 小时前
2.31 机器学习神器项目实战:如何在真实项目中应用XGBoost等算法
人工智能·python·算法·机器学习·ai·数据挖掘
rit84324998 小时前
MATLAB对组合巴克码抗干扰仿真的实现方案
开发语言·matlab
智航GIS9 小时前
10.4 Selenium:Web 自动化测试框架
前端·python·selenium·测试工具
jarreyer9 小时前
摄像头相关记录
python
宝贝儿好9 小时前
【强化学习】第六章:无模型控制:在轨MC控制、在轨时序差分学习(Sarsa)、离轨学习(Q-learning)
人工智能·python·深度学习·学习·机器学习·机器人
大、男人9 小时前
python之asynccontextmanager学习
开发语言·python·学习