Py) ML - 모델 평가(Drop Column Importance)

Py) ML - 모델 평가(Drop Column Importance)

지도학습 모델의 독립변수 중요도를 확인하기 위해 사용하는 Drop Column Importance에 대해 알아본다.


예제 파일: car_bmw3.csv

개요

지도학습 모델을 평가할 때 종속변수를 기반으로 해당 모델의 전반적인 성능을 비교하는 것이 일반적이다. 그리고 더 나아가서 입력된 독립변수의 중요도가 어떠한지 확인하는 작업을 하기도 한다.
모델평가(분류모델) 게시물 확인하기
모델평가(회귀모델) 게시물 확인하기

모델을 만든다고 해서 최종적으로 모든 독립변수를 사용하는 것은 아니다. 어떤 독립변수는 해석하기가 난해할 수 있고, 어떤 독립변수는 (가공 또는 확보)비용이 많이 들 수 있고, 어떤 독립변수는 영향력이나 중요도가 상대적으로 낮아 굳이 필요가 없을 수도 있기에 여러 판단기준에 따라 불필요 하다고 판단되는 독립변수를 모델에서 제외하기도 한다.

이는 모델의 경량화나 정비를 위해 실시하는 특성 공학(Feature Engineering)과 매우 관련이 깊으며 보다 나은 모델을 확보하기 위해 독립변수의 중요도를 아는 것은 중요하다. 그 중요도를 파악하기 위한 방법 중 지도학습 모델에 공통적으로 사용할 수 있는 방법은 대표적으로 두 가지가 있으며 이는 다음과 같다.

  1. Permutation Importance
  2. Drop Column Importance

이 게시글에서는 Drop Column Importance에 대해 다룬다.

장점

  1. 모델에 종속되지 않음
  2. 쉬운 결과 해석

모델에 종속되지 않는 것은 모델의 독립변수별 중요도 평가 방법을 지도학습의 어떠한 모델에도 사용할 수 있다는 것이다. 예를 들어 랜덤포레스트(random forest)의 경우 MDI(Mean Decrease in Impurity)가 있긴 하지만 이는 랜덤포레스트(또는 트리모델)한정으로 사용하는 기법이다. 그래서 이런 자체적인 독립변수 중요도 평가 방법이 존재하지 않는 모델의 경우 Drop Column Importance를 사용하는 것이 좋은 선택이 될 수 있다. 그리고 변수 중요도를 파악하는 과정에서 각 독립변수를 하나씩 제거한 다음에 그 결과를 확인하기 때문에 상대적으로 Permutation Importance보다 그 원리 이해와 해석이 상대적으로 쉽다고 할 수 있다.

단점

기준 평가지표 확인을 위해 모든 독립변수를 사용해서 완전 모형(full model)을 학습하게 된다. 그리고 비교를 위해 각 독립변수가 하나씩 제거된 축소 모형(reduced model)도 독립변수 개수만큼 학습해야 하는데 여기서 연산 비용이 크게 들어간다. 물론 각 모델 학습이 수 분 이내로 끝나면 크게 신경쓰는 내용이 아니겠으나, 모델 학습에 시간단위로 시간소요가 일어난다면 차라리 Permutation Importance를 고려하는 것이 나을 수 있다.

실습

먼저 데이터와 모델을 준비하자. 데이터 “car_bmw3.csv”는 본 게시물 상단 링크를 통해 다운로드 하도록 하자.

1
2
3
4
5
6
7
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error

df = pd.read_csv("car_bmw3.csv")
df.head(2)
year price transmission mileage fuelType tax mpg engineSize
0 2017 16500 Manual 16570 Diesel 125 58.9 2.0
1 2017 14250 Automatic 55594 Other 135 148.7 2.0

명목형 변수를 가변수(dummy variable)로 바꾸고 종속변수로 사용할 “price” 변수를 첫 번째로 옮겨보자.

1
2
3
4
5
6
df_dum = pd.get_dummies(df, columns = ["transmission", "fuelType"], dtype = "int")
df_dum = df_dum.set_index("price").reset_index()
print(df_dum.shape)
## (2443, 13)

df_dum.iloc[:3, :8]
price year mileage tax mpg engineSize transmission_Automatic transmission_Manual
0 16500 2017 16570 125 58.9 2.0 0 1
1 14250 2017 55594 135 148.7 2.0 1 0
2 16000 2017 45456 30 64.2 2.0 1 0

데이터세트를 분리하고 모델을 생성하고 RMSE를 계산한 결과 RMSE가 3577.4인 것을 확인할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
df_train, df_test = train_test_split(df_dum, train_size = 0.7, random_state = 123)
len(df_train), len(df_test)
## (1710, 733)

model_lr = LinearRegression()
model_lr.fit(X = df_train.drop(columns = "price"),
y = df_train["price"])
pred = model_lr.predict(df_test.drop(columns = "price"))
rmse_full = mean_squared_error(y_true = df_test["price"], y_pred = pred) ** 0.5
round(rmse_full, 1)
## 3577.4

모델과 데이터가 준비되었으니 이제 각 독립변수별 중요도를 계산해보자.

첫 번째 종속변수를 제외하고 독립변수를 하나씩 제외한 데이터를 기반으로 RMSE 계산 결과를 “ls_rmse_sub” 객체에 저장한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
ls_rmse_sub = []
for n_col in df_train.columns[1:]:
model_lr_sub = LinearRegression()
model_lr_sub.fit(X = df_train.drop(columns = ["price", n_col]),
y = df_train["price"])
pred_sub = model_lr_sub.predict(df_test.drop(columns = ["price", n_col]))
rmse_sub = mean_squared_error(y_true = df_test["price"], y_pred = pred_sub) ** 0.5
ls_rmse_sub = ls_rmse_sub + [rmse_sub]

ls_rmse_sub
## [4420.0643569864,
## 3855.385305405627,
## 3575.2888621007965,
## 4035.5078971868734,
## 3650.8477408854715,
## 3577.372909538143,
## 3577.3729095381286,
## 3577.3729095381514,
## 3577.372909538166,
## 3577.3729095381796,
## 3577.3729095381523,
## 3577.372909538163]

이제 각 중요도를 보기 좋게 정리하면 다음과 같다.

1
2
3
4
5
df_perf = pd.DataFrame(dict(col_name = df_train.columns[1:],
rmse = ls_rmse_sub))
df_perf["diff"] = df_perf["rmse"] - rmse_full
df_perf["diff_nor"] = (df_perf["diff"] - df_perf["diff"].min()) / (df_perf["diff"].max() - df_perf["diff"].min())
df_perf.style.bar(color = "#FFA07A", subset = "diff_nor", align = 0)
  col_name rmse diff diff_nor
0 year 4420.064357 842.691447 1.000000
1 mileage 3855.385305 278.012396 0.331563
2 tax 3575.288862 -2.084047 0.000000
3 mpg 4035.507897 458.134988 0.544783
4 engineSize 3650.847741 73.474831 0.089443
5 transmission_Automatic 3577.372910 -0.000000 0.002467
6 transmission_Manual 3577.372910 -0.000000 0.002467
7 transmission_Semi-Auto 3577.372910 -0.000000 0.002467
8 fuelType_Diesel 3577.372910 0.000000 0.002467
9 fuelType_Hybrid 3577.372910 0.000000 0.002467
10 fuelType_Other 3577.372910 -0.000000 0.002467
11 fuelType_Petrol 3577.372910 0.000000 0.002467

여기서 “year” 변수의 영향도가 가장 큰 것을 알 수 있다.

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×