본문 바로가기
머신러닝

[변수선택법] 릿리(Ridge) 라쏘 (Lasso) 엘라스틱 넷(Elastic Net)

by 방구석 데이터사이언티스트 2022. 2. 2.
728x90
반응형

1. 릿지, 라쏘, 엘라스틱 넷이란? 

회귀모델에 규제를 가하는 방식인데요!! 규제를 통해 설명력이 좋은 변수는 남기고 좋지 않은 변수는 버리는 방식의 변수선택 개념입니다.

 

릿지: L2 규제를 사용!! -> 설명력이 낮은 변수를 0으로, 특성 무력화

라쏘: L1 규제를 사용!! -> 설명력이 낮은 변수를 0에 가깝게, 특성들의 영향력 감소

엘라스틱: 릿지 + 라쏘 적절히 조합!!

일부 특성이 중요하다면 릿지모델을!!, 특성의 중요도가 전체적으로 비슷하다면 라쏘 모델을!! 애매하면 둘을 적절히 조합해서 엘라스틱 넷을!! 사용하면 됩니다.

 

2. 릿지, 라쏘, 엘라스틱 넷 회귀모델 구현 - 데이터 확인-

 

데이터는 캐글에 있는 NBA 파이널 경기 데이터를 사용했어요!!

총 220개의 데이터이고 변수는 24개이고 각 변수들은 다음과 같습니다!!

Year :  시즌연도

Team :  팀명

Win:  승패여부 Win: 1, Loss: 0

Home :  홈어웨이여부 Home: 1, Away: 0

Game :  파이널 몇차전 경기인지 ex) 1: 1차전 , 2: 2차전

MP :  전체 경기 시간, 240을 넘어갈 경우 연장전

FG Field Goal : 성공 횟수

FGA Field Goal : 시도

FGP Field Goal : 성공률 (FGP=FG/FGA)

TP : 3점슛 성공횟수

TPA : 3점슛 시도 횟수

TPP : 3점슛 성공률 (TPP=TP/TPA)

FT : 자유투 성공횟수

FTA : 자유투 시도 횟수

FTP : 자유투 성공률 (FTP=FT/FTA)

ORB : 공격 리바운드 횟수

DRB : 수비 리바운드 횟수

TRB : 전체 리바운드 횟수(TRB=ORB+DRB)

AST : 어시스트 횟수

STL : 스틸 횟수

BLK : 블록 횟수

TOV : 턴오버 횟수

PF : 상대팀의 퍼스널 파울 횟수

PTS : 전체 득점

 

3. 릿지, 라쏘, 엘라스틱 넷 회귀모델 구현 - 변수간의 산점도 -

산점도를 통해 변수들간의 상관관계랑 선형관계도 보았는데요 PTS랑 FG가 눈에 띄는 선형관계를 가지네요!!

필드골이 많으면 전체득점도 많다는 일반적인 상식으로 볼 수 있겠죠?

 

4. 릿지, 라쏘, 엘라스틱 넷 회귀모델 구현 - 모델 생성 -

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from sklearn.model_selection import cross_val_score
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.linear_model import Ridge, Lasso, ElasticNet
 
# alphas list 값을 반복하면서 alpha에 따른 평균 rmse를 구함
# cross_val_score를 이용해 5 폴드의 평균 RMSE를 계산
# alpha값에 따른 회귀 모델의 폴드 평균 RMSE를 출력하고 회귀계수 값들을 DataFrame으로 반환
y_target = team['PTS']
X_data = team.drop(['PTS','Team','Year','Game','Win','Home'], axis=1, inplace=False)
 
def get_linear_reg_eval(model_name, params=None, X_data_n=None, y_target_n=None, verbose=True):
    coeff_df = pd.DataFrame()
    if verbose : print('######', model_name, '######')
    for param in params:
        if model_name =='Ridge': model = Ridge(alpha=param)
        elif model_name =='Lasso' : model = Lasso(alpha=param)
        elif model_name =='ElasticNet': model = ElasticNet(alpha=param, l1_ratio=0.7)
        neg_mse_scores = cross_val_score(model, X_data_n, y_target_n,
                                        scoring='neg_mean_squared_error', cv = 5)
        avg_rmse = np.mean(np.sqrt(-1*neg_mse_scores))
        print('alpha {0}일 때 5 폴드 세트의 평균 RMSE: {1:.3f}'.format(param, avg_rmse))
        model.fit(X_data, y_target)
        
        coeff = pd.Series(data=model.coef_, index=X_data.columns )
        colname='alpha:'+str(param)
        coeff_df[colname] = coeff
    return coeff_df
 
alphas = [0.070.10.513]
cs

8번과 9번에서 독립변수와 종속변수를 구분했습니다. 그리고 데이터를 5개의 split으로 나누어 교차검증을 할 것이기 때문에 Train/test를 따로 분리해두지 않습니다. 11번부터는 alphas에 따른 릿지, 라쏘, 엘라스틱 넷 모델을 구축하고 5 fold의 평균 rmse를 뽑아내는 함수 입니다. 15번부터 17번까지 조건문에 따라 릿지, 라쏘, 엘라스틱 넷이 적용되는 것을 알 수 있습니다. alpha=param 는 29번에서 정의한 alphas가 들어갑니다. 18번에서 21번은 교차검증을 하고 평균 RMSE를 뽑아내는 코드입니다. 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 릿지 회귀
coeff_ridge_df = get_linear_reg_eval('Ridge', params=alphas, X_data_n=X_data, y_target_n=y_target)
 
### 라쏘회귀
### W의 절댓값에 페널티를 부여하는 L1규제를 선형 회귀에 적용한 것
### 불필용한 회귀 계수를 급격하게 감소시켜 0으로 만들고 제거한다
coeff_lasso_df = get_linear_reg_eval('Lasso', params=alphas, X_data_n=X_data, y_target_n=y_target)
 
