【问题标题】:How to use scale and shape parameters of gamma GLM in statsmodels如何在 statsmodels 中使用 gamma GLM 的尺度和形状参数
【发布时间】:2021-01-18 07:28:03
【问题描述】:

任务

我的数据如下所示:

我想使用 statsmodels 将广义线性模型 (glm) 从伽马系列拟合到此。使用这个模型,对于我的每个观察,我想计算观察到小于(或等于)该值的值的概率。换句话说我要计算:

P(y

我的问题

  • 如何从statsmodels 中的拟合 glm 中获取形状和比例参数?根据this question,statsmodels 中的 scale 参数未以正常方式参数化。我可以将它直接用作scipy 中伽马分布的输入吗?还是我需要先转型?

  • 如何使用这些参数(形状和比例)来获得概率?目前我正在使用scipy 为每个x_i 生成分布并从中获取概率。请参阅下面的实现。

我目前的实现

import scipy.stats as stat
import patsy
import statsmodels.api as sm

# Generate data in correct form
y, X = patsy.dmatrices('y ~ x', data=myData, return_type='dataframe')

# Fit model with gamma family and log link
mod = sm.GLM(y, X, family=sm.families.Gamma(sm.families.links.log())).fit()

# Predict mean
myData['mu'] = mod.predict(exog=X) 

# Predict probabilities (note that for a gamma distribution mean = shape * scale)
probabilities = np.array(
    [stat.gamma(m_i/mod.scale, scale=mod.scale).cdf(y_i) for m_i, y_i in zip(myData['mu'], myData['y'])]
)

但是,当我执行此过程时,我得到以下结果:

目前预测的概率似乎都很高。图中的红线是预测平均值。但即使对于低于这条线的点,预测的累积概率也在 80% 左右。这让我怀疑我使用的比例参数是否确实是正确的。

【问题讨论】:

    标签: python statistics regression statsmodels


    【解决方案1】:

    在 R 中,您可以使用 1/色散作为形状估计值(检查此post)。不幸的是,statsmodels 中色散估计的命名是 scale。所以你确实取了这个的倒数来得到形状估计。我用下面的例子来展示它:

    values = gamma.rvs(2,scale=5,size=500)
    fit = sm.GLM(values, np.repeat(1,500), family=sm.families.Gamma(sm.families.links.log())).fit()
    

    这是一个仅截距模型,我们检查截距和离散度(命名尺度):

    [fit.params,fit.scale]
    [array([2.27875973]), 0.563667465203953]
    

    所以平均值是 exp(2.2599) = 9.582131,如果我们使用 shape 作为 1/dispersion ,shape = 1/0.563667465203953 = 1.774096 这就是我们模拟的结果。

    如果我使用模拟数据集,它可以正常工作。这是它的样子,形状为 10:

    from scipy.stats import gamma
    import numpy as np
    import matplotlib.pyplot as plt
    import patsy
    import statsmodels.api as sm
    import pandas as pd
    
    _shape = 10
    myData = pd.DataFrame({'x':np.random.uniform(0,10,size=500)})
    myData['y'] = gamma.rvs(_shape,scale=np.exp(-myData['x']/3 + 0.5)/_shape,size=500)
    
    myData.plot("x","y",kind="scatter")
    

    然后我们像你一样拟合模型:

    y, X = patsy.dmatrices('y ~ x', data=myData, return_type='dataframe')
    mod = sm.GLM(y, X, family=sm.families.Gamma(sm.families.links.log())).fit()
    mu = mod.predict(exog=X) 
    
    shape_from_model = 1/mod.scale
    
    probabilities = [gamma(shape_from_model, scale=m_i/shape_from_model).cdf(y_i) for m_i, y_i in zip(mu,myData['y'])]
    

    还有情节:

    fig, ax = plt.subplots()
    im = ax.scatter(myData["x"],myData["y"],c=probabilities)
    im = ax.scatter(myData['x'],mu,c="r",s=1)
    fig.colorbar(im, ax=ax)
    

    【讨论】:

    • 如果我理解正确,mod.scale 实际上是 1/shape 的色散。所以mod.scale = 1/shape。如果我使用你的代码并检查这个,我确实找到了mod.scale = .1009。我不明白的是为什么你没有改变probabilities的计算。现在你使用m_i/mod.scale 作为形状参数。但这等于m_i/dispersion = m_i * shape = scale * shape^2。作为您使用的比例 mod.scale = dispersion = 1/shape。不应该是gamma(1/mod.scale, scale=m_i * mod.scale).cdf(y_i)吗?
    • 是的,你是对的,抱歉我写的太晚了,我从错误的笔记本单元格中获取了概率......我已经更新了代码。现在应该是正确的。感谢您发现错误!
    猜你喜欢
    • 2020-05-29
    • 2017-07-25
    • 2019-11-03
    • 2021-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-04
    • 2013-05-15
    相关资源
    最近更新 更多