[ Python ] Cross Validation 병렬로 돌리고 BoxPlot 시각화

2019. 11. 7. 23:05분석 Python/Scikit Learn (싸이킷런)

728x90

(상황)

여러 가지 테이블들이 있고 각각을 GBM으로 모델링을 하고 CrossValidation을 하고 나서 결과값을 box plot으로 시각화하고 싶다.

Result라는 dictionary에 총 8개의 방법론을 사용해서 Imputation 된 값들이 들어가 있다.

이것들을 모델은 Gradient Boosting Machine 이용하고 CrossValidation을 진행하고 Boxplot을 그릴 것다.

시간이 오래 걸릴 것 같아서 joblib을 사용하여 Parallel 하게 돌리도록 했다.

모델링 ㄱㄱ!

from joblib import Parallel, delayed
from sklearn.model_selection import KFold
from sklearn.ensemble import GradientBoostingClassifier as GBM
from sklearn.metrics import f1_score
import category_encoders as CatEncoder
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder


def parallel_cv( Method ,  train_index, test_index) :
    X_imp = deepcopy(Result[Method])
    XX_imp = X_imp.drop(["churn"], axis = 1)
    XXX_imp = CatEncoder.OneHotEncoder().fit_transform(XX_imp).values
    y = LabelEncoder().fit_transform(RAW["churn"].values)
    Model = GBM(max_depth= 7).fit(X = XXX_imp[train_index , : ] , y= y[train_index] )
    y_pred = Model.predict(XXX_imp[test_index, :])
    metric = f1_score(y[test_index] , y_pred)
    return metric 
    

Methods = list(Result.keys())

kf = KFold(n_splits = 7) # Define the split - into 2 folds 
Indexs = list(kf.split(Result["mean"]))

Method_Outcome = {}
for Method in Methods :
    X_imp = deepcopy(Result[Method])
    cv_result = (Parallel(n_jobs= kf.n_splits ,backend = "threading",prefer="threads")
                       (delayed(parallel_cv)
                        (Method , train_index, test_index) 
                        for train_index, test_index in Indexs))
    cv_f1 = np.mean(list(cv_result))
    print("{:11}, cv_f1_score : {:7.5f}".format(Method , cv_f1))
    Method_Outcome[Method] = list(cv_result)

    
    

자 그 다음에는 시각화를 할 차례다. 

가장 시간이 오래 걸린 부분은

1. text 크기를 개별적으로 조정하는 법

2. 결과값을 어떻게 표현할지를 고민

원래는 boxplot 중간 중간에 그리려고 했는데, 먼가 정갈하지 못한 것 같아서 이름 옆에 붙여서 표현하기로 했다!

cv_melting = pd.DataFrame(Method_Outcome).melt()
cv_mean  = cv_melting.groupby(["variable"])["value"].mean()
cv_mean_value = cv_mean.values
pos = range(len(cv_mean_value))
cv_mean_label = [str(np.round(s, 2)) for s in cv_mean.values] 
sns.set(rc={'figure.figsize':(15.7,10.27) }) 
sns.set_context("paper", rc={"font.size":20,
                             "axes.titlesize":30,
                             "axes.labelsize":20},
                font_scale = 2.0
               )  
ax = sns.boxplot(y="variable", x="value", data=cv_melting)
ax.set(xlabel='F1-Score', ylabel='Method',
       title = "Model CV F1-Score Comparision")
list_ = list(ax.get_yticklabels())
xticklables_ = []
for tick , label in enumerate(list_) :
    method = label.get_text()
    value = cv_mean[method]
    xticklables_.append("{:12}({:5.2f})".format(method , value*100,3))
ax.set_yticklabels(xticklables_, rotation = 0)
plt.show()

 

728x90