oem 2.1.0
Bug fixes
- The default
lambda sequence now starts at the smallest
value at which every penalized coefficient is zero. It accounts for
penalty.factor, group.weights,
alpha, unpenalized variables, and the intercept (#8).
Previously the largest value was
max(abs(crossprod(x, y))) / n for every penalty, so a path
could begin with several fits with all coefficients zero, or with some
coefficients already nonzero.
- Logistic regression with a sparse
x returned wrong
intercepts with standardize = TRUE and wrong coefficients
with standardize = FALSE.
- Logistic regression with
standardize = FALSE could use
uninitialized column scales.
- Models with at least as many variables as observations now fit
correctly for a sparse
x, for logistic regression, and for
big.oem() with an intercept or standardization. These cases
previously returned wrong values or crashed R.
big.oem() with a group penalty and an intercept left
the last variable out of its group, so its coefficient was always
zero.
- The ridge part of
elastic.net and of the other
.net penalties shrank unpenalized coefficients, including
the intercept. For the elementwise penalties, the ridge part is now
multiplied by penalty.factor, as in glmnet,
and unpenalized coefficients are not shrunk by any penalty.
- C++ code no longer calls
Rf_error(); errors are raised
with Rcpp exception handling (#25).
- For logistic regression with
hessian.type = "full", the
lower bound on the working weights was applied to only one
observation.
Changes in results
- With
standardize = TRUE, every solver now scales each
column by its standard deviation, computed with denominator n, as in
glmnet. Fits with a sparse x, logistic
regression, big.oem(), and xval.oem()
previously used the uncentered root mean square with denominator n - 1,
so their results with standardize = TRUE change.
- For Gaussian models, the ridge part of the
.net
penalties is divided by the standard deviation of y (its
root mean square when intercept = FALSE), as in
glmnet. This was already the case for a dense
x with an intercept; it now holds for every solver except
oem.xtx(), which does not see y.
New features
- The OEM iterations are now accelerated by default. The new
accelerate argument of oem(),
cv.oem(), xval.oem(), big.oem(),
and oem.xtx() selects FISTA with adaptive restarting
("fista", the default except in oem.xtx()),
SQUAREM ("squarem"), or plain OEM ("none" or
FALSE). For the nonconvex penalties, an accelerated step is
accepted only if it does not increase the objective. On correlated
designs, FISTA reduced computation time along the path by a factor of 4
to 10 and fitted the path to the requested tolerance in cases where
plain OEM stopped at maxit before converging.
Changes in defaults
accelerate = "fista" is the default in
oem(), cv.oem(), xval.oem(), and
big.oem(), so their results change slightly. Use
accelerate = "none" to reproduce the plain OEM iterations
of previous versions. oem.xtx(), the low-level interface
for precomputed crossprod(x) and
crossprod(x, y), keeps plain iterations by default
(accelerate = "none").
- The default
maxit is now 5000 instead of 500. With 500
iterations, plain OEM often stopped before convergence for correlated
variables, without a warning. Fits that converge sooner stop sooner, so
the higher limit costs nothing for them.
- Fits with a sparse
x, logistic regression,
big.oem(), and xval.oem() now center the
columns implicitly and rescale the intercept column. When the columns
have nonzero means, this reduces the number of OEM iterations along the
path by about an order of magnitude.
Other changes
- Sparse matrices are mapped with
Eigen::Map<Eigen::SparseMatrix>, so the package
builds with Eigen 5 (#26, from Dirk Eddelbuettel).
- Added a testthat suite, including comparisons with
glmnet.
src/Makevars assigned PKG_CXXFLAGS twice,
so -DNDEBUG was dropped and Eigen’s debugging assertions
were compiled in. It is now set once.