Younghak Jang
Younghak Jang

Reputation: 489

How to configure lasso regression to not penalize certain variables?

I'm trying to use lasso regression in python. I'm currently using lasso function in scikit-learn library.

I want my model not to penalize certain variables while training. (penalize only the rest of variables)

Below is my current code for training

rg_mdt = linear_model.LassoCV(alphas=np.array(10**np.linspace(0, -4, 100)), fit_intercept=True, normalize=True, cv=10)
rg_mdt.fit(df_mdt_rgmt.loc[df_mdt_rgmt.CLUSTER_ID == k].drop(['RESPONSE', 'CLUSTER_ID'], axis=1), df_mdt_rgmt.loc[df_mdt_rgmt.CLUSTER_ID == k, 'RESPONSE'])

df_mdt_rgmt is the data mart and I'm trying to keep the coefficient for certain columns non-zero.

glmnet in R provides 'penalty factor' parameter that let me do this, but how can I do that in python scikit-learn?

Below is the code I have in R

get.Lassomodel <- function(TB.EXP, TB.RSP){
  VT.PEN <- rep(1, ncol(TB.EXP))
  VT.PEN[which(colnames(TB.EXP) == "DC_RATE")] <- 0
  VT.PEN[which(colnames(TB.EXP) == "FR_PRICE_PW_REP")] <- 0

  VT.GRID <- 10^seq(0, -4, length=100)

  REG.MOD <- cv.glmnet(as.matrix(TB.EXP), as.matrix(TB.RSP), alpha=1, 
  lambda=VT.GRID, penalty.factor=VT.PEN, nfolds=10, intercept=TRUE)

  return(REG.MOD)
}

Upvotes: 5

Views: 3061

Answers (1)

sascha
sascha

Reputation: 33532

I'm afraid you can't. Of course it's not an theoretical issue, but just a design-decision.

My reasoning is based on the available API and while sometimes there are undocumented functions, this time i don't think there is what you need because the user-guide already posts this problem in the 1-factor-norm-of-all form alpha*||w||_1

Depending on your setting you might modify sklearn's code (a bit scared about CD-tunings) or even implement a customized-objective using scipy.optimize (although the latter might be a bit slower).

Here is some example showing the scipy.optimize approach. I simplified the problem by removing intercept's.

""" data """
import numpy as np
from sklearn import datasets
diabetes = datasets.load_diabetes()
A = diabetes.data[:150]
y = diabetes.target[:150]
alpha=0.1
weights=np.ones(A.shape[1])

""" sklearn """
from sklearn import linear_model
clf = linear_model.Lasso(alpha=alpha, fit_intercept=False)
clf.fit(A, y)

""" scipy """
from scipy.optimize import minimize
def lasso(x):  # following sklearn's definition from user-guide!
    return (1. / (2*A.shape[0])) * np.square(np.linalg.norm(A.dot(x) - y, 2)) + alpha * np.linalg.norm(weights*x, 1)

""" Test with weights = 1 """
x0 = np.zeros(A.shape[1])
res = minimize(lasso, x0, method='L-BFGS-B', options={'disp': False})
print('Equal weights')
print(lasso(clf.coef_), clf.coef_[:5])
print(lasso(res.x), res.x[:5])

""" Test scipy-based with special weights """
weights[[0, 3, 5]] = 0.0
res = minimize(lasso, x0, method='L-BFGS-B', options={'disp': False})
print('Specific weights')
print(lasso(res.x), res.x[:5])

Output:

Equal weights
12467.4614224 [-524.03922009  -75.41111354  820.0330707    40.08184085 -307.86020107]
12467.6514697 [-526.7102518   -67.42487561  825.70158417   40.04699607 -271.02909258]
Specific weights
12362.6078842 [ -6.12843589e+02  -1.51628334e+01   8.47561732e+02   9.54387812e+01
  -1.02957112e-05]

Upvotes: 6

Related Questions