- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试重新创建统计学习简介 中的图,但我无法弄清楚如何计算概率预测的置信区间。具体来说,我正在尝试重新创建此图 (figure 7.1) 的右侧面板,该面板根据年龄的 4 次多项式和相关的 95% 置信区间预测工资>250 的概率。工资数据为here如果有人关心的话。
我可以使用以下代码预测并绘制预测概率
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)
但我不知道预测概率的置信区间是如何计算的。我曾多次考虑过引导数据以获得每个年龄段的概率分布,但我知道有一种更简单的方法,但我无法掌握。
我有估计系数协方差矩阵和与每个估计系数相关的标准误差。鉴于此信息,我将如何计算上图右侧面板中所示的置信区间?
谢谢!
最佳答案
您可以使用 delta method找到预测概率的近似方差。即,
var(proba) = np.dot(np.dot(gradient.T, cov), gradient)
其中gradient
是模型系数预测概率的导数向量,cov
是系数的协方差矩阵。
事实证明,Delta 方法对所有最大似然估计都可以渐进地工作。但是,如果您的训练样本较小,渐近方法可能效果不佳,您应该考虑自举。
这是一个将 delta 方法应用于逻辑回归的玩具示例:
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()
它会给出下面的图片
看起来很像里面有大象的 python 。
您可以将它与 bootstrap 估计进行比较:
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 方法假设预测概率是正常的,而在书中,log-odds 是正常的。事实上,它们在有限样本中都不是正态的,而在无限样本中都收敛于正态,只是它们的方差同时收敛于零。最大似然估计对重新参数化不敏感,但它们的估计分布却很敏感,这就是问题所在。
关于python - 逻辑回归统计模型概率预测的置信区间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47414842/
我在 Python 中使用 matplotlib,并制作了一个带条形的直方图。现在,当直方图出现时,仅 5 的倍数出现在 x 轴上,1000 的倍数出现在 y 轴上。对于 y 轴,这完全没有问题,但对
我正在使用 JavaScript 和 jQuery。我有以下脚本每 30 秒提醒一次 hi。 $(document).ready( function() { alert("hi"); setI
已结束。此问题正在寻求书籍、工具、软件库等的推荐。它不满足Stack Overflow guidelines 。目前不接受答案。 我们不允许提出寻求书籍、工具、软件库等推荐的问题。您可以编辑问题,以便
在 Numpy(python 包)中,可以使用语法 numpy.linspace(minValue, MaxValue, numberOfSamples) 构造 float 的离散区间。 . 我看到
所以我想在 -3 到 3 的区间内制作一些数字,以便在下面绘制这些函数,所以我想要尽可能多的数字。 我这样做: double k[601]; double y[601]; for (int i = 0
我有一个 Postgresql 表,用于存储有关计划进程的信息,包括上次执行进程的时间。不同的进程对其运行频率有不同的要求。 我列出了需要重新运行的进程列表: SELECT * FROM proces
如何正确使用此类带日期间隔的查询 @SqlUpdate("delete fromlogin where created < now() - ':days days' :: interval") v
我正在尝试计算图中的间隔,我在维基百科上找到了算法的数学描述: http://en.wikipedia.org/wiki/Interval_(graph_theory) H = { n0 }
我有一个基于 Informix-SQL 的 Pawnshop 应用程序,该应用程序根据黄金的重量和纯度计算应向客户贷出多少钱。当铺的最低贷款额为 5.00 美元。当铺员工通常会借出以 5 或 0 结尾
我将 NHibernate 与代码映射一起使用,并且我有一个由此公式创建的属性。 Property(x => x.IsInOverdue, mapper => mapper .Fo
我正在尝试从头开始为 Beta 分布编写卡方拟合优度检验,而不使用任何外部函数。下面的代码报告“1”适合,即使来自 scipy.stats 的 kstest 返回零。数据是正常分布的,所以我的函数也应
如何在 C# 中将任何值四舍五入到 10 区间?例如,如果我有 11,我希望它返回 10,如果我有 136,那么我希望它返回 140。 我可以很容易地用手做 return ((int)(number
如何在 Go 中表示 PostgreSQL 区间? 我的结构看起来像这样: type Product struct { Id int Name
我想编写一个函数,将数值限制在封闭的 0,1 区间内: func clamp01(_ value:T) -> T { return value 1 ? 1 : value } 在 Swift 3
我有一个简单的表格,用于存储来自在线仪表的降水读数。这是表定义: CREATE TABLE public.precip ( gauge_id smallint,
a = y def __gt__(self, y): return not self.x > y def __eq__(self, y): return
我正在处理 pandas 数据框 D=pd.DataFrame(data=[1.0,2.0,2.0,2.0,5.0,3.0,2.0,2.0,5.0,5.0,8.0,1.0]) 我识别低于特定阈值的值
我编写了一些C++代码来解决此问题: #include #include using namespace std; unsigned int countSetBits(unsigned int n
好的,我知道之前有人用一个有限的缩放示例问过这个问题 [-1, 1]间隔 [a, b] Different intervals for Gauss-Legendre quadrature in num
我是一名优秀的程序员,十分优秀!