Fits a smooth, strictly additive model via component-wise functional
gradient boosting with penalised B-spline (P-spline) base-learners, one
per predictor column. At each of mstop boosting iterations the algorithm
selects the single base-learner that most reduces the current loss (squared
error for gaussian, binomial deviance for binomial), updates only that
component by a shrinkage-scaled Cholesky-backed ridge solve, and repeats.
The result is a smooth GAM with implicit variable selection: predictors
that are never selected retain a zero coefficient vector, and
$selection_frequency (fraction of iterations each predictor was chosen)
serves as a natural importance metric.
Usage
bgam(x, ...)
# S3 method for class 'formula'
bgam(
x,
data = NULL,
subset = NULL,
na.action = c("impute", "omit"),
weights = NULL,
...,
y = NULL
)
# Default S3 method
bgam(
x,
y,
family = c("gaussian", "binomial"),
nu = 0.1,
mstop = NULL,
autotune = TRUE,
mstop_max = 300L,
nfold = 5L,
seed.cv = NULL,
nknots = 20L,
degree = 3L,
dpen = 2L,
df_target = 4,
lambda_method = c("df", "fixed"),
lambda_fixed = NULL,
unpenalized = NULL,
intercept = TRUE,
weights = NULL,
na.action = c("impute", "omit"),
encoding = c("onehot", "means", "integer", "auto"),
encoding_spec = NULL,
n.boot = 0L,
seed = NULL,
nthreads = 1L,
...
)Arguments
- x
A numeric matrix or data frame of predictors (default method), or a model formula (formula method).
- ...
Passed to the default method from the formula method; otherwise currently unused.
- data
A data frame (formula method only).
- subset
Optional integer or logical row-subsetting vector passed to
stats::model.frame()(formula method only).- na.action
Strategy for missing values in
x."impute"(default) replaces each column'sNAs with that column's training median and stores the medians forpredict()to reuse."omit"drops rows with anyNA. Either action warns. Missing values iny, orNaN/Infanywhere inx, are always rejected. For the formula method the model frame is built withna.action = na.passand this rule is applied downstream. Whenxcarries factor / character columns,NAs in those columns are imputed on the expanded indicator scale (median of the 0/1 dummies), not on the original level; passna.action = "omit"to drop such rows if that matters.- weights
Optional strictly positive numeric weight vector of length
nrow(x). For"gaussian", weights scale the pseudo-residual sum of squares used for base-learner selection and the Cholesky prefactor. For"binomial", weights scale the IRLS working weights \(w_i^{(\text{eff})} = w_i \mu_i (1 - \mu_i)\). DefaultNULL(unweighted).- y
Response vector of length
nrow(x). Forfamily = "binomial", must be binary: 0/1 numeric,logical, or a two-levelfactor(second level = 1).- family
Response family:
"gaussian"(default, squared-error loss) or"binomial"(logistic / binomial deviance, binary response).- nu
Boosting shrinkage / learning rate. Must be in
(0, 1]. Smaller values require more iterations but produce smoother solution paths. Default0.1.- mstop
Number of boosting iterations to run. If
NULLandautotune = FALSE, defaults tomstop_max. Ifautotune = TRUE,mstopis set to the CV-selectedmstop_opt.- autotune
If
TRUE(default), selectsmstopby k-fold cross-validation over the gridseq(10, mstop_max, by = 10)using MSE (gaussian) or binomial deviance (binomial) as the criterion. A successive-halving early-stop rule terminates the grid scan once CV loss rises more than 2% of its range above the running best.- mstop_max
Maximum iterations for the CV grid (and the default when
autotune = FALSEandmstop = NULL). Reduced automatically tomax(50, 2 * n)whenn < 100. Default300L.- nfold
Number of CV folds. Default
5L.- seed.cv
Integer seed for CV fold construction. Default
NULL. Binomial CV folds are stratified by response class.- nknots
Number of interior B-spline knots per predictor. Knots are placed at equally-spaced quantiles of the predictor column. Default
20L, givingK_j = nknots + degree + 1 = 24columns per base-learner at defaults.- degree
B-spline polynomial degree (1 to 5). Default
3L(cubic B-splines).- dpen
Order of the difference penalty (1 to
degree). Default2L(second-order penalty, analogous to a thin-plate-spline roughness penalty; Eilers & Marx 1996).- df_target
Target effective degrees of freedom per base-learner, i.e.
tr(S_j(lambda_j)). Must be> 1. Default4. The ridge penaltylambda_jis calibrated per predictor viastats::uniroot.- lambda_method
"df"(default): calibratelambda_jfromdf_targetper predictor."fixed": supplylambda_jdirectly vialambda_fixed.- lambda_fixed
Numeric scalar or length-p vector of lambda values. Required when
lambda_method = "fixed"; ignored otherwise.- unpenalized
Optional character vector of predictor column names to enter as linear (unpenalised, no-spline) base-learners. Useful for known-linear covariates or binary dummies.
- intercept
If
TRUE(default), initialise the additive predictor atmean(y)(gaussian) orlogit(clamp(mean(y), 0.001, 0.999))(binomial). IfFALSE, initialise at 0.- encoding
Categorical-encoding strategy for data-frame
x(default method only): one of"onehot"(default, current behavior),"means","integer", or"auto". The default"onehot"withencoding_spec = NULLpreserves existing one-hot expansion exactly; any other mode (or a non-NULLencoding_spec) routes throughrr_encode_factors().- encoding_spec
Optional pre-built encoding recipe passed to
rr_encode_factors(). DefaultNULL.- n.boot
Number of bootstrap replicates for bagging. Default
0L(no bagging). When> 0,predict()returns the bag mean across the central fit and surviving replicates. Hyperparameters are frozen at the central-fit values; no re-autotune per replicate.- seed
Optional integer RNG seed for the bagging loop. Default
NULL.- nthreads
TBB thread count for the parallel predictor scan per boosting iteration.
0= use all available TBB threads.1L(default) = serial execution. Results are byte-identical across allnthreadsvalues.
Value
An S3 object of class "bgam", a named list with the following
key fields (full contract: 25+ fields):
coefficientsList of p accumulated (nu-scaled) beta vectors, one per predictor. Zero-vector if the predictor was never selected.
fitted.valuesFitted values on the response scale (probabilities for binomial; identical to
linear.predictorsfor gaussian). For bagged fits, this is the bag mean.linear.predictorsFitted values on the link scale.
residualsResiduals on the response scale (gaussian:
y - fitted; binomial: deviance residuals).selection_pathInteger vector of length
mstop, 1-based predictor index selected at each iteration.selection_frequencyNamed numeric vector of length p; fraction of iterations each predictor was selected. Sums to 1.
loss_pathNumeric vector of length
mstop; training loss (MSE or deviance) after each iteration.mstopInteger; iterations run (equals
mstop_optwhenautotune = TRUE).cvList with
$grid,$cv_loss,$mstop_optwhenautotune = TRUE;NULLotherwise.bootList with
$n.bootand$fitswhenn.boot > 0;NULLotherwise.base_learnersList of p per-predictor lists, each containing
$knots,$K,$degree,$dpen,$lambda,$range,$chol,$B_train.
See also: predict.bgam, print.bgam, summary.bgam, plot.bgam.
Details
Each base-learner is a cubic (or general degree-d) B-spline with
nknots interior knots placed at equally-spaced quantiles of the
predictor, penalised by a dpen-th order difference-penalty matrix
\(D^T D\) scaled by a ridge parameter \(\lambda_j\)
calibrated so the effective degrees of freedom of the base-learner equals
df_target. Near-constant predictors fall back automatically to
unpenalised linear base-learners (with a warning).
bgam() complements the rest of the roadrunner lineup: it is more
interpretable than krls() (explicit additive components, no kernel
matrix), handles non-linearity without manual basis specification unlike
ols(), and targets smooth monotonic / additive signals where ares()'s
piecewise-linear hinge functions may be less efficient. The complexity per
fit is O(n * p * K) per iteration (K ~ nknots + degree + 1), making it
practical for large-n, moderately large-p settings where krls() becomes
memory-bound.
The formula method builds a standard model frame (factors expanded via
model.matrix, formula's -1 disables the intercept initialisation),
stores $terms and $xlevels for predict(), and dispatches to the
default method. The default method takes a numeric matrix directly.
References
Buehlmann, P. and Yu, B. (2003). Boosting with the L2 loss: Regression and classification. Journal of the American Statistical Association, 98(462):324–339. doi:10.1198/016214503000125
Eilers, P. H. C. and Marx, B. D. (1996). Flexible smoothing with B-splines and penalties. Statistical Science, 11(2):89–121. doi:10.1214/ss/1038425655
Hofner, B., Mayr, A., Robinzonov, N. and Schmid, M. (2014). Model-based boosting in R: A hands-on tutorial using the R package mboost. Computational Statistics, 29(1–2):3–35. doi:10.1007/s00180-012-0382-5
Schmid, M. and Hothorn, T. (2008). Boosting additive models using component-wise P-splines. Computational Statistics and Data Analysis, 53(2):298–311. doi:10.1016/j.csda.2008.09.009
Examples
set.seed(1)
n <- 200
x <- matrix(rnorm(n * 4), n, 4)
y <- sin(x[, 1]) + 0.5 * x[, 2]^2 + rnorm(n, sd = 0.5)
# Fit with fixed mstop (fast, no CV)
fit <- bgam(x, y, mstop = 100, autotune = FALSE, nthreads = 1)
print(fit)
#> Call:
#> bgam.default(x = x, y = y, mstop = 100, autotune = FALSE, nthreads = 1)
#>
#> bgam fit: family = gaussian
#> n = 200 p (predictors) = 4
#> mstop = 100 nu = 0.1
#> nknots = 20 degree = 3 dpen = 2 df_target = 4
#>
#> Top-5 predictors by selection frequency:
#> V2 : 0.71
#> V1 : 0.28
#> V3 : 0.01
#> V4 : 0
#>
#> Residual sigma: 0.5455
predict(fit, x[1:3, ])
#> [1] -0.4533377 1.7714279 0.7107242
# Formula interface
df <- data.frame(y = y, x)
fit2 <- bgam(y ~ ., data = df, mstop = 50, autotune = FALSE)
head(fit2$selection_frequency)
#> X1 X2 X3 X4
#> 0.36 0.64 0.00 0.00