## Class to describe an elastic net model
ADMM_Enet = setRefClass("ADMM_Enet",
fields = list(alpha = "numeric"),
contains = "ADMM_Lasso"
)
## Class to store fitting results of elastic net model
ADMM_Enet_fit = setRefClass("ADMM_Enet_fit", contains = "ADMM_Lasso_fit")
##### Member functions of ADMM_Enet #####
## Initialize fields including default values
ADMM_Enet$methods(
initialize = function(...)
{
.self$alpha = 1
callSuper(...)
}
)
## Print off ADMM_Enet object
ADMM_Enet$methods(
show = function()
{
cat("ADMM Elastic Net model\n\n")
show_common()
}
)
## Set up penalty parameters
ADMM_Enet$methods(
penalty = function(lambda = NULL, nlambda = 100, lambda_min_ratio,
alpha = 1, ...)
{
if(alpha < 0 | alpha > 1)
stop("alpha must be within [0,1]")
.self$alpha = as.numeric(alpha)
callSuper(lambda, nlambda, lambda_min_ratio, ...)
invisible(.self)
}
)
## Fit model and conduct the computing
ADMM_Enet$methods(
fit = function(...)
{
res = .Call("admm_enet", .self$x, .self$y, .self$lambda,
.self$nlambda, .self$lambda_min_ratio,
.self$standardize, .self$intercept,
.self$alpha,
list(maxit = .self$maxit,
eps_abs = .self$eps_abs,
eps_rel = .self$eps_rel,
rho = .self$rho),
PACKAGE = "ADMM")
do.call(ADMM_Enet_fit, res)
}
)
##### Member functions of ADMM_Lasso_fit #####
## Print off ADMM_Lasso_fit object
ADMM_Enet_fit$methods(
show = function()
{
cat("ADMM Elastic Net fitting result\n\n")
show_common()
}
)
#' Fitting An Elastic Net Model Using ADMM Algorithm
#'
#' @description Elastic Net is an extension to the Lasso model. It seeks a
#' coefficient vector \eqn{\beta} that minimizes
#' \deqn{\frac{1}{2n}\Vert y-X\beta\Vert_2^2+\lambda\alpha\Vert\beta\Vert_1+\frac{\lambda(1-\alpha)}{2}\Vert\beta\Vert_2^2}{
#' 1/(2n) * ||y - X * \beta||_2^2 + \lambda * \alpha * ||\beta||_1 + 0.5 * \lambda * (1 - \alpha) * ||\beta|_2^2|}
#'
#' Here \eqn{n} is the sample size, \eqn{\lambda} is the regularization
#' parameter for penalty term, and \eqn{\alpha} is the proportion of L1 norm
#' in the penalty part.
#'
#' This function will not directly conduct the computation,
#' but rather returns an object of class "\code{ADMM_Enet}" that contains
#' several memeber functions to actually constructs and fits the model.
#'
#' Member functions that are callable from this object are listed below:
#'
#' \tabular{ll}{
#' \code{$penalty()} \tab Specify the penalty parameter. See section
#' \strong{Setting Penalty Parameter} for details.\cr
#' \code{$opts()} \tab Setting additional options. See section
#' \strong{Additional Options} for details.\cr
#' \code{$fit()} \tab Fit the model and do the actual computation.
#' See section \strong{Model Fitting} for details.
#' }
#'
#' @param x The data matrix
#' @param y The response vector
#' @param intercept Whether to fit an intercept in the model. Default is \code{TRUE}.
#' @param standardize Whether to standardize the explanatory variables before
#' fitting the model. Default is \code{TRUE}. Fitted coefficients
#' are always returned on the original scale.
#'
#' @section Setting Penalty Parameter:
#' The penalty parameters \eqn{\lambda} and \eqn{\alpha} can be set through
#' the member function \code{$penalty()}, with the usage and parameters given below:
#'
#' \preformatted{ model$penalty(lambda = NULL, nlambda = 100, lambda_min_ratio,
#' alpha = 1, ...)
#' }
#'
#' \describe{
#' \item{\code{lambda}}{A user provided sequence of \eqn{\lambda}. If set to
#' \code{NULL}, the program will calculate its own sequence
#' according to \code{nlambda} and \code{lambda_min_ratio},
#' which starts from \eqn{\lambda_0} (with this
#' \eqn{\lambda} all coefficients will be zero) and ends at
#' \code{lambda0 * lambda_min_ratio}, containing
#' \code{nlambda} values equally spaced in the log scale.
#' It is recommended to set this parameter to be \code{NULL}
#' (the default).}
#' \item{\code{nlambda}}{Number of values in the \eqn{\lambda} sequence. Only used
#' when the program calculates its own \eqn{\lambda}
#' (by setting \code{lambda = NULL}).}
#' \item{\code{lambda_min_ratio}}{Smallest value in the \eqn{\lambda} sequence
#' as a fraction of \eqn{\lambda_0}. See
#' the explanation of the \code{lambda}
#' argument. This parameter is only used when
#' the program calculates its own \eqn{\lambda}
#' (by setting \code{lambda = NULL}). The default
#' value is the same as \pkg{glmnet}: 0.0001 if
#' \code{nrow(x) >= ncol(x)} and 0.01 otherwise.}
#' \item{\code{alpha}}{Parameter to control the proportion of L1 norm in the
#' penalty term. \code{alpha = 1} corresponds to Lasso and
#' \code{alpha = 2} is equivalent to Ridge Regression.}
#' }
#'
#' This member function will implicitly return the "\code{ADMM_Enet}" object itself.
#'
#' @section Additional Options:
#' Additional options related to ADMM algorithm can be set through the
#' \code{$opts()} member function of an "\code{ADMM_Lasso}" object. The usage of
#' this method is
#'
#' \preformatted{ model$opts(maxit = 10000, eps_abs = 1e-5, eps_rel = 1e-5,
#' rho = NULL)
#' }
#'
#' Here \code{model} is the object returned by \code{admm_enet()}.
#' Explanation of the arguments is given below:
#'
#' \describe{
#' \item{\code{maxit}}{Maximum number of iterations.}
#' \item{\code{eps_abs}}{Absolute tolerance parameter.}
#' \item{\code{eps_rel}}{Relative tolerance parameter.}
#' \item{\code{rho}}{ADMM step size parameter. If set to \code{NULL}, the program
#' will compute a default one.}
#' }
#'
#' This member function will implicitly return the "\code{ADMM_Enet}" object itself.
#'
#' @section Model Fitting:
#' Model will be fit after calling the \code{$fit()} member function. This is no
#' argument that needs to be set. The function will return an object of class
#' "\code{ADMM_Enet_fit}", which contains the following fields:
#'
#' \describe{
#' \item{\code{lambda}}{The sequence of \eqn{\lambda} to build the solution path.}
#' \item{\code{beta}}{A sparse matrix containing the estimated coefficient vectors,
#' each column for one \eqn{\lambda}. Intercepts are in the
#' first row.}
#' \item{\code{niter}}{Number of ADMM iterations.}
#' }
#'
#' Class "\code{ADMM_Enet_fit}" also contains a \code{$plot()} member function,
#' which plots the coefficient paths with the sequence of \eqn{\lambda}.
#' See the examples below.
#'
#' @examples set.seed(123)
#' n = 100
#' p = 20
#' b = runif(p)
#' x = matrix(rnorm(n * p, mean = 1.2, sd = 2), n, p)
#' y = 5 + c(x %*% b) + rnorm(n)
#'
#' ## Directly fit the model
#' admm_enet(x, y)$penalty(alpha = 0.5)$fit()
#'
#' ## Or, if you want to have more customization:
#' model = admm_enet(x, y)
#' print(model)
#'
#' ## Specify the lambda sequence and the alpha parameter
#' model$penalty(nlambda = 20, lambda_min_ratio = 0.01, alpha = 0.5)
#'
#' ## Lower down precision for faster computation
#' model$opts(maxit = 100, eps_rel = 0.001)
#'
#' ## Inspect the updated model setting
#' print(model)
#'
#' ## Fit the model and do the actual computation
#' res = model$fit()
#' res$beta
#'
#' ## Create a solution path plot
#' res$plot()
#'
#' @author Yixuan Qiu <\url{http://statr.me}>
#' @export
admm_enet = function(x, y, intercept = TRUE, standardize = TRUE, ...)
{
ADMM_Enet(x, y, intercept, standardize, ...)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.