I'm attemtping to select a single grpah from multiple plot output with "glmnet" function (especially elastic net) in R.
I'm currently dealing with multinomial case; the response variable has 3 or more categories. So I fit the model with explanatory variable X and the response variable y with 3 types of categories. Assume that we already have alpha and lambda values from cross validation using cv.glmnet. I didn't use the argument type.multinomial = "grouped"
.
fit <- glmnet(X, y, alpha = alpha, lambda = lambda, standardize = TRUE, family = "multinomial")
plot(fit, xvar = "lambda")
fit
is then the elastic net model. I know that plot(fit, xvar = "lambda")
shows the coefficients path something like this:
However, when it is multinomial case, R generates multiple coefficient plots at the same time: for example when y has three categories, then R shows 3 coefficient plots. But I need to select only one graph out of them. I tried to find a way in google, but failed. Is there any way that I can try?
We could modify the glmnet:::plot.multnet
method for this and add a which=
option similar to that in stats:::plot.lm
.
plot.multnet <- function(x, xvar=c("norm", "lambda", "dev"), label=FALSE,
type.coef=c("coef", "2norm"), which=x$classnames, ...) {
xvar <- match.arg(xvar)
type.coef <- match.arg(type.coef)
if (!all(which %in% x$classnames)) {
warning(sprintf('`which="%s"` not in classnames, defaulting to all', which))
which <- x$classnames
}
beta <- x$beta
if (xvar == "norm") {
cnorm1 <- function(beta) {
whichnz <- nonzeroCoef(beta)
beta <- as.matrix(beta[whichnz, ])
apply(abs(beta), 2, sum)
}
norm <- apply(sapply(x$beta, cnorm1), 1, sum)
} else {
norm <- NULL
}
dfmat <- x$dfmat
if (type.coef == "coef") {
ncl <- nrow(dfmat)
clnames <- rownames(dfmat)
lapply(which, function(z) glmnet:::plotCoef(beta[[z]], norm, x$lambda, dfmat[z, ], x$dev.ratio,
label=label, xvar=xvar, ylab=paste("Coefficients: Response",
grep(z, clnames, value=TRUE))))
} else {
dfseq <- round(apply(dfmat, 2, mean), 1)
glmnet:::plotCoef(coefnorm(beta, 2), norm, x$lambda, dfseq, x$dev.ratio,
label=label, xvar=xvar, ylab="Coefficient 2Norms",
...)
}
}
fit1 <- glmnet::glmnet(x, y, family="multinomial")
plot(fit1, xvar='lambda', which='c')
I implemented a warning if a certain layer is not present, then by default all layers are plotted as before.
plot(fit1, xvar='lambda', which='foo')
# Warning message:
# In plot.multnet(fit1, xvar = "lambda", which = 1) :
# `which="foo"` not in classnames, defaulting to all
Data:
set.seed(42)
x <- matrix(rnorm(100 * 20), 100, 20)
y <- sample(letters[1:3], 100, replace=TRUE)