areum

[Machine Learning] Random Forest (랜덤포레스트) 본문

Programming/Machine Learning

[Machine Learning] Random Forest (랜덤포레스트)

armmy 2022. 11. 30. 16:20
728x90
Random Forest

1. 관련 라이브러리 import 

import pandas as pd
from pandas import DataFrame
import numpy as np
from time import time
import zipfile  #zip파일 해제

# 경고 무시
import warnings
warnings.filterwarnings(action='ignore')

2. zip 파일 해제 & csv파일 불러오기

  •  encoding 사용하여 한글 깨짐 방지
img=zipfile.ZipFile('zip파일 경로/ 이름')
img.extractall('저장할 경로/ 저장할 이름', pwd=b'비밀번호')
img.close()

# Table
data=pd.read_csv('경로가 다르면 경로 작성/data.csv', sep=',', encoding="cp949")

3. 데이터 형태 확인

  • 결측치 확인 및 데이터 형태 확인하는 작업
data.info()

4. 데이터 전처리(값이 특정값인 값만 제거, 컬럼이름 및 값 수정, 원핫인코딩, 제외할 컬럼 제거)

  • One-Hot Encoding : 표현하고 싶은 단어의 인덱스에 1의 값을 부여하고, 다른 인덱스에는 0을 부여하는 단어의 벡터 표현 방식.
# count이 2인 값 인덱스 확인 및 제거
count_2=data_raw[data_raw['count']==2].index
data=data_raw.drop(count_2, inplace=False)

# 컬럼 이름 및 값 수정
data=data.rename(columns={'before1':'after1','before1':'after2'})

data=data.replace({'20대' : '20_age','30대' : '30_age'})

# One-Hot encoding (나이 & 성별)
sex_feature=pd.get_dummies(datan['sex'])
data=pd.concat([data,sex_feature],axis=1)

age_feature=pd.get_dummies(data['age'])
data=pd.concat([data,age_feature],axis=1)

# 제외할 column
datathon=datathon.drop(['sex','age'],axis=1)

5. Train, Test set 나누기

  • test_size: test데이터의 비율 
  • random_state: 호출할 때마다 같은 학습/테스트 용 데이터 세트를 생성하기 위해 주어지는 난수 발생 값. train_test_split()는 호출 시 무작위로 데이터를 분리하므로 random_state를 지정하지 않으면 수행할 때마다 다른 학습/테스트 용 데이터를 만들 수 있습니다. 동일한 데이터 세트로 분리하기 위해 random_state를 일정한 숫자 값으로 부여하면 됩니다.
  • stratify: 계층적 데이터 추출 옵션(데이터 분포에 맞춰 잘 분활한다 !! 따라서 저는 y에 있는 outcom비율에 맞게 분할되는 것 -outcome 은 0과 1 존재) 
X = df.drop(['outcome'], axis=1)
y = df['outcome']

x_train, x_test, y_train, y_test=train_test_split(x, y, test_size=0.3, random_state=42, stratify=y)

# check the shape of X_train and X_test
X_train.shape, X_test.shape

6.  교차검증

  • cv함수 : 교차 검증을 하기 위한 함수 생성. 저는 총 5번의 교차 검증을 하기 위해 아래와 같이  cv값을 5로 넣어주었습니다.
# 교차검증
def cv(clf, x_train, y_train):
    accuracy=cross_val_score(clf, x_train, y_train, scoring='accuracy', cv=5)
    precision=cross_val_score(clf, x_train, y_train, scoring='precision', cv=5)
    recall=cross_val_score(clf, x_train, y_train, scoring='recall', cv=5)
    f1=cross_val_score(clf, x_train, y_train, scoring='f1', cv=5)
    roc_auc=cross_val_score(clf, x_train, y_train, scoring='roc_auc', cv=5)
    print("Cross Validation : 5")
    print("정확도(Accuracy)  - 평균 검증 : ", np.round(np.mean(accuracy), 5),"    교차 검증별 : ", np.round(accuracy, 5))
    print("정밀도(Precision) - 평균 검증 : ", np.round(np.mean(precision), 5), "    교차 검증별 : ", np.round(precision, 5))
    print("재현율(Recall)    - 평균 검증 : ", np.round(np.mean(recall), 5), "    교차 검증별 : ", np.round(recall, 5))
    print("F1 score         - 평균 검증 : ", np.round(np.mean(f1), 5), "    교차 검증별 : ", np.round(f1, 5))
    print("AUC              - 평균 검증 : ", np.round(np.mean(roc_auc), 5), "    교차 검증별 : ", np.round(roc_auc, 5),"\n")

7. 모델 정확도 평가

  • 정확도, 정밀도, 재현율, F1 score, AUC확인(round사용하여 소수점 5번째 자리 반올림)
from sklearn.metrics import accuracy_score, f1_score, confusion_matrix, precision_score, recall_score, roc_auc_score

