This is mostly a case of carefully working out the math. I'll handle the two predictor + intercept case, it should be clear how to generalize it.
The standardized elastic net model results in the following relationship:
$$\frac{y - \mu(y)}{\sigma(y)} = \beta_1 \frac{x_1 - \mu(x_1)}{\sigma(x_1)} + \beta_2 \frac{x_1 - \mu(x_1)}{\sigma(x_1)}$$
If you very carefully move terms around until only $y$ is on the left hand side, you'll get
$$ y = \frac{\beta_1 \sigma(y)}{\sigma(x_1)} x_1 + \frac{\beta_2 \sigma(y)}{\sigma(x_2)} x_2- \left( \frac{\beta_1 \mu(x_1)}{\sigma(x_1)} + \frac{\beta_2 \mu(x_2)}{\sigma(x_2)} \right) \sigma(y) + \mu(y) $$
which gives the relationship between the standardized and unstandardized coefficients.
Here's a quick demonstration you can test this with
X <- matrix(runif(100, 0, 1), ncol=2)
y <- 1 -2*X[,1] + X[,2]
Xst <- scale(X)
yst <- scale(y)
enet <- glmnet(X, y, lambda=0)
enetst <- glmnet(Xst, yst, lambda=0)
coef <- coefficients(enetst)
# Un-standardized betas
coef[2]*sd(y)/sd(X[,1]) # = -2
coef[3]*sd(y)/sd(X[,2]) # = 1
# Unstandardized intercept (= 1)
-(coef[2]*mean(X[,1])/sd(X[,1]) + coef[3]*mean(X[,2])/sd(X[,2]))*sd(y) + mean(y)
This smells incorrect, you probably wanted:
fit <- cv.glmnet(model, y, k=k)
coef(fit, "lambda.min")
which will return the coefficients using the internal fit from the cross validation.
Unless ridge_model
has the same predictors, weights, mixing parameter, etc, plugging in a penalty parameter from one model into another seems odd; but if that were the same, ridge_model
would be the same as fit$glmnet.fit
above and redundant.
Best Answer
If you call
the lasso is fit for a grid of 100 values of the regularization parameter lambda. If you call the predict function for a value of lambda that is not a grid point itself, the coefficients are extrapolated.
If you call
the lasso is fit only for a lambda value of 3, and the exact coefficients for this fit are returned. You can make the predict function refit the model using the given lambda value and return exact coefficients by adding the argument
exact=TRUE
.