본문 바로가기
머신러닝

[머신러닝][파이썬] Random Forest Classifier(분류)

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

안녕하세요. 오늘은 파이썬을 통해 RandomForestClassifier를 구현해 보도록하겠습니다.

데이터는 2017-2018년 쏘카의 고객정보와이용내역을 병합한 데이터입니다. 

1. 데이터 불러오기

1
2
3
import pandas as pd
pd.options.display.max_columns = 100
data = pd.read_csv("crm.csv")
cs

전체적인 코딩은 이전 DecisionTreeClassifier 글과 비슷합니다.

먼저 pandas를 활용해 display 옵셥을 바꿔서 더 많은 컬럼을 보여주도록한 후

csv파일을 불러왔습니다. 

2. 레이블 인코딩, Train/Test 분리, 불균형 처리

1
2
3
4
5
6
7
8
9
10
#레이블 인코딩
from sklearn.preprocessing import LabelEncoder
encoder = LabelEncoder()
encoder.fit(data.주소)
data['주소'= encoder.transform(data.주소)
encoder_1 = LabelEncoder()
encoder_1.fit(data.등급)
data['등급'= encoder_1.transform(data.등급)
 
data['성별'= data['성별'].apply(lambda x : 1 if x =='남자'  else 0)
cs

 

그리고 모델을 학습하기 전 레이블 인코딩 작업을 했습니다. 

모델은 문자에 대해서는 입력을 받지 않기 때문에 데이터의 문자형 입력값들을 숫자형을 바꿔주는 작업이 필요합니다.

문자형을 그대로 놓고 모델에 적용하면 에러가 발생하니 주의하시기 바랍니다.

 

저는 변수의 class가 많다면 LabelEncoder를 사용하고, 성별같이 0과1로 만들어야 하는 변수는 apply_lambda를 사용하여 인코딩을 했습니다. 

 

1
2
3
4
5
6
X_features = data.iloc[:, 1:-1]
y_label = data.iloc[:, -1]
 
from sklearn.model_selection import train_test_split
X_train, X_test , y_train, y_test = train_test_split(
    X_features, y_label, test_size = 0.2, random_state = 2021, stratify=y_label)
cs

랜덤포레스트는 지도학습 알고리즘이므로 독립변수와 종속변수를 나눈 후 Train/Test 데이터를 분리해야합니다. 

sklearn의 train_test-split을 활용하면 쉽게 X_train/y_train, X_test/y_test로 분리할 수 있습니다. 

test_size : test data 비율

random_state = 난수값, 재현성을 위한 작업

stratify = 데이터를 분리할 때 target의 class가 모두 포함되도록 하기 위함

 

1
2
3
4
#불균형 처리
from imblearn.over_sampling import SMOTENC
smote_nc = SMOTENC(categorical_features=[0134], random_state=0)
X_resampled, y_resampled = smote_nc.fit_resample(X_train, y_train)
cs

만약 타겟의 분포가 불균형이라면 이를 해결해주는 것이 중요합니다. 

예를 들어) 0 : 1000개 , 1 : 10개 같은 데이터 있다면 이를 그대로 모델에 학습시킨다면 0에 대해서만 과적합된 모델이 생성될 수 있습니다. 
불균형을 처리하는 방법론들은 다양하지만 저는 범주형 변수를 고려해 불균형을 해결하는 SMOTENC 기법을 사용했습니다.
categorical_features = 변수들의 인덱스값(데이터프레임의 몇번째 변수가 categorical_feature인지 지정하는 것입니다.) 단 파이썬은 숫자를 셀 때 0부터시작하기에 주의!!
또한 불균형을 처리할 때 Test data에는 적용하지 않습니다. 그 이유는 이 모델이 일반화된 모델이 되기 위해서는 새로운 정보에 대해서도 잘 분리할 수 있어야합니다. 즉 새로운 정보는 불균형이기에 모델을 Test할 때도 unbalance data가 적용되야 되는 것입니다. 

3. 랜덤포레스트 파라미터 최적화(GridSearchCV)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV
 
params_rf = {
    'n_estimators':[100200300 ,400],
    'max_depth' : [23456], 
    'min_samples_leaf' : [1020304050]
}
 
forest = RandomForestClassifier(random_state=2021, criterion='gini', n_jobs=-1)
grid_cv_rf = GridSearchCV(forest, param_grid=params_rf, cv=10, n_jobs=-1, scoring='average_precision')
grid_cv_rf=grid_cv_rf.fit(X_resampled, y_resampled)
 
print('RF - 최적 하이퍼 파라미터:\n', grid_cv_rf.best_params_)
print('RF - 최고 예측 정확도: {0:.4f}'.format(grid_cv_rf.best_score_))
cs

머신러닝 모델들은 데이터에 맞게 파라미터를 조절하여 모델을 최적화 합니다. 

RandomForestClassifier에도 다양한 파라미터들이 있습니다. 

※ 자세한 사항 : sklearn.ensemble.RandomForestClassifier — scikit-learn 1.0.2 documentation

 

sklearn.ensemble.RandomForestClassifier

Examples using sklearn.ensemble.RandomForestClassifier: Release Highlights for scikit-learn 0.24 Release Highlights for scikit-learn 0.24, Release Highlights for scikit-learn 0.22 Release Highlight...

scikit-learn.org

저는 n_estimators(나무의 수),  min_samples_leaf(리프노드에 필요한 최소 샘플 수), max_depth(나무의 깊이) 세 가지 파라미터를 GridSearchCV를 통해 최적화했습니다. 

GridSearchCV란? 지정한 파라미터의 범위내에서 모든 경우의 수를 고려해 최적의 파라미터를 뽑아내는 방법

※ 자세한 사항 : scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html

 

sklearn.model_selection.GridSearchCV

Examples using sklearn.model_selection.GridSearchCV: Release Highlights for scikit-learn 0.24 Release Highlights for scikit-learn 0.24, Feature agglomeration vs. univariate selection Feature agglom...

scikit-learn.org

마지막 두줄은 최적화된 모델의 성능과 파라미터를 뽑아내는 코드입니다. 성능과 파라미터는 11번째 줄을 보시면 cv= 10, 즉 10번의 split을 통해 교차검증을 거친 결과입니다.  또한 scoring='average_precision'로 설정했습니다. 통상적으로 scoring은 accuracy를 보는 데 정확도를 높이는 학습은  0을 많이 맞추는 방식으로 학습되는 것 같아 10번의 교차검증의 정밀도의 평균이 높아지도록 설정했습니다. 

4. 모델 학습 및 test predict

1
2
3
4
5
6
# 최적의 모델 선택
 
best_tree = grid_cv_rf.best_estimator_ # 최적의 파라미터로 모델 생성
best_tree.fit(X_resampled, y_resampled)
 
y_pred = best_tree.predict(X_test)
cs

 

GridSeachCV를 통해 최적의 파라미터를 찾았다면 최적의 파라미터로 모델을 생성합니다.

그리고 Train data를 학습시키고 X_test로 y_predict 값을 추출합니다.

 

5. 변수중요도 시각화

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import matplotlib.pyplot as plt # 변수 중요도
import seaborn as sns
%matplotlib inline
 
import matplotlib as mpl
import matplotlib.font_manager as fm
import os
if os.name == 'posix'# Mac 환경 폰트 설정
    plt.rc('font', family='AppleGothic')
elif os.name == 'nt'# Windows 환경 폰트 설정
    plt.rc('font', family='Malgun Gothic')
 
plt.rc('axes', unicode_minus=False# 마이너스 폰트 설정
 
ftr_importances_values = best_tree.feature_importances_
ftr_importances = pd.Series(ftr_importances_values, index=X_resampled.columns)
ftr_top = ftr_importances.sort_values(ascending=False)[:20]
 
plt.figure(figsize=(86))
sns.barplot(x=ftr_top, y=ftr_top.index)
plt.show()
cs

 

마지막은 변수중요도 시각화입니다.

시각화에 필요한 matplotlib.pyplot 과 seaborn 라이브러리를 불러옵니다. 

그리고 5-13번 줄은 시각화에 한글폰트를 적용할 수 있도록 하는 것입니다. 

데이터의 컬럼이 한글인 경우 이 코드를 사용하지 않는다면 컬럼명을 빈 네모로 표시됩니다.

한글 폰트 적용 전
한글 폰트 적용 후

15번에서 21번줄은 변수중요도를 시각화하는 코드이며 15번째 best_tree.feature_importances_에서 best_tree는 모델명입니다. 이는 4번의 3번째 줄에서 best_tree = grid_cv_rf.best_estimator_ 과 같이 모델을 생성했기에 best_tree라는 명을 넣어주는 것입니다.  또한 16번째 줄 ftr_importances = pd.Series(ftr_importances_values, index=X_resampled.columns) 부분도 마찬가지로 학습에 사용한 X_feature 데이터를 넣어주는 것입니다. 이에 따라 학습된 모델의 변수중요도를 알 수 있는 것입니다. 

 

보통 데이터를 탐색하기 전에 feature_engineering을 하지 않은 데이터를 랜덤포레스트에 적용해 변수중요도를 먼저 본 다음 그 변수에 대해 탐색하고 활용하는 분석사례도 많습니다. 

728x90
반응형

댓글