Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/visual-studio-code/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python logistic回归统计模型概率预测的置信区间_Python_Logistic Regression_Statsmodels_Confidence Interval - Fatal编程技术网

Python logistic回归统计模型概率预测的置信区间

Python logistic回归统计模型概率预测的置信区间,python,logistic-regression,statsmodels,confidence-interval,Python,Logistic Regression,Statsmodels,Confidence Interval,我正试图根据《统计学习导论》重新创建一个图,但我很难弄清楚如何计算概率预测的置信区间。具体地说,我试图重新创建这个图()的右侧面板,该面板根据年龄的4次多项式预测工资>250的概率,相关的95%置信区间。如果有人在乎的话,工资数据就是 我可以用下面的代码预测和绘制预测的概率 import pandas as pd import numpy as np import matplotlib.pyplot as plt import statsmodels.api as sm from sklearn

我正试图根据《统计学习导论》重新创建一个图,但我很难弄清楚如何计算概率预测的置信区间。具体地说,我试图重新创建这个图()的右侧面板,该面板根据年龄的4次多项式预测工资>250的概率,相关的95%置信区间。如果有人在乎的话,工资数据就是

我可以用下面的代码预测和绘制预测的概率

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import statsmodels.api as sm
from sklearn.preprocessing import PolynomialFeatures

wage = pd.read_csv('../../data/Wage.csv', index_col=0)
wage['wage250'] = 0
wage.loc[wage['wage'] > 250, 'wage250'] = 1

poly = Polynomialfeatures(degree=4)
age = poly.fit_transform(wage['age'].values.reshape(-1, 1))

logit = sm.Logit(wage['wage250'], age).fit()

age_range_poly = poly.fit_transform(np.arange(18, 81).reshape(-1, 1))

y_proba = logit.predict(age_range_poly)

plt.plot(age_range_poly[:, 1], y_proba)
但是我不知道预测概率的置信区间是如何计算的。我已经考虑过多次引导数据,以获得每个年龄段的概率分布,但我知道有一种更简单的方法,这是我无法掌握的

我有估计系数协方差矩阵和与每个估计系数相关的标准误差。在给定这些信息的情况下,如何计算上图右侧面板所示的置信区间

谢谢

您可以使用来查找预测概率的近似方差。即

var(proba) = np.dot(np.dot(gradient.T, cov), gradient)
其中,
gradient
是模型系数预测概率的导数向量,
cov
是系数的协方差矩阵

Delta方法被证明是渐近工作的所有最大似然估计。但是,如果你有一个小的训练样本,渐近方法可能不能很好地工作,你应该考虑引导。 下面是一个将delta方法应用于logistic回归的示例:

import numpy as np
import statsmodels.api as sm
import matplotlib.pyplot as plt

# generate data
np.random.seed(1)
x = np.arange(100)
y = (x * 0.5 + np.random.normal(size=100,scale=10)>30)
# estimate the model
X = sm.add_constant(x)
model = sm.Logit(y, X).fit()
proba = model.predict(X) # predicted probability

# estimate confidence interval for predicted probabilities
cov = model.cov_params()
gradient = (proba * (1 - proba) * X.T).T # matrix of gradients for each observation
std_errors = np.array([np.sqrt(np.dot(np.dot(g, cov), g)) for g in gradient])
c = 1.96 # multiplier for confidence interval
upper = np.maximum(0, np.minimum(1, proba + std_errors * c))
lower = np.maximum(0, np.minimum(1, proba - std_errors * c))

plt.plot(x, proba)
plt.plot(x, lower, color='g')
plt.plot(x, upper, color='g')
plt.show()
它描绘了以下美好的画面:

对于您的示例,代码是

proba = logit.predict(age_range_poly)
cov = logit.cov_params()
gradient = (proba * (1 - proba) * age_range_poly.T).T 
std_errors = np.array([np.sqrt(np.dot(np.dot(g, cov), g)) for g in gradient])
c = 1.96 
upper = np.maximum(0, np.minimum(1, proba + std_errors * c))
lower = np.maximum(0, np.minimum(1, proba - std_errors * c))

plt.plot(age_range_poly[:, 1], proba)
plt.plot(age_range_poly[:, 1], lower, color='g')
plt.plot(age_range_poly[:, 1], upper, color='g')
plt.show()
它会给出下面的图片

看起来很像一条里面有大象的蟒蛇

您可以将其与引导估计值进行比较:

preds = []
for i in range(1000):
    boot_idx = np.random.choice(len(age), replace=True, size=len(age))
    model = sm.Logit(wage['wage250'].iloc[boot_idx], age[boot_idx]).fit(disp=0)
    preds.append(model.predict(age_range_poly))
p = np.array(preds)
plt.plot(age_range_poly[:, 1], np.percentile(p, 97.5, axis=0))
plt.plot(age_range_poly[:, 1], np.percentile(p, 2.5, axis=0))
plt.show()

delta方法和bootstrap的结果看起来几乎相同

然而,这本书的作者走了第三条路。他们利用这样一个事实

proba=np.exp(np.dot(x,params))/(1+np.exp(np.dot(x,params)))

计算线性部分的置信区间,然后使用logit函数进行变换

xb = np.dot(age_range_poly, logit.params)
std_errors = np.array([np.sqrt(np.dot(np.dot(g, cov), g)) for g in age_range_poly])
upper_xb = xb + c * std_errors
lower_xb = xb - c * std_errors
upper = np.exp(upper_xb) / (1 + np.exp(upper_xb))
lower = np.exp(lower_xb) / (1 + np.exp(lower_xb))
plt.plot(age_range_poly[:, 1], upper)
plt.plot(age_range_poly[:, 1], lower)
plt.show()
所以他们得到了发散间隔:


这些方法产生如此不同的结果,因为它们假设不同的事物(预测概率和对数概率)正态分布。也就是说,delta方法假设预测的概率是正常的,在书中,对数概率是正常的。事实上,它们在有限样本中都不是正态的,但在无限样本中它们都收敛到,但它们的方差同时收敛到零。最大似然估计对重新参数化不敏感,但它们的估计分布是不敏感的,这就是问题所在。

这里有一个有指导意义的有效方法来计算statsmodels Logit()对象(“fit”)上拟合('mean_se')和单次观测('obs_se')的标准误差('se'),与《ISLR》一书中的方法和David Dale答案中的最后一种方法相同:

fit_mean = fit.model.exog.dot(fit.params)
fit_mean_se = ((fit.model.exog*fit.model.exog.dot(fit.cov_params())).sum(axis=1))**0.5
fit_obs_se = ( ((fit.model.endog-fit_mean).std(ddof=fit.params.shape[0]))**2 + \
                fit_mean_se**2 )**0.5

阴影区域表示拟合和单次观察的95%置信区间


欢迎提出改进意见。

回答得很好,大卫,谢谢!偏离的置信区间真的让我大吃一惊。@DavidDale回答得很好,但如果你澄清哪种方法假设预测概率为正态分布(增量法),哪种方法假设对数概率为正态分布(转换法,即你显示的最后一个图),那就更好了.你好,大卫,回答得很好-我试图用Sklearn.LogisticRecession重现你的结果,但是predict_proba的结果不同-你为什么这么认为?你好,大卫,你用线性部分的置信区间计算的结果将给我们反应的预测区间?或平均响应的置信区间?如果它给出了置信区间,我们如何计算预测区间?我计算平均响应的置信区间。它是二元分类,因此预测区间总是{0}、{1}或[0,1]。我认为这样的间隔没有多大意义。