1

这是我第一次尝试为对数正态分布的响应建模线性回归。我有一个df包含两个变量的数据框:预测变量X和响应。当我绘制responsevs. 预测变量X时,我们得到了这个漂亮的图: 在此处输入图像描述

当我绘制响应的对数分布时,np.log(response)我得到非常接近正态分布的东西:

.在此处输入图像描述

为了建模和我之间的关系Xresponse我建立了以下模型,

import pymc3 as pm


with pm.Model() as model: 
    a = pm.Normal('a', 0, 10)
    b = pm.Normal('b', 0, 10)
    sigma = pm.Uniform('sigma', lower=0, upper=10)

    mu = pm.Deterministic('mu', a + b * df_train[X])

    y_hat = pm.Lognormal('y_hat', mu = mu, sd = sigma, observed = df['response'] )

    trace = pm.sample(2000, tune = 2000)

下一步是测量模型正确的扩展,因此我计算数据集的平均响应,即

mu_hat = np.exp(trace['mu'].mean(0)

但是,当我绘制该平均值与测试集的拟合程度时,我观察到拟合度非常差:

在此处输入图像描述

可能的解决方案:我尝试了其他可能性,如 Normal 和 Poisson,但我无法实现模型的收敛。我收到一条错误消息:

Bad initial energy: inf. The model might be misspecified.

关于为什么这种适合如此悲惨地失败的任何想法?

4

1 回答 1

2

看起来您的 X 具有线性响应的对数正态分布,并且 X 的大小可能存在一些线性误差。如果没有数据,很难说,但这是我对您的问题的重现:

matplotlib inline

import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns

x = np.random.lognormal(5, 1, 10000)
y = x * np.random.normal(5,1,10000)

f, axes = plt.subplots(2, 1, figsize=(16,12))
sns.scatterplot(x,y, ax=axes[0])
sns.distplot(np.log(y), ax=axes[1])

x 和 y 的散点图,log(y) 的分布

然后我们可以对 x 系数和相关 y 误差进行建模:

with pm.Model() as model: 
    sigma = pm.InverseGamma('sigma', mu=(y/x).std(), sd = (y/x).std()/len(x))
    #intercept = pm.Normal('Intercept', 0, sigma=1)
    x_coeff = pm.Normal('x_coeff', (y/x).mean(), sigma=1)

    l = pm.Normal('l', mu=x_coeff, sigma=sigma, observed=y/x)

    trace = pm.sample(3000, tune=1000, cores=4)

现在绘制我们得到的线条:

f, axes = plt.subplots(figsize=(16,8))
sns.scatterplot(x, y, ax=axes)
for (_,val) in pm.stats.quantiles(trace['x_coeff']).items():
    plt.plot(x, val*x, color='b')
    for (__, sd) in pm.stats.quantiles(trace['sigma']).items():
        plt.plot(x, (val+2*sd)*x, color='r')
        plt.plot(x, (val-2*sd)*x, color='r')

用 2*sd 正负绘制的 x 系数

于 2019-08-05T01:55:53.003 回答