具有对数正态响应 PYMC3 的线性回归

Linear Regression with Lognormal Response PYMC3

这是我第一次尝试为对数正态分布的响应建模线性回归。 我有一个包含两个变量的数据框 df:预测变量 X 和响应。 当我绘制 response 与预测变量 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)

但是,当我绘制这个平均值与测试集的拟合程度时,我发现拟合度很差:

可能的解决方案:我已经尝试了其他可能性,例如正态和泊松,但我无法实现模型的收敛。我收到一条错误消息:

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

关于为什么这次合身如此惨败有什么想法吗?

看起来您的 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])

Scatterplot of x and y, distribution of 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')

x coefficients plotted with 2*sd positive and negative