Можно ли запустить модель Кокса-Пропорционально-Опасных Опасностей с экспоненциальным распределением базовой опасности в «линиях жизни» или другом пакете? - PullRequest
0 голосов
/ 27 июня 2019

Я рассматриваю возможность использования пакета lifelines для установки модели Cox-Proportional-Hazards-Model .Я читал, что спасательный круг использует непараметрический подход для соответствия базовой опасности , что приводит к различным baseline_hazards для некоторых моментов времени (см. Пример кода ниже).Для моего приложения мне нужно экспоненциальное распределение, приводящее к базовой опасности h0 (t) = lambda , которая постоянна во времени.

Итак, мой вопрос: возможно ли (пока) запустить модель Кокса-Пропорционального риска с экспоненциальным распределением для базовой опасности в lifelines или другом пакете Python?

Пример кода:

from lifelines import CoxPHFitter
import pandas as pd

df = pd.DataFrame({'duration': [4, 6, 5, 5, 4, 6], 
                   'event': [0, 0, 0, 1, 1, 1], 
                   'cat': [0, 1, 0, 1, 0, 1]})

cph = CoxPHFitter()
cph.fit(df, duration_col='duration', event_col='event', show_progress=True)
cph.baseline_hazard_

дает

        baseline hazard
T   
4.0     0.160573
5.0     0.278119
6.0     0.658032

1 Ответ

1 голос
/ 27 июня 2019

Автор iflifelines здесь.

Итак, эта модель изначально не существует, но вы можете легко реализовать ее самостоятельно (и, возможно, что-то, что я сделаю для будущего выпуска).Эта идея опирается на пересечение моделей пропорциональной опасности и моделей AFT (ускоренное время отказа).В модели cox-ph с экспоненциальной опасностью (т.е. постоянной базовой опасностью) опасность выглядит следующим образом:

h(t|x) = lambda_0(t) * exp(beta * x) = lambda_0 * exp(beta * x)

В спецификации AFT для экспоненциального распределения опасность выглядит следующим образом:

h(t|x) = exp(-beta * x - beta_0) = exp(-beta * x) * exp(-beta_0) = exp(-beta * x) * lambda_0

Обратите внимание на разницу отрицательных знаков!

Таким образом, вместо того, чтобы делать CoxPH, мы можем сделать экспоненциальную подборку AFT (и перевернуть знаки, если мы хотим получить ту же интерпретацию, что и CoxPH).Для этого мы можем использовать собственный синтаксис модели regession:

from lifelines.fitters import ParametricRegressionFitter
from autograd import numpy as np


class ExponentialAFTFitter(ParametricRegressionFitter):

    # this is necessary, and should always be a non-empty list of strings.
    _fitted_parameter_names = ['lambda_']

    def _cumulative_hazard(self, params, T, Xs):
        # params is a dictionary that maps unknown parameters to a numpy vector.
        # Xs is a dictionary that maps unknown parameters to a numpy 2d array
        lambda_ = np.exp(np.dot(Xs['lambda_'], params['lambda_']))
        return T / lambda_

Проверка этого,

from lifelines.datasets import load_rossi
from lifelines import CoxPHFitter

rossi = load_rossi()
rossi['intercept'] = 1
regressors = {'lambda_': rossi.columns}
eaf = ExponentialAFTFitter().fit(rossi, "week", "arrest", regressors=regressors)

eaf.print_summary()
"""
<lifelines.ExponentialAFTFitter: fitted with 432 observations, 318 censored>
         event col = 'arrest'
number of subjects = 432
  number of events = 114
    log-likelihood = -686.37
  time fit was run = 2019-06-27 15:13:18 UTC

---
                    coef exp(coef)  se(coef)     z      p  -log2(p)  lower 0.95  upper 0.95
lambda_ fin         0.37      1.44      0.19  1.92   0.06      4.18       -0.01        0.74
        age         0.06      1.06      0.02  2.55   0.01      6.52        0.01        0.10
        race       -0.30      0.74      0.31 -0.99   0.32      1.63       -0.91        0.30
        wexp        0.15      1.16      0.21  0.69   0.49      1.03       -0.27        0.56
        mar         0.43      1.53      0.38  1.12   0.26      1.93       -0.32        1.17
        paro        0.08      1.09      0.20  0.42   0.67      0.57       -0.30        0.47
        prio       -0.09      0.92      0.03 -3.03 <0.005      8.65       -0.14       -0.03
        _intercept  4.05     57.44      0.59  6.91 <0.005     37.61        2.90        5.20
_fixed  _intercept  0.00      1.00      0.00   nan    nan       nan        0.00        0.00
---
"""

CoxPHFitter().fit(load_rossi(), 'week', 'arrest').print_summary()
"""
<lifelines.CoxPHFitter: fitted with 432 observations, 318 censored>
      duration col = 'week'
         event col = 'arrest'
number of subjects = 432
  number of events = 114
partial log-likelihood = -658.75
  time fit was run = 2019-06-27 15:17:41 UTC

---
      coef exp(coef)  se(coef)     z      p  -log2(p)  lower 0.95  upper 0.95
fin  -0.38      0.68      0.19 -1.98   0.05      4.40       -0.75       -0.00
age  -0.06      0.94      0.02 -2.61   0.01      6.79       -0.10       -0.01
race  0.31      1.37      0.31  1.02   0.31      1.70       -0.29        0.92
wexp -0.15      0.86      0.21 -0.71   0.48      1.06       -0.57        0.27
mar  -0.43      0.65      0.38 -1.14   0.26      1.97       -1.18        0.31
paro -0.08      0.92      0.20 -0.43   0.66      0.59       -0.47        0.30
prio  0.09      1.10      0.03  3.19 <0.005      9.48        0.04        0.15
---
Concordance = 0.64
Log-likelihood ratio test = 33.27 on 7 df, -log2(p)=15.37
"""

Обратите внимание на изменение знака!Так что если вы хотите постоянную базовую опасность в модели, это exp(-4.05).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...