Poisson deviance (xgboost vs gbm vs regression) I would like to know which is the deviance expression in poisson regression using by xgboost tool (extreme gradient boosting).
According to source code, the evaluation function is:
struct EvalPoissonNegLogLik : public EvalEWiseBase {

const char *Name() const override {

return "poisson-nloglik";

}

inline bst_float EvalRow(bst_float y, bst_float py) const {

const bst_float eps = 1e-16f;

if (py < eps) py = eps;

return common::LogGamma(y + 1.0f) + py - std::log(py) * y;

}

}

So deviance (in R) should be something like:
poisson_deviance <- function(y, py, eps) {

mean(LogGamma(y + 1.0f) + pmax(py, eps) - log(pmax(py, eps)) * y);

}

I have two questions here:
1) How translate LogGamma to R?. I found several links googling 'loggamma' and seems each language understand differents expressions for this term.
2) What to do with exposures? I know we need to set to xgbMatrix using:
setinfo(xgbMatrix, "base_margin", log(exposure))

But in the code of EvalPoissonNegLogLik I never saw the offset again, so what I deducted is that the only we need is to add the log(exposure) to predictiors:
poisson_deviance <- function(y, py, exposure, eps) {

mean(LogGamma(y + 1.0f) + pmax(py + log(exposure), eps) - log(pmax(py + 

log(exposure), eps)) * y);

}

The deviance formula used by gradient boosting gbm R package for poisson regression is:
poisson_deviance <- function(y, py) {mean(y*py - exp(py))}

(capped py at eps too)
As you can see in the last page of this document:
Are gbm and xgboost using the same error for poisson regression?
This expression of deviance seems different that what is used in xgboost.
At last, the deviance formula in poisson regression according to B.5.3 in
here should be:
2 * mean(y * log(y / py) - (y - py))

that is other different formula.
I would appreciate any help to understand why both gbm and xgboost use other deviance formulation.
 A: It is not well-documented, but I have examined the source code for xgboost and I have determined the following for the count:poisson objective: 


*

*It uses the Poisson likelihood with a log link.

*The base_margin parameter is on the linear scale, not the response scale. As the boosting rounds proceed, new trees are also added on the linear scale.

*The xgboost Poisson negative log likelihood formula is correct, but it's a little different from the Poisson deviance. However the negative log likelihood and deviance are very close and asymptotically equivalent up to a factor of 2.

*Setting base_margin to log(exposure) is equivalent to including a log(exposure) offset term.


A bit more detail on these points:
LogGamma is the logarithm of the gamma function, which is a continuous extension of the factorial. Specifically, $\Gamma(n) = (n-1)!$ for integer $n$. Thus, LogGamma(y + 1) = factorial(y). The LogGamma term represents the $\log(y!)$ term in the full Poisson log-likelihood. (This term is normally omitted from the log-likelihood expression, since it does not affect the optimization.)
According to Stirling's approximation, $\log(y!) \approx y\log(y) - y$. Replacing LogGamma with this approximation, and substituting py=exp(p) (i.e. replacing the linear predictor with the mean via log link) yields y * log(y / py) - (y - py). This is almost the standard Poisson deviance, except it is missing the factor of 2. 
The formula you found for GBM is not the standard Poisson deviance, although it is the same up to an additive (y-dependent) constant. Confusingly, the py in your GBM formula is actually the linear scale prediction, not the response scale, whereas in the other formulas py is the response, the predicted mean of y.
You do not need to add log(exposure) to the objective formula. All you need to do is set base_margin=log(exposure). This ensures that the first sum term in the boosting series is log(exposure). Subsequent boosting rounds add more terms but the initial offset is never removed or changed.
