Я хотел бы использовать mlr для запуска xgboost на данных о выживании с правой цензурой в R. Код xgboost перечисляет целевую функцию выживания: cox, которая говорит:
survival:cox: Cox regression for right censored survival time data (negative values are considered right censored).
Mlr 2, который я использую, поддерживает только xgboost для обучения регрессии и классификации. Если я попытаюсь использовать встроенный регрессионный обучающий модуль для xgboost, он использует mse в качестве метрики оценки. Поэтому я попытался изменить метрику на cindex и получил ошибку
Measures: cindex cindex
Error in FUN(X[[i]], ...) : Measure cindex does not support task type regr!
Итак, затем я попытался написать новый обучающий модуль выживания для xgboost, который является просто копией регрессионного обучающего модуля, но с заменой «Regr» на «Surv», но, конечно, он ожидает, что цель будет иметь 2 столбца — время и статус — и не принимает отрицательное время, тогда как xgboost ожидает только один столбец — время — и предполагает, что любые строки с отрицательным значением времени подвергаются цензуре.
Ниже то, что я пробовал. Есть ли способ добиться этого в mlr2 или mlr3?
data(veteran)
veteran_xgb <- veteran
veteran_xgb <- veteran_xgb[c("trt", "karno", "diagtime", "age", "prior", "time")]
veteran_xgb$time <- ifelse(veteran$status==1, veteran$time, -veteran$time)
xgb.task <- makeRegrTask(id = "XGBOOST_VET", data = veteran_xgb, target = "time")
xgb_learner <- makeLearner(id = "xgboost",
cl = "regr.xgboost",
predict.type = "response",
par.vals = list(
objective = "survival:cox",
eval_metric = "cox-nloglik",
nrounds = 200
)
)
learners = list(xgb_learner)
outer = makeResampleDesc("CV", iters=5) # Benchmarking
bmr = benchmark(learners, xgb.task, outer, show.info = TRUE)
data(veteran)
veteran_xgb <- veteran
veteran_xgb <- veteran_xgb[c("trt", "karno", "diagtime", "age", "prior", "time", "status")]
veteran_xgb$time <- ifelse(veteran$status==1, veteran$time, -veteran$time)
xgb.task <- makeSurvTask(id = "XGBOOST_VET", data = veteran_xgb, target = c("time", "status"))
xgb_learner <- makeLearner(id = "xgboost",
cl = "surv.xgboost",
predict.type = "response",
par.vals = list(
objective = "survival:cox",
eval_metric = "cox-nloglik",
nrounds = 200
)
)
learners = list(xgb_learner)
outer = makeResampleDesc("CV", iters=5) # Benchmarking
surv.measures = list(cindex)
bmr = benchmark(learners, xgb.task, outer, surv.measures, show.info = TRUE)
Файл RLearner_surv_xgboost.R можно скачать с OneDrive здесь https://1drv.ms/u/s!AjTjdzp0sDJRrhZtZF5-HZF2BrBB?e=FNLS94
Да, @Lars Kotthoff, я пытаюсь создать версию xgboost для выживания в млр. Спасибо за ваш ответ. Я знаю, как создать своего собственного обучающегося, но основная проблема, как я описал выше, заключается в том, что обучаемый модуль выживания ожидает, что цель будет иметь 2 столбца, статус и время, тогда как xgboost ожидает, что цель будет иметь только один столбец, время , а статус определяется тем, является ли время положительным или отрицательным. Поэтому я не вижу никакого способа создать версию xgboost для выживания в млр.
Похоже, вы не можете сделать это с помощью xgboost. Может Эта проблема поможет?
Я нашел решение и обновил свой пользовательский ученик здесь: https://1drv.ms/u/s!AjTjdzp0sDJRrhewy0yx3Wot3FiI?e=sxRrTN
Хитрость заключалась в изменении функции trainlearner.surv.xgboost. Будучи учеником выживания, он ожидает, что будут переданы данные с целью, содержащей 2 столбца времени и статуса. Но в этом обучающем модуле мы можем вычислить цель, которую ожидает xgboost, с отрицательным временем для подвергнутых цензуре данных, а затем передать эту новую цель с одним столбцом в xgboost:
trainLearner.surv.xgboost = function(.learner, .task, .subset, .weights = NULL, ...) {
parlist = list(...)
if (is.null(parlist$objective))
{
parlist$objective = "survival:cox"
parlist$eval_metric = "cox-nloglik"
}
task.data = getTaskData(.task, .subset, target.extra = TRUE)
survtime <- ifelse(task.data$target$status==1, task.data$target$time, -task.data$target$time)
parlist$data = xgboost::xgb.DMatrix(data = data.matrix(task.data$data), label = survtime)
if (!is.null(.weights))
xgboost::setinfo(parlist$data, "weight", .weights)
if (is.null(parlist$watchlist))
parlist$watchlist = list(train = parlist$data)
do.call(xgboost::xgb.train, parlist)
}
Затем, чтобы использовать этого нового ученика:
library(xgboost)
library(survival)
library(mlr)
source("RLearner_surv_xgboost.R")
data(veteran)
veteran.xgb <- veteran[, !(names(veteran) %in% c("celltype"))]
xgb.task <- makeSurvTask(id = "XGBOOST_VET", data = veteran.xgb, target = c("time", "status"))
surv.measures = list(cindex)
outer= makeResampleDesc("CV", iters=5)
xgb.learner <- makeLearner(id = "xgboost",
cl = "surv.xgboost",
predict.type = "response")
learners = list(xgb.learner)
bmr = benchmark(learners, xgb.task, outer, surv.measures, show.info = TRUE)
Эй, @panda, ты знал, что можешь отмечать свои вопросы?
Если я правильно понимаю, вы пытаетесь реализовать версию xgboost для выживания? Вы смотрели на некоторых других учеников выживания, чтобы увидеть, как они реализованы? обучающая глава о том, как создать своего собственного ученика также должен быть полезен.