ICHI.PRO 쿠의블로그


06_통계분석_2 (Ridge, Lasso, Elastic Net)

  1. Ridge
  2. Lasso
  3. Elastic Net

When to use?

import pandas as pd
import numpy as np
from scipy import stats
from sklearn.datasets import load_boston
import matplotlib.pyplot as plt
import seaborn as sns
## 예제 데이터 load
boston = load_boston()
df_boston = pd.DataFrame(boston.data, columns = boston.feature_names)
df_boston['PRICE'] = boston.target
df_boston.head()
CRIM ZN INDUS CHAS NOX RM AGE DIS RAD TAX PTRATIO B LSTAT PRICE
0 0.00632 18.0 2.31 0.0 0.538 6.575 65.2 4.0900 1.0 296.0 15.3 396.90 4.98 24.0
1 0.02731 0.0 7.07 0.0 0.469 6.421 78.9 4.9671 2.0 242.0 17.8 396.90 9.14 21.6
2 0.02729 0.0 7.07 0.0 0.469 7.185 61.1 4.9671 2.0 242.0 17.8 392.83 4.03 34.7
3 0.03237 0.0 2.18 0.0 0.458 6.998 45.8 6.0622 3.0 222.0 18.7 394.63 2.94 33.4
4 0.06905 0.0 2.18 0.0 0.458 7.147 54.2 6.0622 3.0 222.0 18.7 396.90 5.33 36.2
X_data = df_boston.drop(['PRICE'], axis = 1)
y_target = df_boston['PRICE']



릿지회귀(L2규제)

from sklearn.linear_model import Ridge
from sklearn.model_selection import cross_val_score

ridge = Ridge(alpha = 10) ## alpha는 규제항에 곱해지는 것으로 alpha가 커질수록 회귀계수는 작아짐 (alpha = 회귀식의 람다)
neg_mse_scores = cross_val_score(ridge, X_data, y_target, scoring = "neg_mean_squared_error", cv = 5) 
rmse_scores = np.sqrt(-1 * neg_mse_scores)
avg_rmse = np.mean(rmse_scores)
## 규제항에 곱해지는 alpha(=람다) 값의 변화에 따른 정확도, 회귀계수의 크기 변화 측정
alphas = [0, 0.1, 1, 10, 100] ## alpha = 0일때는 규제가 없는 경우와 동일

for alpha in alphas:
  ridge = Ridge(alpha = alpha)

  neg_mse_scores = cross_val_score(ridge, X_data, y_target, scoring = "neg_mean_squared_error", cv = 5)
  avg_rmse = np.mean(np.sqrt(-1 * neg_mse_scores))
  print('alpha {0} 일 때 5 folds의 평균 RMSE: {1:.3f}'.format(alpha, avg_rmse))
alpha 0 일 때 5 folds의 평균 RMSE: 5.829
alpha 0.1 일 때 5 folds의 평균 RMSE: 5.788
alpha 1 일 때 5 folds의 평균 RMSE: 5.653
alpha 10 일 때 5 folds의 평균 RMSE: 5.518
alpha 100 일 때 5 folds의 평균 RMSE: 5.330
coeff_df = pd.DataFrame()

for pos, alpha in enumerate(alphas):
  ridge = Ridge(alpha = alpha)
  ridge.fit(X_data, y_target)

  coeff = pd.Series(data = ridge.coef_, index = X_data.columns)
  colname = 'alpha:' + str(alpha)
  coeff_df[colname] = coeff

print(coeff_df)
           alpha:0  alpha:0.1    alpha:1  alpha:10  alpha:100
CRIM     -0.108011  -0.107474  -0.104595 -0.101435  -0.102202
ZN        0.046420   0.046572   0.047443  0.049579   0.054496
INDUS     0.020559   0.015999  -0.008805 -0.042962  -0.052826
CHAS      2.686734   2.670019   2.552393  1.952021   0.638335
NOX     -17.766611 -16.684645 -10.777015 -2.371619  -0.262847
RM        3.809865   3.818233   3.854000  3.702272   2.334536
AGE       0.000692  -0.000269  -0.005415 -0.010707   0.001212
DIS      -1.475567  -1.459626  -1.372654 -1.248808  -1.153390
RAD       0.306049   0.303515   0.290142  0.279596   0.315358
TAX      -0.012335  -0.012421  -0.012912 -0.013993  -0.015856
PTRATIO  -0.952747  -0.940759  -0.876074 -0.797945  -0.829218
B         0.009312   0.009368   0.009673  0.010037   0.009393
LSTAT    -0.524758  -0.525966  -0.533343 -0.559366  -0.660764

위의 릿지회귀모델에서는 alpha가 100일 때 CV를 이용한 모델평가 정확도가 가장 높게 나왔다. 또한 규제항의 alpha가 높아지면 회귀계수의 값은 점점 더 작아짐을 확인할 수 있는데, 0이 되는 항은 하나도 없는 것에서 릿지 모델의 특징을 알 수 있다.



라쏘회귀(L1규제)

## Lasso는 Ridge회귀에서 사용했던 식 그대로에서 함수만 바꿔주면 된다.

from sklearn.linear_model import Lasso
alphas = [0, 0.1, 1, 10, 100]

for alpha in alphas:
  lasso = Lasso(alpha = alpha)

  neg_mse_scores = cross_val_score(lasso, X_data, y_target, scoring = "neg_mean_squared_error", cv = 5)
  avg_rmse = np.mean(np.sqrt(-1 * neg_mse_scores))
  print('Lasso 회귀 alpha {0} 일 때 5 folds의 평균 RMSE: {1:.3f}'.format(alpha, avg_rmse))