### 엘라스틱넷 회귀는 L2규제와 L1 규제를 결합한 회귀 
 
 
# 엘라스틱넷에 사용될 alpha 파라미터의 값들을 정의하고 get_linear_reg_eval() 함수 호출
# ㅣ1_ratio는 0.7로 고정
coeff_elastic_df = get_linear_reg_eval('ElasticNet', params=alphas,
                                      X_data_n=X_data, y_target_n=y_target)
cs

위에서 정의한 함수를 다음과 같이 매개변수를 지정해서 모델을 생성하고 결과를 추출합니다. 

 

5. 회귀계수 시각화

마지막으로 alpaha 값에 따른 릿지, 라쏘, 엘라스틱 넷 모델의 회귀계수를 시각화하는 코드입니다. 

- 릿지 -

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 반환된 coeff_ridge_df를 첫 번째 칼럼순으로 내림차순 정렬해 회귀계수 DataFrame 출력
sort_column = 'alpha:'+str(alphas[0])
coeff_ridge_df.sort_values(by=sort_column, ascending=False)
 
# 각 alpha에 따른 회귀 계수 값을 시각화하기 위해 5개의 열로 된 맷플롯립 축 생성
fig, axs = plt.subplots(figsize=(186), nrows=1, ncols=5)
# 각 alpha에 따른 회귀 계수 값을 데이터로 저장하기 위한 DataFrame 생성
coeff_df = pd.DataFrame()
 
# alphas 리스트 값을 차례로 입력해 회귀 계수 값 시각화 및 데이터 저장. 
for pos, alpha in enumerate(alphas) :
    ridge = Ridge(alpha = alpha)
    ridge.fit(X_data, y_target)
    # alpha에 따른 피처별로 회귀 계수를 Series로 변환하고 이를 DataFrame의 칼럼으로 추가
    coeff = pd.Series(data=ridge.coef_, index=X_data.columns)
    colname='alpha:'+str(alpha)
    coeff_df[colname] = coeff
    # 막대 그래프로 각 alpha 값에서의 회귀 계수를 시각화. 회귀 계수값이 높은  순으로 표현 
    coeff = coeff.sort_values(ascending=False)
    axs[pos].set_title(colname)
    axs[pos].set_xlim(-36)
    sns.barplot(x=coeff.values, y=coeff.index, ax=axs[pos])
    
plt.show()
cs

-라쏘-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 반환된 coeff_lass_df를 첫 번째 칼럼순으로 내림차순 정렬해 회귀계수 DataFrame 출력
sort_column = 'alpha:'+str(alphas[0])
coeff_lasso_df.sort_values(by=sort_column, ascending=False)
 
# 각 alpha에 따른 회귀 계수 값을 시각화하기 위해 5개의 열로 된 맷플롯립 축 생성
fig, axs = plt.subplots(figsize=(186), nrows=1, ncols=5)
# 각 alpha에 따른 회귀 계수 값을 데이터로 저장하기 위한 DataFrame 생성
coeff_df = pd.DataFrame()
 
# alphas 리스트 값을 차례로 입력해 회귀 계수 값 시각화 및 데이터 저장. 
for pos, alpha in enumerate(alphas) :
    lasso = Lasso(alpha = alpha)
    lasso.fit(X_data, y_target)
    # alpha에 따른 피처별로 회귀 계수를 Series로 변환하고 이를 DataFrame의 칼럼으로 추가
    coeff = pd.Series(data=lasso.coef_, index=X_data.columns)
    colname='alpha:'+str(alpha)
    coeff_df[colname] = coeff
    # 막대 그래프로 각 alpha 값에서의 회귀 계수를 시각화. 회귀 계수값이 높은  순으로 표현 
    coeff = coeff.sort_values(ascending=False)
    axs[pos].set_title(colname)
    axs[pos].set_xlim(-36)
    sns.barplot(x=coeff.values, y=coeff.index, ax=axs[pos])
    
plt.show()
cs

-엘라스틱 넷-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 반환된 coeff_elastic_df를 첫 번째 칼럼순으로 내림차순 정렬해 회귀계수 DataFrame 출력
sort_column = 'alpha:'+str(alphas[0])
coeff_elastic_df.sort_values(by=sort_column, ascending=False)
 
# 각 alpha에 따른 회귀 계수 값을 시각화하기 위해 5개의 열로 된 맷플롯립 축 생성
fig, axs = plt.subplots(figsize=(186), nrows=1, ncols=5)
# 각 alpha에 따른 회귀 계수 값을 데이터로 저장하기 위한 DataFrame 생성
coeff_df = pd.DataFrame()
 
# alphas 리스트 값을 차례로 입력해 회귀 계수 값 시각화 및 데이터 저장. 
for pos, alpha in enumerate(alphas) :
    elastic = ElasticNet(alpha = alpha)
    elastic.fit(X_data, y_target)
    # alpha에 따른 피처별로 회귀 계수를 Series로 변환하고 이를 DataFrame의 칼럼으로 추가
    coeff = pd.Series(data=elastic.coef_, index=X_data.columns)
    colname='alpha:'+str(alpha)
    coeff_df[colname] = coeff
    # 막대 그래프로 각 alpha 값에서의 회귀 계수를 시각화. 회귀 계수값이 높은  순으로 표현 
    coeff = coeff.sort_values(ascending=False)
    axs[pos].set_title(colname)
    axs[pos].set_xlim(-36)
    sns.barplot(x=coeff.values, y=coeff.index, ax=axs[pos])
    
plt.show()
 
cs

728x90
반응형

댓글