什么是生存分析
生存分析(回归)模型时间到感兴趣事件的持续时间。生存分析是一种特殊的回归,与传统的回归任务不同,具体如下:
- 标签始终为正值,因为不能等待负时间直到事件发生
- 标签可能不是完全已知,或被截断,因为“测量时间需要时间”
第二点至关重要,更深入地研究一下。正如从名称中猜到的那样,生存分析的最早应用之一是对给定人群的死亡率进行建模。以NCCTG肺癌数据集为例。前8列表示特征,最后一列“生存时间”表示标签。
Inst | Age | Sex | ph.ecog | ph.karno | pat.karno | meal.cal | wt.loss | Time to death (days) |
---|---|---|---|---|---|---|---|---|
3 | 74 | 1 | 1 | 90 | 100 | 1175 | N/A | 306 |
3 | 68 | 1 | 0 | 90 | 90 | 1225 | 15 | 455 |
3 | 56 | 1 | 0 | 90 | 90 | N/A | 15 | [1010, ∞) |
5 | 57 | 1 | 1 | 90 | 60 | 1150 | 11 | 210 |
1 | 60 | 1 | 0 | 100 | 90 | N/A | 0 | 883 |
12 | 74 | 1 | 1 | 50 | 80 | 513 | 0 | [1022, ∞) |
7 | 68 | 2 | 2 | 70 | 60 | 384 | 10 | 310 |
仔细看一下第三位患者的标签,是一个范围,而不是一个单一的数字。第三位患者的标签被称为被截断,因为由于某种原因实验者无法获得该标签的完整测量。可能的情况之一:患者在第1010天幸存并于第1011天走出诊所,因此他的死亡并没有直接观察到。另一种可能性:由于实验无法永远进行,实验被提前中断,无法观察到他的死亡。在任何情况下,他的标签是,这意味着他的死亡时间可以是任何大于1010的数字,例如2000、3000或10000。
有四种类型的截断:
- 未被截断:标签未被截断,以单一数字给出
- 右截断:标签的形式为,其中是下限
- 左截断:标签的形式为,其中是上限
- 区间截断:标签的形式为,其中和分别是下限和上限。
右截断是最常用的。
加速故障时间模型
加速失效时间(AFT) 模型是生存分析中最常用的模型之一。该模型的形式如下:
其中:
- 是表示特征的向量
- 是由个系数组成的向量,每个系数对应一个特征
- 是向量的点积
- 是自然对数
- 和是随机变量
- 是输出标签
- 是已知概率分布的随机变量。常见的选择包括正态分布、逻辑分布和极值分布。直观地说,表示将预测值从真实对数标签远离的“噪声”。
- 是缩放的参数
请注意,该模型是线性回归模型的广义形式。为了使AFT与梯度提升一起工作,将模型修改为:
其中表示给定输入的决策树集合的输出。由于是随机变量,可以为表达式定义一个似然性。因此,XGBoost 的目标是通过拟合良好的决策树集合来最大化(对数)似然性。
如何使用
第一步是将标签表示为范围的形式,使得每个数据点都与两个数字关联,即标签的下界和上界。对于未被截断的标签,请使用形式的退化区间。
Censoring type | Interval form | Lower bound finite? | Upper bound finite? |
---|---|---|---|
Uncensored | [a, a] | ✔ | ✔ |
Right-censored | [a, ∞) | ✔ | ✘ |
Left-censored | [0, b] | ✔ | ✔ |
Interval-censored | [a, b] | ✔ | ✔ |
将下界数值收集到一个数组中(y_lower_bound
),将上界数值收集到另一个数组中(y_upper_bound
)。通过调用xgboost.DMatrix.set_float_info()
,将范围标签与数据矩阵对象关联起来:
import numpy as np
import xgboost as xgb
# 4-by-2 Data matrix
X = np.array([[1, -1], [-1, 1], [0, 1], [1, 0]])
dtrain = xgb.DMatrix(X)
# Associate ranged labels with the data matrix.
# This example shows each kind of censored labels.
# uncensored right left interval
y_lower_bound = np.array([ 2.0, 3.0, 0.0, 4.0])
y_upper_bound = np.array([ 2.0, np.inf, 4.0, 5.0])
dtrain.set_float_info('label_lower_bound', y_lower_bound)
dtrain.set_float_info('label_upper_bound', y_upper_bound)
params = {'objective': 'survival:aft',
'eval_metric': 'aft-nloglik',
'aft_loss_distribution': 'normal',
'aft_loss_distribution_scale': 1.20,
'tree_method': 'hist', 'learning_rate': 0.05, 'max_depth': 2}
bst = xgb.train(params, dtrain, num_boost_round=100,
evals=[(dtrain, 'train')])
将目标参数objective
设置为survival:aft
,将评估指标设置eval_metric
为aft-nloglik
,以便最大化AFT模型的对数似然。 (XGBoost实际上将最小化负对数似然,因此称为aft-nloglik
)
参数aft_loss_distribution
对应于AFT模型中项的分布,而aft_loss_distribution_scale
对应于缩放因子 。
目前,可以从三个概率分布中选择aft_loss_distribution
: