R: где шаг градиента в исходном коде xgboost? - PullRequest
5 голосов
/ 25 апреля 2020

Ниже приведен исходный код для функции xgb.train в пакете xgboost.

library(xgboost)
> xgb.train
function (params = list(), data, nrounds, watchlist = list(), 
    obj = NULL, feval = NULL, verbose = 1, print_every_n = 1L, 
    early_stopping_rounds = NULL, maximize = NULL, save_period = NULL, 
    save_name = "xgboost.model", xgb_model = NULL, callbacks = list(), 
    ...) 
{
    check.deprecation(...)
    params <- check.booster.params(params, ...)
    check.custom.obj()
    check.custom.eval()
    dtrain <- data
    if (!inherits(dtrain, "xgb.DMatrix")) 
        stop("second argument dtrain must be xgb.DMatrix")
    if (length(watchlist) > 0) {
        if (typeof(watchlist) != "list" || !all(vapply(watchlist, 
            inherits, logical(1), what = "xgb.DMatrix"))) 
            stop("watchlist must be a list of xgb.DMatrix elements")
        evnames <- names(watchlist)
        if (is.null(evnames) || any(evnames == "")) 
            stop("each element of the watchlist must have a name tag")
    }
    params <- c(params, list(silent = ifelse(verbose > 1, 0, 
        1)))
    print_every_n <- max(as.integer(print_every_n), 1L)
    if (!has.callbacks(callbacks, "cb.print.evaluation") && verbose) {
        callbacks <- add.cb(callbacks, cb.print.evaluation(print_every_n))
    }
    evaluation_log <- list()
    if (!has.callbacks(callbacks, "cb.evaluation.log") && length(watchlist) > 
        0) {
        callbacks <- add.cb(callbacks, cb.evaluation.log())
    }
    if (!is.null(save_period) && !has.callbacks(callbacks, "cb.save.model")) {
        callbacks <- add.cb(callbacks, cb.save.model(save_period, 
            save_name))
    }
    stop_condition <- FALSE
    if (!is.null(early_stopping_rounds) && !has.callbacks(callbacks, 
        "cb.early.stop")) {
        callbacks <- add.cb(callbacks, cb.early.stop(early_stopping_rounds, 
            maximize = maximize, verbose = verbose))
    }
    cb <- categorize.callbacks(callbacks)
    if (!is.null(params[["seed"]])) {
        warning("xgb.train: `seed` is ignored in R package.  Use `set.seed()` instead.")
    }
    is_update <- NVL(params[["process_type"]], ".") == "update"
    handle <- xgb.Booster.handle(params, append(watchlist, dtrain), 
        xgb_model)
    bst <- xgb.handleToBooster(handle)
    num_class <- max(as.numeric(NVL(params[["num_class"]], 1)), 
        1)
    num_parallel_tree <- max(as.numeric(NVL(params[["num_parallel_tree"]], 
        1)), 1)
    niter_init <- 0
    if (!is.null(xgb_model)) {
        niter_init <- as.numeric(xgb.attr(bst, "niter")) + 1
        if (length(niter_init) == 0) {
            niter_init <- xgb.ntree(bst)%/%(num_parallel_tree * 
                num_class)
        }
    }
    if (is_update && nrounds > niter_init) 
        stop("nrounds cannot be larger than ", niter_init, " (nrounds of xgb_model)")
    rank <- 0
    niter_skip <- ifelse(is_update, 0, niter_init)
    begin_iteration <- niter_skip + 1
    end_iteration <- niter_skip + nrounds
    for (iteration in begin_iteration:end_iteration) {
        for (f in cb$pre_iter) f()
        xgb.iter.update(bst$handle, dtrain, iteration - 1, obj)
        bst_evaluation <- numeric(0)
        if (length(watchlist) > 0) 
            bst_evaluation <- xgb.iter.eval(bst$handle, watchlist, 
                iteration - 1, feval)
        xgb.attr(bst$handle, "niter") <- iteration - 1
        for (f in cb$post_iter) f()
        if (stop_condition) 
            break
    }
    for (f in cb$finalize) f(finalize = TRUE)
    bst <- xgb.Booster.complete(bst, saveraw = TRUE)
    bst$niter = end_iteration
    if (length(evaluation_log) > 0 && nrow(evaluation_log) > 
        0) {
        if (inherits(xgb_model, "xgb.Booster") && !is_update && 
            !is.null(xgb_model$evaluation_log) && isTRUE(all.equal(colnames(evaluation_log), 
            colnames(xgb_model$evaluation_log)))) {
            evaluation_log <- rbindlist(list(xgb_model$evaluation_log, 
                evaluation_log))
        }
        bst$evaluation_log <- evaluation_log
    }
    bst$call <- match.call()
    bst$params <- params
    bst$callbacks <- callbacks
    if (!is.null(colnames(dtrain))) 
        bst$feature_names <- colnames(dtrain)
    bst$nfeatures <- ncol(dtrain)
    return(bst)
}

В частности, я пытаюсь найти, где в исходном коде xgboost рассчитывает градиент. Я вижу, что объект handle определен как handle <- xgb.Booster.handle(params, append(watchlist, dtrain), xgb_model). И я нашел xgb.Booster.handle здесь: https://github.com/dmlc/xgboost/blob/master/R-package/R/xgb.Booster.R. Этот файл вызывает несколько файлов C ++, один из которых XGBoosterCreate_R, который определен здесь: https://github.com/dmlc/xgboost/blob/master/R-package/src/xgboost_R.cc.

Однако при сканировании кода C ++ мне неясно, где именно рассчитывается шаг градиента. Может кто-нибудь указать мне, где градиент определяется в исходном коде?

1 Ответ

2 голосов
/ 06 мая 2020

Существует обширная документация, см., Например, https://github.com/dmlc/xgboost/blob/master/doc/c.rst, которую я считаю проницательной.

Кроме этого, ссылки, которыми вы поделились, находятся внутри R-оболочки (если я могу назвать это как что) фактического исходного кода, исходный код начинается с

#include <dmlc/logging.h>
#include <dmlc/omp.h>
#include <xgboost/c_api.h>
#include <vector>
#include <string>
#include <utility>
#include <cstring>
#include <cstdio>
#include <sstream>
#include "./xgboost_R.h"

3-я строка указывает на каталог xgboost/, где вы найдете c_api.h, который является продвинутым программистом Интерфейс для актуальной библиотеки. Код удивительно хорошо документирован: на первый взгляд, фактический шаг итерации, вероятно, XGBoosterUpdateOneIter.

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