반응형
분류 개요와 결정트리 소개¶
정보 균일도 측정 방법¶
- 엔트로피 : 데이터 집합의 혼잡도. 다른값 섞이면 엔트로피 높음. 같으면 낮음.
- 정보 이득 지수 : 1-엔트로피 지수. 데이터 혼잡도가 낮으면 1-엔트로피는 높은값을 가짐. 즉 혼잡도가 낮을수록 높은 지수를 가진다.
정보이득 지수가 높은 속성을 기준으로 분할 - 지니계수 : 데이터가 다양한 값을 가질수록 평등하며 특정값으로 쏠릴 경우에는 불평등. 불평등할수록 1값
즉, 지니계수가 높은 속성을 기준으로 분할(혼잡도 낮음)
결정트리의 특징¶
- 장점 : 쉽고 직관적임, 피처스케일링이나 정규화 등의 사전 데이터 가공 영향도가 적음.
- 단점 : 과적합으로 알고리즘 성능 저하(recursive하게 계속 파고들어서) -> 사전에 트리의 크기 제한하는 튜닝 필요.
결정트리 주요 하이퍼 파라미터¶
- max_depth : 과적합 방지. 사전 트리 크기 제한.
- max_feature : default값 None이고, default면 모든 피처를 사용해 분할 수행. float으로 지정하면 대상 피처의 퍼센트로 지정 가능
sqrt, auto(sqrt와 동일), log등 파라미터 지정 가능. $$sqrt : \sqrt {total features}$$ - min_samples_split : 과적합 방지. 노드를 분할하기위한 최소한의 sample수.
- min_samples_leaf : 과적합 방지. leaf가 되기위한 최소한의 샘플 데이터 수
imbalanced 데이터의 경우 특정 클래스의 데이터가 ㅣ극도로 작을 수 있으므로 작게 설정 필요. - max_leaf_nodes : leaf의 최대 개수
사용자 행동 인식데이터를 이용한 결정트리 실습¶
https://archive.ics.uci.edu/ml/machine-learning-databases/00240/¶
In [ ]:
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
#features.txt 파일에는 피쳐 이름 index와 피쳐명이 공백으로 분리 되어 있음. DataFrame으로 로드
feature_name_df = pd.read_csv('./human_activity/features.txt', sep='\s+', header = None, names=['column_index', 'column_name'])
feature_name_df.head()
In [ ]:
#피처명 index를 제거하고, 피처명만 리스트 객체로 생성한 뒤 샘플로 10개만 추출
feature_name = feature_name_df.iloc[:, 1].tolist()
feature_name
print('전체 피처명에서 10개만 추출\n', feature_name[:10])
질문. 왜 values.tolist()하는지 위 cell에서 바로 tolist하니까 되는데?¶
'./human_activity/train/X_train.txt'에서 .txt꼭 붙여야하는건지?
In [ ]:
def get_human_dataset():
#각 데이터 파일들은 공백으로 분리되어 있으므로 read_csv에서 공백 문자를 serp으로 할당.
feature_name_df = pd.read_csv('./human_activity/features.txt', sep = '\s+', header = None , names=['column_index', 'coluumn_name'])
#DataFrame에 피처명을 컬럼으로 부여하기 위해 리스트 객체로 다시 변환
feature_name = feature_name_df.iloc[:,1].values.tolist()
#학습 피쳐 데이터 셋과 테스트 피쳐 데이터 셋을 DataFrame으로 로딩, 컬럼명은 feature_name 적용.
X_train = pd.read_csv('./human_activity/train/X_train.txt', sep='\s+', names = feature_name)
X_test = pd.read_csv('./human_activity/test/X_test.txt', sep = '\s+', names = feature_name)
#학습 레이블과 테스트 레이블 데이터를 DataFrame으로 로딩하고 컬럼명은 action으로 부여
y_train = pd.read_csv('./human_activity/train/y_train.txt', sep='\s+', header = None , names=['action'])
y_test = pd.read_csv('./human_activity/test/y_test.txt', sep='\s+', header = None , names=['action'])
return X_train, X_test, y_train, y_test
X_train, X_test, y_train, y_test = get_human_dataset()
561개 feature에서 len(set(feature_name)) 하니 477개가 나왔음 90개정도 중복되고있는데. feature name이 중복되도 괜찮은지...¶
In [ ]:
print('## 학습 피쳐 데이터셋 info()')
print(X_train.info())
In [ ]:
y_train.head()
In [ ]:
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
#예제 반복 시 마다 동일한 예측 결과 도출을 위해 random_state 설정
dt_clf = DecisionTreeClassifier(random_state = 156)
dt_clf.fit(X_train, y_train)
pred = dt_clf.predict(X_test)
accuracy = accuracy_score(y_test, pred)
print(f'결정 트리 예측 정확도 {accuracy:.4f}')
#DecisionTreeClassifier의 하이퍼 파라미터 추출
print('DecisionTreeClassifier 기본 하이퍼 파라미터:\n', dt_clf.get_params())
In [ ]:
from sklearn.model_selection import GridSearchCV
params = {
'max_depth' : [6, 8, 10, 12, 16, 20, 24]
}
grid_cv = GridSearchCV(dt_clf, param_grid = params, scoring = 'accuracy', cv=5, verbose =1)
grid_cv.fit(X_train, y_train)
print(f'GridSearchCV 최고 평균 정확도 수치:{grid_cv.best_score_:.4f}')
print(f'GridSearchCV 최적 하이퍼 파라미터:{grid_cv.best_params_}')
In [ ]:
#GridSearchCV 객체이ㅡ cv_results_ 속성을 DataFrame으로 생성
cv_results_df = pd.DataFrame(grid_cv.cv_results_)
#max_depth 파라미터 값과 그때의 테스트(Evaluation)셋, 학습데이터 셋의 정확도 수치 추출
cv_results_df[['param_max_depth', 'mean_test_score']]
In [ ]:
max_depths = [6,8,10,12,16,20,24]
# max_depth값을 변화 시키면서 그때마다 학습과 테스트 셋에서의 예측 성능 측정
for depth in max_depths:
dt_clf = DecisionTreeClassifier(max_depth = depth, random_state =156)
dt_clf.fit(X_train, y_train)
pred = dt_clf.predict(X_test)
accuracy = accuracy_score(y_test , pred)
print(f'max_depth = {depth}, 정확도 : {accuracy:.4f}')
In [ ]:
params = {
'max_depth' : [ 8 , 12, 16 ,20],
'min_samples_split' : [16,24],
}
grid_cv = GridSearchCV(dt_clf, param_grid = params, scoring = 'accuracy', cv=5, verbose=1)
grid_cv.fit(X_train, y_train)
print(f'GridSearchCV 최고 평균 정확도 수치 : {grid_cv.best_score_:.4f}')
print(f'GridSearchCV 최적 하이퍼 파라미터 :{grid_cv.best_params_}')
In [ ]:
best_df_clf = grid_cv.best_estimator_
pred1 = best_df_clf.predict(X_test)
accuracy = accuracy_score(y_test , pred1)
print(f'결정 트리 예측 정확도:{accuracy:.4f}')
In [ ]:
import seaborn as sns
ftr_importances_values = best_df_clf.feature_importances_
#Top 중요도로 정렬을 쉽게 하고, seaborn의 막대그래프로 쉽게 표현하기 위해 Series변환
ftr_importances = pd.Series(ftr_importances_values, index =X_train.columns)
display(ftr_importances.sort_values(ascending = False).head(20))
#중요도 값 순으로 Series를 정렬
ftr_top20 = ftr_importances.sort_values(ascending = False)[:20]
print(ftr_top20.index)
plt.figure(figsize=(8,6)) #그래프 크기.
plt.title('Feature importances Top 20')
sns.barplot(x=ftr_top20, y = ftr_top20.index) #
plt.show()
앙상블(Ensemble) 학습의 개요와 보팅(voting)의 이해¶
앙상블 학습¶
- 앙상블 학습을 통한 분류는 여러개의 분류기를 생성하고
그 예측을 결합함으로써 보다 정확한 최종 예측을 도입하는 기법을 말한다. - 보팅(voting), 배깅(bagging), 부스팅(Boosting)으로 구분할 수 있으며, 이외에 스태킹(stacking)등의 기법이 있음.
- 배깅 : 랜덤포레스트(Random Forest)알고리즘
- 부스팅 : 에이다 부스팅, 그래디언트부스팅(GBM), XGBoost, LightGBM
- 넓은 의미로는 서로 다른 모델을 결합한 것.
성능은 각기 떨어지는 모델이지만 이질적인 모델들을 합치면 전체 성능에 도움이 될 수있음.
성능이 좋은모델+ 좋은모델의 단점을 커버할 수 있는 이질적인 모델들 = 좋은 성능
ex)Tree기반 + SVM기반 + Linear기반 앙상블 = 좋은 성능
결정트리의 단점인 과적합(overfitting)을 수십~ 수천개의 많은 분류기를 결합해서 보완하고 장점인 직관적인 분류기준은 강화#### 보팅과 배깅
- 보팅(voting) : 같은 data set + 다른 알고리즘 모델 (일반적으로 Soft voting이 성능이 우수)
- Hard voting : 각 모델들이 예측 후 다수결
- Soft voting : 각 모델들이 예측전 확률값을 평균내어 결정
- Hard voting : 각 모델들이 예측 후 다수결
- 배깅(bagging) : split된 data set + 같은 알고리즘 모델
위스콘신 유방암 데이터로드 (Voting방식 실습)¶
In [ ]:
import pandas as pd
from sklearn.ensemble import VotingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
cancer = load_breast_cancer()
data_df = pd.DataFrame(cancer.data, columns=cancer.feature_names)
data_df.head(3)
VotingClassifier안의 voting = 'soft'를 지정해서 소프트보팅 객체 만듦.¶
- LogisticRegression모델 + KNeighborsClassifier모델
In [ ]:
# 개별 모델은 로지스틱 회귀와 KNN 임.
lr_clf = LogisticRegression()
knn_clf = KNeighborsClassifier(n_neighbors=8)
# 개별 모델을 소프트 보팅 기반의 앙상블 모델로 구현한 분류기
vo_clf = VotingClassifier( estimators=[('LR',lr_clf),('KNN',knn_clf)] , voting='soft' )
X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target,
test_size=0.2 , random_state= 156)
# VotingClassifier 학습/예측/평가.
vo_clf.fit(X_train , y_train)
pred = vo_clf.predict(X_test)
print('Voting 분류기 정확도: {0:.4f}'.format(accuracy_score(y_test , pred)))
# 개별 모델의 학습/예측/평가.
classifiers = [lr_clf, knn_clf]
for classifier in classifiers:
classifier.fit(X_train , y_train)
pred = classifier.predict(X_test)
class_name= classifier.__class__.__name__
print('{0} 정확도: {1:.4f}'.format(class_name, accuracy_score(y_test , pred)))
배깅(bagging) - 랜덤 포레스트(Random Forest)¶
- 배깅의 대표적인 알고리즘 : 랜덤 포레스트
- 빠른수행속도.
- 여러개의 결정트리 분류기가 전체데이터에서 배깅방식으로 각자의 데이터 샘플링
개별적으로 학습을 수행하고 최종적으로 모든 분류기가 보팅을 통해 예측 결정 - bootstrap aggregating의 줄임말 : 개별트리가 학습하는 데이터세트는 전체 데이터에서 일부가 중첩되게 샘플링된 데이터세트
이렇게 중복 sampling하는 방식을 bootstraping이라 한다. - 하이퍼 파라미터
- n_estimators : 결정트리의 개수(default 10) 많으면 좋은 성능을 기대할 수 있지만 무조건적인 성능 향상x. 학습수행시간과 trade-off
- max_features : 기본설정이 None이 아님. sqrt라서 9개의 feature면 3개의 feature를 참조.
In [ ]:
import pandas as pd
def get_new_feature_name_df(old_feature_name_df):
feature_dup_df = pd.DataFrame(data=old_feature_name_df.groupby('column_name').cumcount(), columns=['dup_cnt'])
feature_dup_df = feature_dup_df.reset_index()
new_feature_name_df = pd.merge(old_feature_name_df.reset_index(), feature_dup_df, how='outer')
new_feature_name_df['column_name'] = new_feature_name_df[['column_name', 'dup_cnt']].apply(lambda x : x[0]+'_'+str(x[1])
if x[1] >0 else x[0] , axis=1)
new_feature_name_df = new_feature_name_df.drop(['index'], axis=1)
return new_feature_name_df
In [ ]:
import pandas as pd
def get_human_dataset( ):
# 각 데이터 파일들은 공백으로 분리되어 있으므로 read_csv에서 공백 문자를 sep으로 할당.
feature_name_df = pd.read_csv('./human_activity/features.txt',sep='\s+',
header=None,names=['column_index','column_name'])
# 중복된 feature명을 새롭게 수정하는 get_new_feature_name_df()를 이용하여 새로운 feature명 DataFrame생성.
new_feature_name_df = get_new_feature_name_df(feature_name_df)
# DataFrame에 피처명을 컬럼으로 부여하기 위해 리스트 객체로 다시 변환
feature_name = new_feature_name_df.iloc[:, 1].values.tolist()
# 학습 피처 데이터 셋과 테스트 피처 데이터을 DataFrame으로 로딩. 컬럼명은 feature_name 적용
X_train = pd.read_csv('./human_activity/train/X_train.txt',sep='\s+', names=feature_name )
X_test = pd.read_csv('./human_activity/test/X_test.txt',sep='\s+', names=feature_name)
# 학습 레이블과 테스트 레이블 데이터을 DataFrame으로 로딩하고 컬럼명은 action으로 부여
y_train = pd.read_csv('./human_activity/train/y_train.txt',sep='\s+',header=None,names=['action'])
y_test = pd.read_csv('./human_activity/test/y_test.txt',sep='\s+',header=None,names=['action'])
# 로드된 학습/테스트용 DataFrame을 모두 반환
return X_train, X_test, y_train, y_test
X_train, X_test, y_train, y_test = get_human_dataset()
학습/테스트 데이터로 분리하고 (get_human_dataset) 랜덤 포레스트로 학습/예측/평가¶
In [ ]:
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
import pandas as pd
import warnings
warnings.filterwarnings('ignore')
# 결정 트리에서 사용한 get_human_dataset( )을 이용해 학습/테스트용 DataFrame 반환
X_train, X_test, y_train, y_test = get_human_dataset()
# 랜덤 포레스트 학습 및 별도의 테스트 셋으로 예측 성능 평가
rf_clf = RandomForestClassifier(random_state=0)
rf_clf.fit(X_train , y_train)
pred = rf_clf.predict(X_test)
accuracy = accuracy_score(y_test , pred)
print('랜덤 포레스트 정확도: {0:.4f}'.format(accuracy))
GridSearchCV로 교차검증 및 하이퍼 파라미터 튜닝¶
In [ ]:
from sklearn.model_selection import GridSearchCV
params = {
'n_estimators':[100],
'max_depth' : [6, 8, 10, 12],
'min_samples_leaf' : [8, 12, 18 ],
'min_samples_split' : [8, 16, 20]
}
# RandomForestClassifier 객체 생성 후 GridSearchCV 수행
rf_clf = RandomForestClassifier(random_state=0, n_jobs=-1)
grid_cv = GridSearchCV(rf_clf , param_grid=params , cv=2, n_jobs=-1 )
grid_cv.fit(X_train , y_train)
print('최적 하이퍼 파라미터:\n', grid_cv.best_params_)
print('최고 예측 정확도: {0:.4f}'.format(grid_cv.best_score_))
튜닝된 하이퍼 파라미터로 재 학습 및 예측/평가¶
In [ ]:
rf_clf1 = RandomForestClassifier(n_estimators=300, max_depth=10, min_samples_leaf=8, \
min_samples_split=8, random_state=0)
rf_clf1.fit(X_train , y_train)
pred = rf_clf1.predict(X_test)
print('예측 정확도: {0:.4f}'.format(accuracy_score(y_test , pred)))
개별 feature들의 중요도 시각화¶
In [ ]:
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
ftr_importances_values = rf_clf1.feature_importances_
ftr_importances = pd.Series(ftr_importances_values,index=X_train.columns )
ftr_top20 = ftr_importances.sort_values(ascending=False)[:20]
plt.figure(figsize=(8,6))
plt.title('Feature importances Top 20')
sns.barplot(x=ftr_top20 , y = ftr_top20.index)
plt.show()
부스팅¶
여러개의 약한 학습기(weak learner)를 순차적으로 학습-예측 하면서
잘못 예측한 데이터에 가중치 부여를 통해 오류를 개선해 나가면서 학습하는 방식
- 순차적으로 하다보니 수행시간이 오래걸림
- 에이다부스팅 프로세스 : 오류들에 가중치 부여 - 분류기준 - 예측 반복.
- GBM(Gradient Boost Machine) : 에이다부스트와 유사하나, 가중치 업데이트를 경사하강법을 이용하는 것이 큰차이
h(x) = y-F(x)를 최소화하는 방향성을 가지고 가중치 업데이트.
사이킷런 GBM 하이퍼파라미타¶
- loss : 경사하강법에 사용할 비용함수. default = deviance
- learning_rate : 학습률 - 딥러닝의 알파와 같음. 아는 내용이니 설명 생략.
- n_estimators : weak learner의 개수. 약한 학습기가 순차적으로 오류를 보정하므로 개수가 많을수록 성능상승
그러나 개수가 많을수록 수행시간 오래걸림. default = 100 - subsample : weak learner가 학습에 사용하는 데이터의 샘플링 비율. default =1. 과적합 우려시 1보다 작은값설정
In [ ]:
from sklearn.ensemble import GradientBoostingClassifier
import time
import warnings
warnings.filterwarnings('ignore')
X_train, X_test, y_train, y_test = get_human_dataset()
# GBM 수행 시간 측정을 위함. 시작 시간 설정.
start_time = time.time()
gb_clf = GradientBoostingClassifier(random_state=0)
gb_clf.fit(X_train , y_train)
gb_pred = gb_clf.predict(X_test)
gb_accuracy = accuracy_score(y_test, gb_pred)
print('GBM 정확도: {0:.4f}'.format(gb_accuracy))
print("GBM 수행 시간: {0:.1f} 초 ".format(time.time() - start_time))
In [ ]:
scores_df = pd.DataFrame(grid_cv.cv_results_)
scores_df[['params', 'mean_test_score', 'rank_test_score',
'split0_test_score', 'split1_test_score']]
In [ ]:
# GridSearchCV를 이용하여 최적으로 학습된 estimator로 predict 수행.
gb_pred = grid_cv.best_estimator_.predict(X_test)
gb_accuracy = accuracy_score(y_test, gb_pred)
print('GBM 정확도: {0:.4f}'.format(gb_accuracy))
XGBoost (eXtra Gradient Boost)¶
- 뛰어난 예측 성능, GBM 대비 빠른 수행시간 CPU병렬, GPU 지원
- 다양한 성능 향상기능 (regularization)기능, Tree Pruning
- Tree pruning(가지치기) : 노드를 모두 만들었다가 역으로 노드들이 제 역할을 하는지 검증. 불필요하다고 판단되면 가지치기 해버림.
- 다양한 편의 기능 추가(조기중단, 내장 교차검증, 결손값 자체처리
### 파이썬 Wrapper vs 사이킷런 Wrapper
- 파이썬 래퍼를 쓰던 안쓰던 어느정도 이해 필요.
- XGBoost의 하이퍼파라미터가 많지만 엄청 공들여서 튜닝하지 말 것.
- 사이킷런 Wrapper의 경우 GBM에 동일한 하이퍼 파라미터가 있다면
이를 사용하고 그렇지 않다면 파이썬 Wrapper의 하이퍼 파라미터를 사용 - 다른 하이퍼파라미터들 설명은 생략.
- Early Stopping
- 특정 반복 횟수(n)만큼 더이상 비용함수가 감소하지 않으면 지정된 반복횟수를 다 완료하지 않고 수행 종료.
- n값이 너무 적으면 성능 최적화가 안된상태에서 학습이 종료될 수 있음.
- early_stooping_rounds : n값 설정해줌
- eval_metric : 반복 수행시 사용하는 비용 평가 지표
- eval_set : 평가를 수행하는 별도의 검증 데이터 세트(validation set)
In [ ]:
import xgboost
xgboost.__version__
파이썬 래퍼 XGBoost 적용
위스콘신 Breast Cancer 데이터 셋
데이터 세트 로딩¶
In [ ]:
import xgboost as xgb
from xgboost import plot_importance
import pandas as pd
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
import warnings
warnings.filterwarnings('ignore')
dataset = load_breast_cancer()
X_features = dataset.data
y_label = dataset.target
cancer_df = pd.DataFrame(data = X_features, columns = dataset.feature_names)
cancer_df['target'] = y_label
cancer_df.info()
In [ ]:
print(dataset.target_names)
print(cancer_df['target'].value_counts())
In [ ]:
#전체 데이터 중 80%는 학습용 데이터, 20%는 테스트용 데이터 추출
X_train, X_test, y_train, y_test = train_test_split(X_features, y_label, test_size = 0.2, random_state=156)
print(X_train.shape, X_test.shape)
학습과 예측 데이터 세트를 DMatrix로 변환¶
In [ ]:
dtrain = xgb.DMatrix(data=X_train, label=y_train)
dtest = xgb.DMatrix(data=X_test, label = y_test)
하이퍼 파라미터 설정¶
In [ ]:
params = {'max_depth':3,
'eta' : 0.1,
'objective':'binary:logistic',
'eval_metric':'logloss',
'early_stopings' : 100
}
num_rounds = 400
주어진 하이퍼 파라미터와 early stopping 파라미터를 train() 함수의 파라미터로 전달하고 학습¶
In [ ]:
#train 데이터 셋은 'train', evaluation(test) 데이터 셋은 'eval' 로 명기한다.
wlist = [(dtrain,'train'),(dtest,'eval')]
#하이퍼 파라미터와 early stopping 파라미터를 train() 함수의 파라미터로 전달
xgb_model = xgb.train(params = params, dtrain = dtrain,
num_boost_round = num_rounds, evals = wlist )
predict()를 통해 예측 확률값을 반환하고 예측 값으로 변환¶
In [ ]:
pred_probs = xgb_model.predict(dtest)
print('predict() 수행 결과값을 10개만 표시, 예측 확률 값으로 표시됨')
print(np.round(pred_probs[:10],3))
#예측 확률이 0.5보다 크면 1, 그렇지 않으면 0으로 예측값 결정하여 List객체인 preds에 저장
preds = [1 if x>0.5 else 0 for x in pred_probs]
print('예측값 10개만 표시:', preds[:10])
get_clf_eval()을 통해 예측 평가¶
In [ ]:
from sklearn.metrics import confusion_matrix, accuracy_score
from sklearn.metrics import precision_score, recall_score
from sklearn.metrics import f1_score, roc_auc_score
#수정된 get_clf_eval()함수
def get_clf_eval(y_test, pred=None, pred_proba = None):
confusion = confusion_matrix(y_test, pred)
accuracy = accuracy_score(y_test, pred)
precision = precision_score(y_test, pred)
recall = recall_score(y_test, pred)
f1 = f1_score(y_test, pred)
#ROC-AUC 추가
roc_auc = roc_auc_score(y_test, pred_proba)
print('오차 행렬')
print(confusion)
#ROC-AUC print 추가
print(f'정확도: {accuracy:.4f}, 정밀도:{precision:.4f}, 재현률: {recall:.4f},\
F1: {f1:.4f}, AUC:{roc_auc:.4f}')
In [ ]:
get_clf_eval(y_test, preds, pred_probs)
Feature importance 시각화¶
In [ ]:
import matplotlib.pyplot as plt
%matplotlib inline
fig, ax = plt.subplots(figsize=(10,12))
plot_importance(xgb_model, ax = ax)
In [ ]:
#사이킷런 래퍼 XGBoost 클래스인 XGBClassifier import
from xgboost import XGBClassifier
evals = [(X_test, y_test)]
xgb_wrapper = XGBClassifier(n_estimators = 400, learning_rate = 0.1, max_depth=3)
xgb_wrapper.fit(X_train, y_train, early_stopping_rounds=400, eval_set = evals, eval_metric = 'logloss', verbose=True)
w_preds = xgb_wrapper.predict(X_test)
w_pred_proba = xgb_wrapper.predict_proba(X_test)[:,1]
In [ ]:
get_clf_eval(y_test, w_preds, w_pred_proba)
early stopping을 100으로 설정하고 재 학습/예측/평가¶
In [ ]:
from xgboost import XGBClassifier
xgb_wrapper = XGBClassifier(n_estimators = 400, learning_rate=0.1, max_depth = 3)
evals = [(X_test, y_test)]
xgb_wrapper.fit(X_train, y_train, early_stopping_rounds=100, eval_metric='logloss',
eval_set = evals, verbose = True)
ws100_preds = xgb_wrapper.predict(X_test)
ws100_pred_proba = xgb_wrapper.predict_proba(X_test)[:,1]
predict=0
for proba in ws100_pred_proba:
if proba >0.5 :
predict = 1
else:
predict = 0
print(f'proba : {proba:.4f}, 예측값 = {predict}')
In [ ]:
get_clf_eval(y_test, ws100_preds, ws100_pred_proba)
early stopping을 10으로 설정하고 재 학습/예측/평가¶
In [ ]:
#early_stopping_rounds를 10으로 설정하고 재학습
xgb_wrapper.fit(X_train, y_train, early_stopping_rounds= 10,
eval_metric = "logloss", eval_set = evals, verbose = True)
ws10_preds = xgb_wrapper.predict(X_test)
ws10_pred_proba = xgb_wrapper.predict_proba(X_test)[:,1]
get_clf_eval(y_test, ws10_preds, ws10_pred_proba)
In [ ]:
from xgboost import plot_importance
import matplotlib.pyplot as plt
%matplotlib inline
fig,ax = plt.subplots(figsize = (10,12))
#사이킷런 래퍼 클래스를 입력해도 무방.
plot_importance(xgb_wrapper, ax = ax)
LightGBM¶
XGBoost 대비 장점¶
- 더 빠른 학습과 예측 수행 시간
- 더 작은 메모리사용량
- 카테고리형 피처의 자동 변환과 최적 분할(One-Hot인코딩 등을 사용하지 않고도 카테고리형 피처를 최적으로 변환하고
이에 따른 노드 분할 수행
LightGBM 트리 분할 방식 - Leaf Wise¶
- 균형 트리 분할(Level Wise) : Depth최소화 - depth가 깊어지면 overfitting될 확률이 높을것이다.
- 리프 중심 트리 분할(Leaf Wise) : Depth 신경쓰지 않음 -
depth가 깊어지는 방향성을 가져도 오류를 줄일 수 있다면 Leaf중심으로 분할해도 괜찮다.
하이퍼 파라미터는 XGBoost에 있는 하이퍼 파라미터면 그대로 받아들이고, 없는거면 파이썬 래퍼를 따름.¶
In [ ]:
import lightgbm
lightgbm.__version__
LightGBM 적용 - 위스콘신 Breast Cancer Prediction¶
In [ ]:
#LightGBM의 파이선 패키지인 lightgbm에서 LGBMClassifier import
from lightgbm import LGBMClassifier
import pandas as pd
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
dataset = load_breast_cancer()
ftr = dataset.data
target = dataset.target
#전체 데이터 중 80%는 학습용 데이터, 20%는 테스트용 데이터 추출
X_train, X_test, y_train, y_test = train_test_split(ftr, target, test_size = 0.2, random_state = 156)
#앞서 XGBoost와 동일하게 n_estimators는 400설정
lgbm_wrapper = LGBMClassifier(n_estimators = 400)
#LightGBM도 XGBoost와 동일하게 조기 중단 수행 가능.
evals = [(X_test, y_test)]
lgbm_wrapper.fit(X_train, y_train, early_stopping_rounds = 100, eval_metric="logloss",
eval_set=evals, verbose = True)
preds = lgbm_wrapper.predict(X_test)
pred_proba = lgbm_wrapper.predict_proba(X_test)[:, 1]
In [ ]:
from sklearn.metrics import confusion_matrix, accuracy_score
from sklearn.metrics import precision_score, recall_score
from sklearn.metrics import f1_score, roc_auc_score
# 수정된 get_clf_eval() 함수
def get_clf_eval(y_test, pred=None, pred_proba=None):
confusion = confusion_matrix( y_test, pred)
accuracy = accuracy_score(y_test , pred)
precision = precision_score(y_test , pred)
recall = recall_score(y_test , pred)
f1 = f1_score(y_test,pred)
# ROC-AUC 추가
roc_auc = roc_auc_score(y_test, pred_proba)
print('오차 행렬')
print(confusion)
# ROC-AUC print 추가
print('정확도: {0:.4f}, 정밀도: {1:.4f}, 재현율: {2:.4f},\
F1: {3:.4f}, AUC:{4:.4f}'.format(accuracy, precision, recall, f1, roc_auc))
In [ ]:
get_clf_eval(y_test, preds, pred_proba)
In [ ]:
from lightgbm import plot_importance
import matplotlib.pyplot as plt
%matplotlib inline
fig, ax = plt.subplots(figsize=(10, 12))
# 사이킷런 래퍼 클래스를 입력해도 무방.
plot_importance(lgbm_wrapper, ax=ax)
numpy로 들어가있기때문에 column명을 알 수가 없음.¶
In [ ]:
print(dataset.feature_names)
산탄데르, 신용카드 사기 예측 실습 보고오기
스태킹(Stacking)¶
- 여러모델들이 예측한 결과값을 쌓아서(stacking) Meta model이 재학습하여 최종 predict
- 성능이 더 좋아질거란 보장은 없음
Basic 스태킹 모델¶
데이터 로딩¶
In [ ]:
import numpy as np
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
cancer_data = load_breast_cancer()
X_data = cancer_data.data
y_label = cancer_data.target
X_train , X_test , y_train , y_test = train_test_split(X_data , y_label , test_size=0.2 , random_state=0)
개별 Classifier와 최종 Stacking 데이터를 학습할 메타 Classifier 생성¶
In [ ]:
# 개별 ML 모델을 위한 Classifier 생성.
knn_clf = KNeighborsClassifier(n_neighbors=4)
rf_clf = RandomForestClassifier(n_estimators=100, random_state=0)
dt_clf = DecisionTreeClassifier()
ada_clf = AdaBoostClassifier(n_estimators=100)
# 최종 Stacking 모델을 위한 Classifier생성.
lr_final = LogisticRegression(C=10)
개별 Classifier 학습/예측/평가¶
In [ ]:
# 개별 모델들을 학습.
knn_clf.fit(X_train, y_train)
rf_clf.fit(X_train , y_train)
dt_clf.fit(X_train , y_train)
ada_clf.fit(X_train, y_train)
In [ ]:
# 학습된 개별 모델들이 각자 반환하는 예측 데이터 셋을 생성하고 개별 모델의 정확도 측정.
knn_pred = knn_clf.predict(X_test)
rf_pred = rf_clf.predict(X_test)
dt_pred = dt_clf.predict(X_test)
ada_pred = ada_clf.predict(X_test)
print('KNN 정확도: {0:.4f}'.format(accuracy_score(y_test, knn_pred)))
print('랜덤 포레스트 정확도: {0:.4f}'.format(accuracy_score(y_test, rf_pred)))
print('결정 트리 정확도: {0:.4f}'.format(accuracy_score(y_test, dt_pred)))
print('에이다부스트 정확도: {0:.4f} '.format(accuracy_score(y_test, ada_pred)))
개별 모델의 예측 결과를 메타 모델이 학습할 수 있도록 스태킹 형태로 재 생성¶
In [ ]:
pred = np.array([knn_pred, rf_pred, dt_pred, ada_pred])
print(pred.shape)
# transpose를 이용해 행과 열의 위치 교환. 컬럼 레벨로 각 알고리즘의 예측 결과를 피처로 만듦.
pred = np.transpose(pred)
print(pred.shape)
메타 모델 학습/예측/평가¶
In [ ]:
lr_final.fit(pred, y_test)
final = lr_final.predict(pred)
print('최종 메타 모델의 예측 정확도: {0:.4f}'.format(accuracy_score(y_test , final)))
In [ ]:
from sklearn.model_selection import KFold
from sklearn.metrics import mean_absolute_error
# 개별 기반 모델에서 최종 메타 모델이 사용할 학습 및 테스트용 데이터를 생성하기 위한 함수.
def get_stacking_base_datasets(model, X_train_n, y_train_n, X_test_n, n_folds ):
# 지정된 n_folds값으로 KFold 생성.
kf = KFold(n_splits=n_folds, shuffle=False, random_state=0)
#추후에 메타 모델이 사용할 학습 데이터 반환을 위한 넘파이 배열 초기화
train_fold_pred = np.zeros((X_train_n.shape[0] ,1 ))
test_pred = np.zeros((X_test_n.shape[0],n_folds))
print(model.__class__.__name__ , ' model 시작 ')
for folder_counter , (train_index, valid_index) in enumerate(kf.split(X_train_n)):
#입력된 학습 데이터에서 기반 모델이 학습/예측할 폴드 데이터 셋 추출
print('\t 폴드 세트: ',folder_counter,' 시작 ')
X_tr = X_train_n[train_index]
y_tr = y_train_n[train_index]
X_te = X_train_n[valid_index]
#폴드 세트 내부에서 다시 만들어진 학습 데이터로 기반 모델의 학습 수행.
model.fit(X_tr , y_tr)
#폴드 세트 내부에서 다시 만들어진 검증 데이터로 기반 모델 예측 후 데이터 저장.
train_fold_pred[valid_index, :] = model.predict(X_te).reshape(-1,1)
#입력된 원본 테스트 데이터를 폴드 세트내 학습된 기반 모델에서 예측 후 데이터 저장.
test_pred[:, folder_counter] = model.predict(X_test_n)
# 폴드 세트 내에서 원본 테스트 데이터를 예측한 데이터를 평균하여 테스트 데이터로 생성
test_pred_mean = np.mean(test_pred, axis=1).reshape(-1,1)
#train_fold_pred는 최종 메타 모델이 사용하는 학습 데이터, test_pred_mean은 테스트 데이터
return train_fold_pred , test_pred_mean
In [ ]:
knn_train, knn_test = get_stacking_base_datasets(knn_clf, X_train, y_train, X_test, 7)
rf_train, rf_test = get_stacking_base_datasets(rf_clf, X_train, y_train, X_test, 7)
dt_train, dt_test = get_stacking_base_datasets(dt_clf, X_train, y_train, X_test, 7)
ada_train, ada_test = get_stacking_base_datasets(ada_clf, X_train, y_train, X_test, 7)
In [ ]:
Stack_final_X_train = np.concatenate((knn_train, rf_train, dt_train, ada_train), axis=1)
Stack_final_X_test = np.concatenate((knn_test, rf_test, dt_test, ada_test), axis=1)
print('원본 학습 피처 데이터 Shape:',X_train.shape, '원본 테스트 피처 Shape:',X_test.shape)
print('스태킹 학습 피처 데이터 Shape:', Stack_final_X_train.shape,
'스태킹 테스트 피처 데이터 Shape:',Stack_final_X_test.shape)
In [ ]:
lr_final.fit(Stack_final_X_train, y_train)
stack_final = lr_final.predict(Stack_final_X_test)
print('최종 메타 모델의 예측 정확도: {0:.4f}'.format(accuracy_score(y_test, stack_final)))
Feature Selection¶
- 어떤 피쳐를 제거할 것인가
- 피쳐값의 분포 ( 모두 단일 값인경우 의미가 없음 )
- NULL값이 대부분
- 피처간 너무 높은 상관도( B = A/2 등등.. )
- Target값과 독립된 피쳐
- 대부분 모델의 피쳐 중요도(Feature Importance) 기반
### 사이킷런의 Feature Selection 지원
- RFE(Recursive Feature Elimination)
- 모델 최초 학습 후 Feature 중요도 선정
- feature 중요도가 낮은 속성들을 차례로 제거하고 반복적으로 학습/평가 추출하여 최적 feature 추출
- 경우의 수가 너무 많고, 수행시간 너무 오래걸림.
- SelectionFromModel
- 모델 최초 학습 후 선정된 Feature 중요도에 따라 평균/중앙값 특정 비율 이상인 Feature들을 선택
In [ ]:
반응형
'인공지능 > Merchine_Learning' 카테고리의 다른 글
[파이썬 머신러닝 완벽가이드] 협업필터링 (0) | 2020.12.21 |
---|---|
[파이썬 머신러닝 완벽가이드] 추천시스템 - 콘텐츠기반 (1) | 2020.12.21 |
[파이썬 머신러닝 완벽가이드] Ch7 Clustering 내용 (0) | 2020.11.23 |
[파이썬 머신러닝 완벽가이드] Ch4. Practice 산탄데르 고객 만족 예측 (0) | 2020.11.14 |
[파이썬 머신러닝 완벽가이드] Ch.5 Regression (0) | 2020.11.14 |