coeff_df = pd.DataFrame()

for pos, alpha in enumerate(alphas):
  lasso = Lasso(alpha = alpha)
  lasso.fit(X_data, y_target)

  coeff = pd.Series(data = lasso.coef_, index = X_data.columns)
  colname = 'alpha:' + str(alpha)
  coeff_df[colname] = coeff

print(coeff_df)
Lasso 회귀 alpha 0 일 때 5 folds의 평균 RMSE: 5.829
Lasso 회귀 alpha 0.1 일 때 5 folds의 평균 RMSE: 5.615
Lasso 회귀 alpha 1 일 때 5 folds의 평균 RMSE: 5.776
Lasso 회귀 alpha 10 일 때 5 folds의 평균 RMSE: 6.586
Lasso 회귀 alpha 100 일 때 5 folds의 평균 RMSE: 8.393
           alpha:0  alpha:0.1   alpha:1  alpha:10  alpha:100
CRIM     -0.108011  -0.097894 -0.063437 -0.000000  -0.000000
ZN        0.046420   0.049211  0.049165  0.026146   0.000000
INDUS     0.020559  -0.036619 -0.000000 -0.000000  -0.000000
CHAS      2.686734   0.955190  0.000000  0.000000   0.000000
NOX     -17.766611  -0.000000 -0.000000  0.000000  -0.000000
RM        3.809865   3.703202  0.949811  0.000000   0.000000
AGE       0.000692  -0.010037  0.020910  0.000000  -0.000000
DIS      -1.475567  -1.160538 -0.668790 -0.000000   0.000000
RAD       0.306049   0.274707  0.264206  0.000000  -0.000000
TAX      -0.012335  -0.014570 -0.015212 -0.009282  -0.020972
PTRATIO  -0.952747  -0.770654 -0.722966 -0.000000  -0.000000
B         0.009312   0.010249  0.008247  0.007496   0.004466
LSTAT    -0.524758  -0.568769 -0.761115 -0.564038  -0.000000

라쏘 회귀는 ALPHA가 0.1일 때 가장 좋은 성능을 보였고, ALPHA값이 증가함에 따라 다수의 회귀계수가 0이 되는 모습을 보임. 릿지 회귀는 alpha를 높여도 w가 작아질지언정 0이 되지는 않았으나, lasso는 급격하게 0을 만들어나감. 따라서 feature selection에 적합한 모델이라 볼 수 있음. 라쏘와 릿지의 비교에서, 이 boston 집값 데이터는 row 수는 충분하기 때문에 정보량을 줄이는 쪽으로 모델링해야 한다고 말할 수 있을 것 같음



엘라스틱넷

## 다 똑같다.. 그냥 함수만 계속 바꿔주면 된다

from sklearn.linear_model import ElasticNet
alphas = [0, 0.1, 1, 10, 100]

for alpha in alphas:
  elasticnet = ElasticNet(alpha = alpha)

  neg_mse_scores = cross_val_score(elasticnet, X_data, y_target, scoring = "neg_mean_squared_error", cv = 5)
  avg_rmse = np.mean(np.sqrt(-1 * neg_mse_scores))
  print('ElasticNet 회귀 alpha {0} 일 때 5 folds의 평균 RMSE: {1:.3f}'.format(alpha, avg_rmse))


coeff_df = pd.DataFrame()

for pos, alpha in enumerate(alphas):
  elasticnet = ElasticNet(alpha = alpha)
  elasticnet.fit(X_data, y_target)

  coeff = pd.Series(data = elasticnet.coef_, index = X_data.columns)
  colname = 'alpha:' + str(alpha)
  coeff_df[colname] = coeff

print(coeff_df)
ElasticNet 회귀 alpha 0 일 때 5 folds의 평균 RMSE: 5.829
ElasticNet 회귀 alpha 0.1 일 때 5 folds의 평균 RMSE: 5.478
ElasticNet 회귀 alpha 1 일 때 5 folds의 평균 RMSE: 5.522
ElasticNet 회귀 alpha 10 일 때 5 folds의 평균 RMSE: 6.472
ElasticNet 회귀 alpha 100 일 때 5 folds의 평균 RMSE: 8.312
           alpha:0  alpha:0.1   alpha:1  alpha:10  alpha:100
CRIM     -0.108011  -0.100079 -0.080371 -0.000000  -0.000000
ZN        0.046420   0.051377  0.053240  0.040935   0.000000
INDUS     0.020559  -0.045901 -0.012657 -0.000000  -0.000000
CHAS      2.686734   0.987970  0.000000  0.000000   0.000000
NOX     -17.766611  -0.059533 -0.000000  0.000000  -0.000000
RM        3.809865   3.252662  0.933936  0.000000   0.000000
AGE       0.000692  -0.007219  0.020579  0.020067  -0.000000
DIS      -1.475567  -1.181402 -0.762044 -0.000000   0.000000
RAD       0.306049   0.288726  0.301569  0.000000   0.000000
TAX      -0.012335  -0.014952 -0.016439 -0.008950  -0.021347
PTRATIO  -0.952747  -0.793502 -0.748046 -0.000000  -0.000000
B         0.009312   0.009963  0.008339  0.007436   0.010110
LSTAT    -0.524758  -0.598184 -0.758426 -0.632398  -0.000000