# 모델 정확도 평가
def pred_eval(y_test, y_pred, model):
    print("Model : ", model)
    print('정확도(Accuracy)  : ' , round(accuracy_score(y_test, y_pred), 5))
    print('정밀도(Precision) : ' , round(precision_score(y_test, y_pred), 5))
    print('재현율(Recall)    : ' , round(recall_score(y_test, y_pred), 5))
    print('F1 score         : ' , round(f1_score(y_test, y_pred), 5))
    print('AUC              : ' , round(roc_auc_score(y_test, y_pred), 5),"\n")

8. RandomForestClassifier 실행

  • GridSearchCV하는 과정에서 n_jobs=30으로 정해줌으로써 cpu자원을 3000까지 쓸 수 있도록 제한 하였습니다. (현재 docker container로 작업중이여서 가지고 있는 cpu자원이 80개 한정이라 30정도로 잡아주었고, 일반 컴퓨터에서 실행하시는거면 cpu자원이 제한되어 있기 때문에 확인 후 가지고 있는 cpu자원을 전체 사용하려면 n_jobs=-1로 작성하면 됩니다.)
  • verbose=2 로 할당해주면 현재 어디까지 진행되고 있는지 실시간을 출력됩니다.
  • cv_results_ : 는 위 파라미터의 경우의 수를 다 뽑아 score점수를 볼 수 있습니다. 경우의 수가 얼마 안되는 경우 print를 사용해서 보면 되지만 저는 경우의 수가 너무 많아 csv파일로 따로 뽑아 확인해 보고, 파라미터 조정을 계속 해주었습니다.
from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestClassifier

 # 랜덤포레스트 실행
 def rf_best(x_train, y_train, x_test, y_test):
    #find best parameter
    start=time()
    clf = RandomForestClassifier()
    params = {'n_estimators' : list(range(50,400,10)),
              'max_depth' : list(range(4,20,15)),
              'min_samples_leaf' : list(range(4,20,1)),
              'min_samples_split' : list(range(2,20,1))}
    grid_cv = GridSearchCV(clf, param_grid=params, cv=5, n_jobs=30, verbose=2)
    grid_cv.fit(x_train, y_train)
    
    # 보통 best_params만 확인하지만 저는 혹시 모를 상황에 모든 parameter들의 점수를 확인한 후 추출하는 과정을 시행하였습니다.
    score_df=pd.DataFrame(grid_cv.cv_results_)
    # 양이 너무 많기 때문에 csv로 따로 저장
    score_df.to_csv("/save/score_df_rf.csv")
    #print(score_df)
    
    best_params = pd.DataFrame.from_records([grid_cv.best_params_])
    print(best_params)
    print("best parameter(RF) - find best parameter : {} 분\n".format(round((time()-start)/60, 2)))
    
    #input best parameter 
    start=time()
    clf = RandomForestClassifier(n_estimators = int(best_params['n_estimators']),
                                 max_depth = int(best_params['max_depth']),
                                 min_samples_leaf = int(best_params['min_samples_leaf']),
                                 min_samples_split = int(best_params['min_samples_split']))
    clf.fit(x_train, y_train)
    y_pred=clf.predict(x_test)
    feature_importance = clf.feature_importances_
    pred_eval(y_test, y_pred, "Random Forest, Best")
    print("best parameter(RF) - model fit : {} 분\n".format(round((time()-start)/60, 2)))
    return y_pred, feature_importance

9. feature importance확인 및 confusuon matrix확인

import seaborn as sns
import matplotlib.pyplot as plt

# figure 함수
def feature_impo(feature_importance, X_train, model):
    feature_imp=np.array(feature_importance)
    feature_name=np.array(X_train.columns)
    data={"feature_name": feature_name, "feature_importance":feature_imp}
    data=pd.DataFrame(data)
    data.sort_values(by=['feature_importance'], ascending=False, inplace=True)
    plt.figure(figsize=(10,20))
    sns.barplot(x=data['feature_importance'], y=data["feature_name"])
    plt.title(model+" feature importance")
    plt.show()
    return 
    
# 위 시각화를 dataframe으로 보는 작업
def feature_impo_df(feature_importance, X_train):
    feature_importance = pd.Series(feature_importance, index=X_train.columns)
    feature_top = feature_importance.sort_values(ascending=False)[:len(X_train)]
    feature = pd.DataFrame(feature_top.reset_index())
    feature.columns = ['feature', 'importance']
    return feature

#confusion matrix
def confu(y_test, y_pred, model):
    result = pd.concat([y_test.loc[:,['OUTCOME']].reset_index(drop=True),pd.DataFrame(y_pred,columns=['예측값'])],axis=1)
    cm=pd.DataFrame(confusion_matrix(result['OUTCOME'],result['예측값']))
    sns.heatmap(cm, annot=True, fmt='g')
    plt.title(model+" Confusion Metrix")

여기까지 RandomForestClassifier 분석을 마치겠습니다.