ch04. 분류

Chapter 04. 분류

00. 정리

결정 트리

  • 대부분의 앙상블 기법은 결정 트리 기반의 다수의 약한 학습기를 결합해 변동성을 줄여 예측 오류를 줄이고 성능을 개선하고 있습니다.
  • 결정 트리 알고리즘은 정보의 균일도에 기반한 규칙 트리를 만들어서 예측을 수행합니다.
  • 결정 트리는 어떻게 예측 결과가 도출되었는지 그 과정을 비교적 쉽게 알 수 있습니다.
  • 결정 트리의 단점은 균일한 최종 예측 결과를 도출하기 위해 결정 트리가 깊어지고 복잡해 지면서 과적합이 쉽게 발생합니다.

배깅

  • 배깅 방식은 학습 데이터를 중복을 허용하면서 다수의 세트로 샘플링하여 이를 다수의 약한 학습기가 학습한 뒤 최종 결과를 결합해 예측하는 방식입니다.
  • 랜덤 포레스트는 수행시간이 빠르고 비교적 안정적인 예측 성능을 제공하는 훌륭한 머신러닝 알고리즘입니다.

부스팅

  • 부스팅은 학습기들이 순차적으로 학습을 진행하면서 예측이 틀린 데이터에 대해서는 가중치를 부여해 다음번 학습기가 학습할 때에는 이전에 예측이 틀린 데이터에 대해서는 보다 높은 정확도로 예측할 수 있도록 해줍니다.
  • GBM은 뛰어난 예측 성능을 가졌지만, 수행 시간이 너무 오래 걸린다는 단점이 있습니다.
  • XGBoost는 많은 캐글 경연대회에서 우승을 위한 알고리즘으로 불리면서 명성을 쌓아 왔습니다.
  • LightGBM은 XGBoost보다 빠른 학습 수행 시간에도 불구하고 XGBoost에 버금가는 예측 성능을 보유하고 있습니다.

01. 분류(Classification)의 개요

지도학습은 레이블(Label) -> 기대가 되는 값, 예측되는 값
즉, 명시적인 정답이 있는 데이터가 주어진 상태에서 학습하는 머신러닝 방식.

ㅋ.png

즉, 기존 데이터가 어떤 레이블에 속하는지 패턴을 알고리즘으로 인지한 뒤에 새롭게 관측된 데이터에 대한 레이블을 판별하는 것이다.

분류는 다양한 머신러닝 알고리즘으로 구현할 수 있습니다.

  • 나이브 베이즈 : 베이즈 통계와 생성 모델에 기반
  • 로지스틱 회귀 : 독립변수와 종속변수의 선형 관계성에 기반
  • 결정 트리 : 데이터 균일도에 따른 규칙 기반
  • 서포트 벡터 머신 : 개별 클래스 간의 최대 분류 마진을 효과적으로 찾아줌
  • 신경망 : 심층 연결 기반
  • 앙상블 : 서로 같거나 다른 머신러닝 알고리즘을 결합

이번 장에서는 이 다양한 알고리즘 중에서 앙상블 방법을 집중적으로 다루게 됩니다.
앙상블은 분류에서 가장 각광을 받는 방법 중 하나이다.

앙상블은 일반적으로 배깅부스팅 방식으로 나뉘게 됩니다.

  • 배깅

    • 랜덤 포레스트 : 뛰어난 예측 성능, 상대적으로 빠른 수행 시간, 유연성 등 -> 분석가가 애용하는 알고리즘
  • 부스팅

    • 그래디언트 부스팅 : 뛰어난 예측성능을 가지고 있지만 수행시간이 너무 오래 걸리는 단점으로 최적화 모델 튜닝이 어려웠다. but. XGBoost(eXtra Gradient Boost)와 LightGBM 등 기존 그래디언트 부스팅의 예측 성능을 한 단계 발전과 수행 시간 단축으로 정형 데이터 분류 영역에서 가장 활용도가 높은 알고리즘으로 자리 잡음.

2. 결정 트리

1. 결정 트리 모델 특징

  • 데이터에 있는 규칙을 학습을 통해 트리 기반의 분류 규칙을 만든다.
  • 일반적으로 if/else 기반으로 나타내는데 스무고개 게임처럼 if/else를 반복하며 분류
  • 장점
    1. 균일도를 기반으로 하기 때무에 쉽고 직관적이다.
    2. 룰이 매우 명확하여 규칙노드와 리프 노드가 만들어지는 기준을 파악할 수 있다.
      → 정보의 균일도만 신경쓰면 되기 때문에 사적 가공이 많이 필요하지 않다.
  • 단점
    • 과적합으로 알고리즘 성능이 떨어질 수 있다.피처가 많고 균일도가 다양하게 존재할수록 트리의 깊이가 커지고 복잡해질 수 밖에 없다.(학습 데이터를 기반으로 정확도를 올리기 위해 계속 조건을 추가하기 때문에 깊이가 깊어지고 복잡한 모델이되어 새로운 상황에 대한 예측력이 떨어진다.)
  • 결정 트리 구조
    • 루트노드 : 트리 구조가 시작되는 곳
    • 규칙노드 : 규칙조건이 되는 것
    • 리프노드 : 결정된 클래스 값(더 이상 자식 노드가 없는 것)
    • 서브트리 : 새로운 규칙 조건마다 생성

ㅋㅋ.png

  • 규칙의 기준은 순수도를 가장 높여줄 수 있는 쪽을 선택해 진행한다. – 최대한 균일한 데이터 세트를 구성할 수 있도록 분할하는 것이 필요

ㅋㅋㅋ.png

  • 그림에서 균일한 데이터 세트의 순서는 1 → 2 → 3 이다.

항아리에 10개의 구슬이 들어 있고 그 중 절반가량이 빨간색이고 나머지 절반가량이 파란색인 경우 그 구슬들의 집합은 빨간색과 파란색이 섞여 있어 불순한 것으로 간주한다 (항아리 2). 반면에 항아리에 빨간색 또는 파란색 구슬만 있는 경우 그 구슬 집합은 완벽하게 순수한 것으로 간주한다.

결정노드는 정보 균일도가 높은 데이터를 먼저 선택하도록 규칙을 만든다. 즉 데이터를 나눌 수 있는 조건을 찾아 자식 노드를 만들며 내려가게 된다. 이때 정보의 균일도를 측정하는 대표적인 방법은 엔트로피를 이용한 정보 이득 지수와 지니계수가 있다.

  • 엔트로피, 정보이득지수, 지니 계수
    • 엔트로피 : 주어진 데이터 집합의 혼잡도 (<->균일도) (값이 작을수록 데이터가 균일)
    • 정보이득지수 : 1- 엔트로피 지수 (정보 이득이 높은 속성을 기준으로 분할)
    • 지니계수: 0이 가장 평등하고 1로 갈수록 불평등하다. (지니 계수가 낮을수록 데이터 균일도가 높다. 지니계수가 낮은 속성을 기준으로 분할)

2. 결정 트리 파라미터

  • min_samples_split(분리될 노드에 최소 자료 수)
    • 노드를 분할하기 위한 최소한의 샘플 데이터 수
    • 과적합 제어 용도
    • 디폴트 2 (작게 설정할수록 과적합 가능성 증가)
  • min_samples_leaf(잎사귀 노드에 최소 자료 수)
    • 말단 노드가 되기 위한 최소한의 샘플 데이터 수
    • 과적합 제어 용도
    • 비대칭적 데이터(하나의 피처가 과도하게 많은 경우) 에는 특정 클래스의 데이터가 극도로 작을 수 있으므로 작게 설정
  • max_features
    • 최적의 분할을 위해 고려할 최대 피처 개수
    • 디폴트 = none (데이터 세트의 모든 피처를 사용해 분할)
    • max_features = sqrt/ auto : √(전체 피처 개수)
    • log = log2(전체 피처 개수) 선정
    • Int형으로 지정하면 대상 피처의 개수, float형으로 지정하면 전체 피처 중 대상 피처의 퍼센트
  • max _depth
    • 트리의 최대 깊이
    • 디폴트 = None (완벽하게 클래스 결정값이 될 때까지 깊이를 계속 키우며 분할 하거나 노드가 가지는 데이터의 개수가 min_sample_split보다 작아질때까지 계속 깊이를증가 시킨다.)
    • 깊이가 깊어지면 과적합하므로 주의

3. 결정 트리 모델 시각화

결정트리는 Graphviz 패키지 이용하여 시각화 할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
import warnings
warnings.filterwarnings('ignore')

# DecisionTree Classifier 생성
dt_clf = DecisionTreeClassifier(random_state=156)

# 붓꽃 데이터를 로딩하고, 학습과 테스트 데이터 셋으로 분리
iris_data = load_iris()
X_train , X_test , y_train , y_test = train_test_split(iris_data.data, iris_data.target,
test_size=0.2, random_state=11)

# DecisionTreeClassifer 학습.
dt_clf.fit(X_train , y_train)
DecisionTreeClassifier(random_state=156)

test_size = test데이터의 비율

random_state = 난수 값 고정

1
2
3
4
5
6
7
8
9
10
11
12
from sklearn.tree import export_graphviz

# export_graphviz()의 호출 결과로 out_file로 지정된 tree.dot 파일을 생성함.
export_graphviz(dt_clf, out_file="tree.dot", class_names=iris_data.target_names , \
feature_names = iris_data.feature_names, impurity=True, filled=True)

import graphviz

# 위에서 생성된 tree.dot 파일을 Graphviz 읽어서 Jupyter Notebook상에서 시각화
with open("tree.dot") as f:
dot_graph = f.read()
graphviz.Source(dot_graph)

svg

Impurity가 True일 경우 각 노드의 불순물을 표시한다.

filledTrue일 경우 분류를 위한 다수 클래스, 회귀 값의 극한 또는 다중 출력의 노드 순도를 나타내기 위해 노드를 색칠한다.

1
2
3
4
5
6
7
8
9
from sklearn.tree import export_graphviz

export_graphviz(dt_clf, out_file='tree1.dot', class_names=iris_data.target_names,
feature_names=iris_data.feature_names, impurity=False, filled=True)

import graphviz
with open('tree1.dot') as f:
dot_graph = f.read()
graphviz.Source(dot_graph)

svg

두 그림을 비교해보면 impurity=False일때 gini 계수가 사라진 것을 알 수 있다.

- Graphviz로 시각화된 결정 트리 지표 설명**

ㅋㅋㅋㅋ.png

이 그림은 직관적으로 리프 노드브랜치 노드를 볼 수 있다. 자식노드가 없는 리프 노드에서 최종적으로 어떤 클래스인지 결정된다. 그 노드에 도달하기까지의 조건을 만족한다면 거기서 이 꽃이 어떤 종류의 붓꽃인지 예측하는 것이다.

1)리프노드가 되는 조건?

  • 최종 데이터가 오직 “하나의” 클래스 값으로 구성
  • 하이퍼 파라미터 조건 충족(뒤에서 자세히 설명)

ㅋㅋㅋㅋㅋ.png
브랜치 노드 안에는 맨 위와 같이 5개의 지표가 존재하고, 리프 노드에는 주황색 노드와 같이 4개의 지표가 존재한다.

맨 위의 노드 구성을 예시로 설명해보겠다.

  1. petal length(꽃잎 길이) ≤ 2.45
    • 자식노드를 만들기 위한 규칙조건 (없으면 리프노드라는 증거!)
    • 꽃잎 길이가 2.45 이하인 데이터와 초과인 데이터로 분류하겠다는 의미
  2. gini = 0.666
    • 지니계수
    • 아래의 value 분포도를 통해 계산
    • 높을수록 데이터 불균일
  3. samples = 120
    • 아직 아무런 조건으로도 나뉘어있지 않은 상황
    • 세 품종 데이터 전체 갯수가 120개
  4. value = [38, 41, 41]
    • 품종 순서대로 Setosa 38개, Versicolor 41개, Virginica41개라는 의미
    • 리스트 안의 값을 모두 더하면 samples의 개수와 같음
  5. class = versicolor
    • 하위 노드를 가질경우 value에서 가장 많은 값의 품종선택
    • 여기서는 versicolor = virginica 41으로 같으므로 인덱스 작은것 선택

노드 색깔이 의미하는 것

붓꽃 데이터의 레이블 값을 의미, 색깔이 짙어질수록 지니계수가 낮아 데이터가 균일하고 해당 레이블에 속하는 샘플이 많다는 의미이다.

0 : Setosa(주황) 1 : Versicolor(초록) 2 : Virginica(보라)

위의 주황색 노드에서 전체 41개의 샘플이 모두 Setosa이므로 매우 균일한 상태라고 볼 수 있다.

2) 하이퍼 파라미터 변경에 따른 트리 변화

너무 복잡한 트리가 되면 과적합이 발생하여 오히려 예측성능이 낮아질 수 있다. 이를 제어하는 파라미터를 알아보자.

  1. max_depth
  2. min_samples_split
  3. min_samples_leaf

max_depth : 너무 깊어지지 않도록!

적절히 설정하는 것이 중요할 것이다. 너무 간단해도, 너무 복잡해도 성능이 좋지 않을 것이기 때문이다.

min_samples_split : 현재 sample 갯수를 보고 자식을 만들지 말지 결정!

기본 설정값은 2이다. 현재 sample이 2개이고, 두 개가 다른 품종이라면 자식노드를 만들어 분할해야한다. 하지만 이 파라미터를 4로 변경하면 샘플이 다른 품종이 섞인 3개여도 분할을 멈추고 리프노드가 된다. 따라서 자연스레 트리 깊이도 줄어든다.

min_samples_leaf : sample갯수가 이 값 이하가 되도록 부모 규칙 변경!

리프노드가 될 수 있는 조건은 샘플수의 디폴트가 1이다. 즉, 샘플이 하나 남아야 리프노드로 인정되는 것이다. 그래야 한 품종만 남는다.

하지만 그러면 트리의 리프노드는 너무 많아지고 더 복잡해진다. 따라서 이 파라미터로 리프노드의 엄격했던 기준을 완화시켜주도록 한다.

자식 샘플 갯수가 4여도 리프노드로 만들어줄게! 그러니까 규칙을 좀만 널널하게 해줘~

이런 식이다.

3) 어떤 속성이 좋은 모델을 만들까?

사이킷런에는 규칙을 정하는 데 있어 피처(속성)의 중요한 역할 지표를 DecisionTreeclassifierr 객체의 featureimportances 속성으로 제공한다

반환되는 ndarray값은 피처 순서대로 중요도가 할당되어있다. 막대그래프로 시각화하면 더욱 직관적으로 확인 가능하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
import seaborn as sns
import numpy as np
%matplotlib inline

# feature importance 추출
print("Feature importances:/n{0}". format(np.round(dt_clf.feature_importances_, 3)))

# feature별 importance 매핑
for name, value in zip(iris_data.feature_names, dt_clf.feature_importances_):
print('{0}:{1:3f}'.format(name, value))

# feature importance를 column 별로 시각화하기
sns.barplot(x=dt_clf.feature_importances_, y=iris_data.feature_names)
Feature importances:/n[0.025 0.    0.555 0.42 ]
sepal length (cm):0.025005
sepal width (cm):0.000000
petal length (cm):0.554903
petal width (cm):0.420092





<matplotlib.axes._subplots.AxesSubplot at 0x7f25ee2f30f0>

png

4. 결정 트리 과적합(Overfitting)

청일점, 홍일점처럼 일부 이상치 데이터까지 분류하기 위해서 분할이 자주 일어나면 결정 기준 경계도 많아지게 된다. 이렇게 복잡한 모델은 학습 데이터셋의 특성과 약간만 다른형태의 데이터 셋이 들어오면 제대로 예측할 수 없다.

1
2
3
4
5
6
7
8
9
10
11
12
from sklearn.datasets import make_classification
import matplotlib.pyplot as plt
%matplotlib inline

plt.title("3 Class values with 2 Features Sample data creation")

# 2차원 시각화를 위해서 feature는 2개, 결정값 클래스는 3가지 유형의 classification 샘플 데이터 생성.
X_features, y_labels = make_classification(n_features=2, n_redundant=0, n_informative=2,
n_classes=3, n_clusters_per_class=1,random_state=0)

# plot 형태로 2개의 feature로 2차원 좌표 시각화, 각 클래스값은 다른 색깔로 표시됨.
plt.scatter(X_features[:, 0], X_features[:, 1], marker='o', c=y_labels, s=25, cmap='rainbow', edgecolor='k')
<matplotlib.collections.PathCollection at 0x7f25edd95f60>

png

과적합 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import numpy as np

# Classifier의 Decision Boundary를 시각화 하는 함수
def visualize_boundary(model, X, y):
fig,ax = plt.subplots()

# 학습 데이타 scatter plot으로 나타내기
ax.scatter(X[:, 0], X[:, 1], c=y, s=25, cmap='rainbow', edgecolor='k',
clim=(y.min(), y.max()), zorder=3)
ax.axis('tight')
ax.axis('off')
xlim_start , xlim_end = ax.get_xlim()
ylim_start , ylim_end = ax.get_ylim()

# 호출 파라미터로 들어온 training 데이타로 model 학습 .
model.fit(X, y)
# meshgrid 형태인 모든 좌표값으로 예측 수행.
xx, yy = np.meshgrid(np.linspace(xlim_start,xlim_end, num=200),np.linspace(ylim_start,ylim_end, num=200))
Z = model.predict(np.c_[xx.ravel(), yy.ravel()]).reshape(xx.shape)

# contourf() 를 이용하여 class boundary 를 visualization 수행.
n_classes = len(np.unique(y))
contours = ax.contourf(xx, yy, Z, alpha=0.3,
levels=np.arange(n_classes + 1) - 0.5,
cmap='rainbow', clim=(y.min(), y.max()),
zorder=1)
1
2
3
4
5
from sklearn.tree import DecisionTreeClassifier

# 특정한 트리 생성 제약없는 결정 트리의 Decsion Boundary 시각화.
dt_clf = DecisionTreeClassifier().fit(X_features, y_labels)
visualize_boundary(dt_clf, X_features, y_labels)

png

1
2
3
# min_samples_leaf=6 으로 트리 생성 조건을 제약한 Decision Boundary 시각화
dt_clf = DecisionTreeClassifier( min_samples_leaf=6).fit(X_features, y_labels)
visualize_boundary(dt_clf, X_features, y_labels)

png

이상치에 크게 반응하지 않으면서 좀 더 일반화된 분류 규칙에 따라 분류됐음을 알 수 있다.

5. 결정 트리 실습 - 사용자 행동 인식 데이터 세트**

Ch04-02. 결정트리 실습 - 사용자 행동 인식 데이터 세트

  • 주제 : 결정 트리를 이용해 사용자 행동 인식 데이터 셋에 대한 예측 분류 수행
  • 데이터 셋 : UCI 머신러닝 리포지토리에서 제공, 해당 데이터는 30명에게 스마트폰 센서를 장착한 뒤 사람의 동작과 관련된 여러가지 피처를 수집한 데이터임.
1
2
3
4
5
6
7
8
9
10
from google.colab import drive # 패키지 불러오기 
from os.path import join

ROOT = "/content/drive" # 드라이브 기본 경로
print(ROOT) # print content of ROOT (Optional)
drive.mount(ROOT) # 드라이브 기본 경로 Mount

MY_GOOGLE_DRIVE_PATH = 'My Drive/human_activity/' # 프로젝트 경로
PROJECT_PATH = join(ROOT, MY_GOOGLE_DRIVE_PATH) # 프로젝트 경로
print(PROJECT_PATH)
/content/drive
Mounted at /content/drive
/content/drive/My Drive/human_activity/
1
%cd "{PROJECT_PATH}"
/content/drive/My Drive/human_activity
1
2
3
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
1
2
3
4
5
6
# features.txt 파일에는 피처 이름 index와 피처명이 공백으로 분리되어 있음. 이를 DataFrame으로 로드.
feature_name_df = pd.read_csv('/content/drive/My Drive/human_activity/features.txt', sep='\s+', header=None, names=['column_index', 'column_name'])

# 피처명 index를 제거하고, 피처명만 리스트 객체로 생성한 뒤 샘플로 10개만 추출
feature_name = feature_name_df.iloc[:, 1].values.tolist()
print('전체 피처명에서 10개만 추출:', feature_name[:10])
전체 피처명에서 10개만 추출: ['tBodyAcc-mean()-X', 'tBodyAcc-mean()-Y', 'tBodyAcc-mean()-Z', 'tBodyAcc-std()-X', 'tBodyAcc-std()-Y', 'tBodyAcc-std()-Z', 'tBodyAcc-mad()-X', 'tBodyAcc-mad()-Y', 'tBodyAcc-mad()-Z', 'tBodyAcc-max()-X']
1
2
3
4
# 중복된 피처명 확인
feature_dup_df=feature_name_df.groupby('column_name').count()
print(feature_dup_df[feature_dup_df['column_index']>1].count())
feature_dup_df[feature_dup_df['column_index']>1].head()
column_index    42
dtype: int64

column_index
column_name
fBodyAcc-bandsEnergy()-1,16 3
fBodyAcc-bandsEnergy()-1,24 3
fBodyAcc-bandsEnergy()-1,8 3
fBodyAcc-bandsEnergy()-17,24 3
fBodyAcc-bandsEnergy()-17,32 3
1
2
3
4
5
6
7
8
# 중복된 피처명에 대해서는 원본 피처명에 _1 또는 _2를 추가로 부여해 새로운 피처명을 가지는 DataFrame반환
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

train/test data load

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import pandas as pd

def get_human_dataset():

# 각 데이터 파일은 공백으로 분리되어 있으므로 read_csv에서 공백 문자를 sep으로 할당.
feature_name_df=pd.read_csv('/content/drive/My Drive/human_activity/features.txt', sep='\s+',
header=None, names=['column_index','column_name'])

# 중복된 피처명을 수정하는 get_new_feature_name_df()를 이용, 신규 피처명 DataFrame 생성
new_feature_name_df = get_new_feature_name_df(feature_name_df)

# DataFrame에 피처명을 칼럼으로 부여하기 위해 리스트 객체로 다시 변환
feature_name=new_feature_name_df.iloc[:, 1].values.tolist()

# train 피처 데이터셋과 test 피처 데이터를 DataFrame으로 로딩. 칼럼명은 feature_name 적용
X_train=pd.read_csv('/content/drive/My Drive/human_activity/train/X_train.txt',sep='\s+',names=feature_name)
X_test=pd.read_csv('/content/drive/My Drive/human_activity/test/X_test.txt',sep='\s+',names=feature_name)

# train label과 test label 데이터를 DataFrame으로 로딩하고 칼럼명은 action으로 부여
y_train=pd.read_csv('/content/drive/My Drive/human_activity/train/y_train.txt',sep='\s+',header=None,names=['action'])
y_test=pd.read_csv('/content/drive/My Drive/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()
1
2
print('## 학습 피처 데이터셋 info()')
print(X_train.info())
## 학습 피처 데이터셋 info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 7352 entries, 0 to 7351
Columns: 561 entries, tBodyAcc-mean()-X to angle(Z,gravityMean)
dtypes: float64(561)
memory usage: 31.5 MB
None
1
print(y_train['action'].value_counts())
6    1407
5    1374
4    1286
1    1226
2    1073
3     986
Name: action, dtype: int64

레이블 값은 1, 2, 3, 4, 5, 6의 6개 값이고 이는 움직임 위치와 관련된 속성이다. 분포도는 특정 값으로 왜곡되지 않고 비교적 고르게 분포되어있다.

DecisionTreeClassifier

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
import time

# 수행 시간 측정을 위함. 시작 시간 설정.
start_time = time.time()

# 예제 반복 시 마다 동일한 예측 결과 도출을 위해 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('결정 트리 예측 정확도 : {0:.4f}'.format(accuracy))

# DecisionTreeClassifier의 하이퍼 파라미터 추출
print('DecisionTreeClassifie의 기본 하이퍼 파라미터:\n', dt_clf.get_params())
print("결정 트리 수행 시간: {0:.1f} 초 ".format(time.time() - start_time))
결정 트리 예측 정확도 : 0.8548
DecisionTreeClassifie의 기본 하이퍼 파라미터:
 {'ccp_alpha': 0.0, 'class_weight': None, 'criterion': 'gini', 'max_depth': None, 'max_features': None, 'max_leaf_nodes': None, 'min_impurity_decrease': 0.0, 'min_impurity_split': None, 'min_samples_leaf': 1, 'min_samples_split': 2, 'min_weight_fraction_leaf': 0.0, 'presort': 'deprecated', 'random_state': 156, 'splitter': 'best'}
결정 트리 수행 시간: 5.2 초 

Tree Depth에 따른 예측 성능 변화
아래 예제 테스트 시간이 2분이니 주의 요망

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from sklearn.model_selection import GridSearchCV
import time

# 수행 시간 측정을 위함. 시작 시간 설정.
start_time = time.time()

params = { 'max_depth' : [6, 8, 10, 12, 16, 20, 24]}

# 5개의 cv세트로 7개의 max_depth 테스트
grid_cv = GridSearchCV(dt_clf, param_grid=params, scoring='accuracy', cv=5, verbose=1)
grid_cv.fit(X_train, y_train)
print('GridSearchCV 최고 평균 정확도 수치 : {0:.4f}'.format(grid_cv.best_score_))
print('GridSearchCV 최적 하이퍼 파라미터: ',grid_cv.best_params_)
print("GridSearchCV 수행 시간: {0:.1f} 초 ".format(time.time() - start_time))
Fitting 5 folds for each of 7 candidates, totalling 35 fits


[Parallel(n_jobs=1)]: Using backend SequentialBackend with 1 concurrent workers.
[Parallel(n_jobs=1)]: Done  35 out of  35 | elapsed:  1.9min finished


GridSearchCV 최고 평균 정확도 수치 : 0.8513
GridSearchCV 최적 하이퍼 파라미터:  {'max_depth': 16}
GridSearchCV 수행 시간: 116.1 초 

max_depth가 16일때 5개의 폴드 세트의 최고 평균 정확도가 약 85.13%로 도출되었다. 그렇다면 max_depth값에 따라 어떻게 예측 성능이 변화했는지 GridSearchCV객체의 cvresult 속성을 통해서 살펴보도록 할 것이다.

1
2
3
4
5
# GridSearchCV객체의 cv_result_ 속성을 DataFrame으로 생성.
cv_results_df = pd.DataFrame(grid_cv.cv_results_)

# max_depth 파라미터 값과 그때의 테스트 셋의 정확도 수치 추출
cv_results_df[['param_max_depth', 'mean_test_score']]

param_max_depth mean_test_score
0 6 0.850791
1 8 0.851069
2 10 0.851209
3 12 0.844135
4 16 0.851344
5 20 0.850800
6 24 0.849440
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import time

# 수행 시간 측정을 위함. 시작 시간 설정.
start_time = time.time()

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('max_depth = {0} 정확도: {1:.4f}'.format(depth , accuracy))
print("수행 시간: {0:.1f} 초 ".format(time.time() - start_time))
max_depth = 6 정확도: 0.8558
max_depth = 8 정확도: 0.8707
max_depth = 10 정확도: 0.8673
max_depth = 12 정확도: 0.8646
max_depth = 16 정확도: 0.8575
max_depth = 20 정확도: 0.8548
max_depth = 24 정확도: 0.8548
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# max_depth와 min_samples_split을 같이 변경하면서 성능 튜닝
import time

# 수행 시간 측정을 위함. 시작 시간 설정.
start_time = time.time()

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('GridSearchCV 최고 평균 정확도 수치 : {0:.4f}'.format(grid_cv.best_score_))
print('GridSearchCV 최적 하이퍼 파라미터: ',grid_cv.best_params_)
print("GridSearchCV 수행 시간: {0:.1f} 초 ".format(time.time() - start_time))
Fitting 5 folds for each of 8 candidates, totalling 40 fits


[Parallel(n_jobs=1)]: Using backend SequentialBackend with 1 concurrent workers.
[Parallel(n_jobs=1)]: Done  40 out of  40 | elapsed:  2.2min finished


GridSearchCV 최고 평균 정확도 수치 : 0.8549
GridSearchCV 최적 하이퍼 파라미터:  {'max_depth': 8, 'min_samples_split': 16}
1
2
3
4
best_df_clf = grid_cv.best_estimator_
pred1 = best_df_clf.predict(X_test)
accuracy = accuracy_score(y_test , pred1)
print('결정 트리 예측 정확도:{0:.4f}'.format(accuracy))
결정 트리 예측 정확도:0.8717
1
2
3
4
5
6
7
8
9
10
11
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 )
# 중요도값 순으로 Series를 정렬
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()

png

03. 앙상블 학습

1. 앙상블 학습 개요

  • Ensemble Learning : 여러 개의 분류기(Classifier)를 생성하고 그 예측을 결합함으로써 보다 정확한 최종 예측을 도축하는 기법
    • 마치 집단 지성으로 어려운 문제를 쉽게 해결하는 것처럼

ㅋㅋㅋㅋㅋ.png

  • 목표: 다양한 분류기의 예측 결과를 결합 -> 단일 분류기보다 신뢰성이 높은 예측값 얻는 것
  • 대부분의 정형 데이터 분류 시 뛰어난 성능 보임 (이미지, 영상, 음성 등의 비정형 데이터의 분류는 딥러닝이 더 뛰어난 성능)
  • 대표적인 앙상블 알고리즘: Random Forest, Gradient Boosting

기존의 Gradient Boosting을 뛰어넘는 새로운 알고리즘 개발

  1. XGBoost
  2. LightGBM (XGBoost보다 훨씬 빠른 수행 속도)
  3. Stacking (여러 가지 모델의 결과를 기반으로 메타 모델을 수립)
  • Ensemble Learning 유형: 전통적으로 Voting, Bagging, Boosting 3가지 + Stacking을 포함한 다양한 앙상블 방법
    • Bagging, Boosting은 결정 트리 알고리즘 기반, Voting과 Stacking은 서로 다른 알고리즘을 기반(Ensemble의 한 개념)
  1. Voting과 Bagging : 여러 개의 분류기가 투표를 통해 최종 예측 결과를 결정하는 방식

Voting은 서로 다른 알고리즘을 가진 분류기 결합, Bagging은 각각의 분류기가 모두 같은 유형의 알고리즘 기반이지만, 데이터 샘플링을 서로 다르게 가져가면서 학습을 수행해 Voting을 수행하는 것이다. (대표적인 Bagging: Random Forest)

  • Voting : 다른 ML 알고리즘이 같은 데이터 세트에 대해 학습하고 예측한 결과를 가지고 보팅을 통해 최종 예측 결과 선정

ㅎ.png

  • Bagging : 단일 ML 알고리즘이 Bootstrapping 방식으로 샘플링된 데이터 세트에 대해서 학습을 통해 개별적인 예측을 수행한 결과를 보팅을 통해 최종 예측 결과 선정
    ㅎㅎ.png

    • Bootstrapping 분할 방식: 개별 분류기에게 데이터를 샘플링해서 추출하는 방식, 여러 개의 데이터 세트를 중첩되게 분리하는 것 (Voting 방식과 다름)
    • 교차 검증이 데이터 세트 간에 중첩 허용하지 않는 것과 다르게, Bagging은 중첩 허용

ㅎㅎㅎ.png

5 size만큼 Bootstrap 실행 (중복 허용, 복원 추출 개념)

ㅎㅎㅎㅎ.png

각 분류기 k개만큼 데이터를 샘플링 -> 개별적인 예측을 보팅(결과 값 평균)을 통해 최종 예측 결과 선정

ㅎㅎㅎㅎㅎ.png

OOB error(Out-of-Bag error): 학습데이터에서 미 추출된 데이터에 대해 각각의 분류기가 예측하고 Error율 계산해서 평균 냄 -> 학습데이터 내에서 미 추출된 데이터를 검증 데이터로 써서 검증데이터에 대한 성능지표를 계산할 수 있는 장점

  • Bagging과 Tree의 차이점
    • Tree: 쉽고 직관적인 분류 기준을 가지고 있지만, Low Bias(정답과 예측값의 거리), High Variance(모델별 예측값 간의 거리) => overfitting 발생
    • Bagging: 위와 같은 문제를 해결하기 위해 모델이 예측한 값의 평균을 사용하여 bias를 유지하고 Variance를 감소, 학습데이터의 noise에 강건해짐, 모형해석의 어려움(단점)

결정 트리 알고리즘의 장점은 그대로 취하고 단점은 보완하면서 bias-variance trade-off의 효과를 극대화할 수 있음

  1. Boosting : 여러 개의 분류기가 순차적으로 학습을 수행하되, 앞에서 학습한 분류기가 예측이 틀린 데이터에 대해서 올바르게 예측할 수 있도록 다음 분류기에게 가중치(weight)를 부여하면서 학습과 예측 진행
  2. Stacking : 여러 가지 다른 모델의 예측 결괏값을 다시 학습 데이터로 만들어서 다른 모델(메타 모델)로 재학습시켜 결과를 예측

2. 보팅 유형: 하드 보팅(Hard Voting), 소프트 보팅(Soft Voting)**

  1. 하드 보팅 : 예측한 결괏값들 중 다수의 분류기가 결정한 예측값을 최종 보팅 결괏값으로 선정 (다수결 원칙과 비슷)
  2. 소프트 보팅 : 분류기들의 레이블 값 결정 확률을 모두 더하고 이를 평균해서 이들 중 확률이 가장 높은 레이블 값을 최종 보팅 결괏값으로 선정 (일반적인 보팅 방법)
    1.png

일반적으로 하드 보팅보다는 소프트 보팅이 예측 성능이 좋아서 더 많이 사용됨.

3. 보팅 분류기(Voting Classifier)

  1. 사이킷런은 보팅 방식의 앙상블을 구현한 보팅 분류기 클래스를 제공하고 있다.
  2. 암 데이터로 위스콘신 데이터 세트를 생성
1
2
3
4
5
6
7
8
9
10
11
12
13
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)

mean radius mean texture mean perimeter mean area mean smoothness mean compactness mean concavity mean concave points mean symmetry mean fractal dimension radius error texture error perimeter error area error smoothness error compactness error concavity error concave points error symmetry error fractal dimension error worst radius worst texture worst perimeter worst area worst smoothness worst compactness worst concavity worst concave points worst symmetry worst fractal dimension
0 17.99 10.38 122.8 1001.0 0.11840 0.27760 0.3001 0.14710 0.2419 0.07871 1.0950 0.9053 8.589 153.40 0.006399 0.04904 0.05373 0.01587 0.03003 0.006193 25.38 17.33 184.6 2019.0 0.1622 0.6656 0.7119 0.2654 0.4601 0.11890
1 20.57 17.77 132.9 1326.0 0.08474 0.07864 0.0869 0.07017 0.1812 0.05667 0.5435 0.7339 3.398 74.08 0.005225 0.01308 0.01860 0.01340 0.01389 0.003532 24.99 23.41 158.8 1956.0 0.1238 0.1866 0.2416 0.1860 0.2750 0.08902
2 19.69 21.25 130.0 1203.0 0.10960 0.15990 0.1974 0.12790 0.2069 0.05999 0.7456 0.7869 4.585 94.03 0.006150 0.04006 0.03832 0.02058 0.02250 0.004571 23.57 25.53 152.5 1709.0 0.1444 0.4245 0.4504 0.2430 0.3613 0.08758
  • 로지스틱 회귀와 KNN을 기반하여 소프트 보팅 방식으로 새롭게 보팅 분류기를 만들어 보았다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 개별 모델은 로지스틱 회귀와 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)))
Voting 분류기 정확도: 0.9474
LogisticRegression 정확도: 0.9386
KNeighborsClassifier 정확도: 0.9386

04. 랜덤 포레스트

1. 랜덤 포레스트의 개요 및 실습

  • Bagging의 대표적인 알고리즘 Random Forest; 비교적 빠른 수행 속도 + 높은 예측 성능

2.png

  • 여러 개의 결정 트리 분류기가 전체 데이터에서 bagging 방식으로 각자의 데이터를 샘플링 -> 개별적으로 학습 수행 후 최종적으로 모든 분류기가 voting을 통해 예측 결정3.png
  • (X+Y)의 분산이 X와 Y 각각의 분산을 더한 것보다 더 크기 때문에 Bagging Model 자체의 분산이 커질 수 있음
  • 공분산이 0이면, 두 변수는 서로 독립적인 관계
  • 따라서 Random Forest는 기본 Bagging과 다르게 데이터뿐만 아니라, 변수도 random하게 뽑아서 다양한 모델 만듦 (각 분류기간의 공분산을 줄이는 게 목표)
  • 모델의 분산을 줄여 일반적으로 Bagging보다 성능이 좋음
  • 뽑을 변수의 수는 hyper parameter(일반적으로 √p 사용, p는 변수 개수)
  • 개별적인 분류기의 기반 알고리즘은 결정트리이지만, 개별 트리가 학습하는 데이터세트는 전체 데이터에서 일부가 중첩되게 샘플링된 데이터 세트 (Bootstrapping 방식)
    • Bagging: bootstrap aggregating의 줄임말
  • 랜덤 포레스트의 Subset 데이터는 Bootstrapping 방식으로 데이터가 임의로 만들어짐

4.png

  • Subset 데이터의 건수는 전체 데이터의 건수와 동일하지만, 개별 데이터가 중첩되어 만들어짐
  • 데이터가 중첩된 개별 데이터 세트에 결정 트리 분류기를 각각 적용 ⇒ 랜덤 포레스트!
  • 정리
    배깅: 같은 알고리즘으로 여러 개의 분류기를 만들어서 보팅으로 최종 결정하는 알고리즘.

배깅의 대표적인 알고리즘은 랜덤포레스트

랜덤포레스트의 장점 : 1. 앙상블 알고리즘 중 비교적 빠른 수행 속도를 가지고 있음

  1. 다양한 영역에서 높은 예측 성능
  2. 결정 트리의 쉽고 직관적인 장점 그대로 가지고 있음
    5.png

2. 랜덤 포레스트 하이퍼 파라미터 및 튜닝

하이퍼 파라미터란, 일반적으로 머신러닝에서 어떠한 임의의 모델을 학습시킬때, 사람이 직접 튜닝 (설정) 해주어야하는 변수를 말한다.

RandomForest의 단점:

  1. 하이퍼 파라미터가 너무 많다
  2. 시간이 많이 소모된다
  3. 예측 성능이 크게 향상되는 경우가 많지 않다

트리 기반 자체의 하이퍼 파라미터가 원래 많고, 배깅, 부스팅, 학습, 정규화를 위한 하이퍼 파라미터까지 추가되므로 많을 수 밖에 없다.

코드: n_estimators: 결정 트리의 개수 지정/ max_features는 결정트리에 max_features 파라미터와 같음(최적의 분할을 위해 고려할 최대 피처갯수). 기본이 sqrt(전체 피처갯수) / max_depth(트리의 최대 깊이 규정), min_samples_leaf(말단 노드가 되기 위한 최소한의 샘플 데이터 수): 과적합 개선

아래 예제는 5분 이상 소요 주의 요망

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# GridSearchCV 로 교차검증 및 하이퍼 파라미터 튜닝

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_))
1
2
3
4
5
6
7
# 튜닝된 하이퍼 파라미터로 재 학습 및 예측/평가

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)))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 개별 feature들의 중요도 시각화

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()

05. GBM(Gradient Boosting Machine)

1. GBM의 개요 및 실습

부스팅 알고리즘: 순차적으로 학습-예측하면서 잘못 예측한 데이터에 가중치 부여를 하고, 오류를 개선해 나가면서 학습하는 방식

에이다 부스트, GBM 과의 차이: GBM은 가중치 업데이트를 경사하강법을 이용한다.
경사하강법은 “반복 수행을 통해 오류를 최소화할 수 있도록 가중치의 업데이트 값을 도출하는 기법” 정도로만 이해하고 5장(회귀)에서 더 알아보도록 한다.

경사하강법

6.png

보통 GBM이 랜덤 포레스트 보다는 예측 성능이 뛰어나다.
BUT, 수행시간 문제는 GBM이 극복해야할 중요한 과제.

아래 코드 수행시간 3분 이상

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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))

2. GBM 하이퍼 파라미터 및 튜닝

n_estimators: 결정트리갯수/ max_depth:. Max_features: 위와 같이

loss: 경사 하강법에서 사용할 비용 함수 지정

learning_rate: weak learner가 순차적으로 오류값을 보정해 나가는데 적용하는 계수. 범위는 0과 1사이 , 기본값은 0.1, 너무 작은 값: 예측성능은 높아지지만 속도 느림. 너무 큰 값: 예측성능이 떨어지지만 속도는 빠름/

subsample: 학 습에 사용하는 데이터 샘플링 비율 (ex. 0.5 면 학습데이터 50%)

장점: 과적합에도 강한 뛰어난 예측 성능을 가진 알고리즘

단점: 수행시간이 오래걸림

아래 코드 수행시간 1시간 이상

1
2
3
4
5
6
7
8
9
10
from sklearn.model_selection import GridSearchCV

params = {
'n_estimators':[100, 500],
'learning_rate' : [ 0.05, 0.1]
}
grid_cv = GridSearchCV(gb_clf , param_grid=params , cv=2 ,verbose=1)
grid_cv.fit(X_train , y_train)
print('최적 하이퍼 파라미터:\n', grid_cv.best_params_)
print('최고 예측 정확도: {0:.4f}'.format(grid_cv.best_score_))
1
2
3
4
# 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))

06. XGBoost(eXtra Gradient Boost)

1. XGBoost 개요

트리 기반의 앙상블 학습7.png

1
2
3
import xgboost

print(xgboost.__version__)
1.2.1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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.head(3)

mean radius mean texture mean perimeter mean area mean smoothness mean compactness mean concavity mean concave points mean symmetry mean fractal dimension ... worst texture worst perimeter worst area worst smoothness worst compactness worst concavity worst concave points worst symmetry worst fractal dimension target
0 17.99 10.38 122.8 1001.0 0.11840 0.27760 0.3001 0.14710 0.2419 0.07871 ... 17.33 184.6 2019.0 0.1622 0.6656 0.7119 0.2654 0.4601 0.11890 0
1 20.57 17.77 132.9 1326.0 0.08474 0.07864 0.0869 0.07017 0.1812 0.05667 ... 23.41 158.8 1956.0 0.1238 0.1866 0.2416 0.1860 0.2750 0.08902 0
2 19.69 21.25 130.0 1203.0 0.10960 0.15990 0.1974 0.12790 0.2069 0.05999 ... 25.53 152.5 1709.0 0.1444 0.4245 0.4504 0.2430 0.3613 0.08758 0

3 rows × 31 columns

1
2
print(dataset.target_names)
print(cancer_df['target'].value_counts())
['malignant' 'benign']
1    357
0    212
Name: target, dtype: int64
1
2
3
4
# 전체 데이터 중 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)
(455, 30) (114, 30)
1
2
dtrain = xgb.DMatrix(data=X_train , label=y_train)
dtest = xgb.DMatrix(data=X_test , label=y_test)
1
2
3
4
5
6
7
params = { 'max_depth':3,
'eta': 0.1,
'objective':'binary:logistic',
'eval_metric':'logloss',
'early_stoppings':100
}
num_rounds = 400
1
2
3
4
# 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 )
[10:03:48] WARNING: C:\Users\Administrator\workspace\xgboost-win64_release_1.2.0\src\learner.cc:516: 
Parameters: { early_stoppings } might not be used.

  This may not be accurate due to some parameters are only used in language bindings but
  passed down to XGBoost core.  Or some parameters are not used but slip through this
  verification. Please open an issue if you find above cases.


[0]    train-logloss:0.60969    eval-logloss:0.61352
[1]    train-logloss:0.54080    eval-logloss:0.54784
[2]    train-logloss:0.48375    eval-logloss:0.49425
[3]    train-logloss:0.43446    eval-logloss:0.44799
[4]    train-logloss:0.39055    eval-logloss:0.40911
[5]    train-logloss:0.35414    eval-logloss:0.37498
[6]    train-logloss:0.32122    eval-logloss:0.34571
[7]    train-logloss:0.29259    eval-logloss:0.32053
[8]    train-logloss:0.26747    eval-logloss:0.29721
[9]    train-logloss:0.24515    eval-logloss:0.27799
[10]    train-logloss:0.22569    eval-logloss:0.26030
[11]    train-logloss:0.20794    eval-logloss:0.24604
[12]    train-logloss:0.19218    eval-logloss:0.23156
[13]    train-logloss:0.17792    eval-logloss:0.22005
[14]    train-logloss:0.16522    eval-logloss:0.20857
[15]    train-logloss:0.15362    eval-logloss:0.19999
[16]    train-logloss:0.14333    eval-logloss:0.19012
[17]    train-logloss:0.13398    eval-logloss:0.18182
[18]    train-logloss:0.12560    eval-logloss:0.17473
[19]    train-logloss:0.11729    eval-logloss:0.16766
[20]    train-logloss:0.10969    eval-logloss:0.15820
[21]    train-logloss:0.10297    eval-logloss:0.15473
[22]    train-logloss:0.09707    eval-logloss:0.14895
[23]    train-logloss:0.09143    eval-logloss:0.14331
[24]    train-logloss:0.08633    eval-logloss:0.13634
[25]    train-logloss:0.08131    eval-logloss:0.13278
[26]    train-logloss:0.07686    eval-logloss:0.12791
[27]    train-logloss:0.07284    eval-logloss:0.12526
[28]    train-logloss:0.06925    eval-logloss:0.11998
[29]    train-logloss:0.06555    eval-logloss:0.11641
[30]    train-logloss:0.06241    eval-logloss:0.11450
[31]    train-logloss:0.05959    eval-logloss:0.11257
[32]    train-logloss:0.05710    eval-logloss:0.11154
[33]    train-logloss:0.05441    eval-logloss:0.10868
[34]    train-logloss:0.05204    eval-logloss:0.10668
[35]    train-logloss:0.04975    eval-logloss:0.10421
[36]    train-logloss:0.04775    eval-logloss:0.10296
[37]    train-logloss:0.04585    eval-logloss:0.10058
[38]    train-logloss:0.04401    eval-logloss:0.09868
[39]    train-logloss:0.04226    eval-logloss:0.09644
[40]    train-logloss:0.04065    eval-logloss:0.09587
[41]    train-logloss:0.03913    eval-logloss:0.09424
[42]    train-logloss:0.03738    eval-logloss:0.09471
[43]    train-logloss:0.03611    eval-logloss:0.09427
[44]    train-logloss:0.03494    eval-logloss:0.09389
[45]    train-logloss:0.03365    eval-logloss:0.09418
[46]    train-logloss:0.03253    eval-logloss:0.09402
[47]    train-logloss:0.03148    eval-logloss:0.09236
[48]    train-logloss:0.03039    eval-logloss:0.09301
[49]    train-logloss:0.02947    eval-logloss:0.09127
[50]    train-logloss:0.02855    eval-logloss:0.09005
[51]    train-logloss:0.02753    eval-logloss:0.08961
[52]    train-logloss:0.02655    eval-logloss:0.08958
[53]    train-logloss:0.02568    eval-logloss:0.09070
[54]    train-logloss:0.02500    eval-logloss:0.08958
[55]    train-logloss:0.02430    eval-logloss:0.09036
[56]    train-logloss:0.02357    eval-logloss:0.09159
[57]    train-logloss:0.02296    eval-logloss:0.09153
[58]    train-logloss:0.02249    eval-logloss:0.09199
[59]    train-logloss:0.02185    eval-logloss:0.09195
[60]    train-logloss:0.02132    eval-logloss:0.09194
[61]    train-logloss:0.02079    eval-logloss:0.09146
[62]    train-logloss:0.02022    eval-logloss:0.09031
[63]    train-logloss:0.01970    eval-logloss:0.08941
[64]    train-logloss:0.01918    eval-logloss:0.08972
[65]    train-logloss:0.01872    eval-logloss:0.08974
[66]    train-logloss:0.01833    eval-logloss:0.08962
[67]    train-logloss:0.01787    eval-logloss:0.08873
[68]    train-logloss:0.01760    eval-logloss:0.08862
[69]    train-logloss:0.01724    eval-logloss:0.08974
[70]    train-logloss:0.01688    eval-logloss:0.08998
[71]    train-logloss:0.01664    eval-logloss:0.08978
[72]    train-logloss:0.01629    eval-logloss:0.08958
[73]    train-logloss:0.01598    eval-logloss:0.08953
[74]    train-logloss:0.01566    eval-logloss:0.08875
[75]    train-logloss:0.01539    eval-logloss:0.08860
[76]    train-logloss:0.01515    eval-logloss:0.08812
[77]    train-logloss:0.01488    eval-logloss:0.08840
[78]    train-logloss:0.01464    eval-logloss:0.08874
[79]    train-logloss:0.01449    eval-logloss:0.08815
[80]    train-logloss:0.01418    eval-logloss:0.08758
[81]    train-logloss:0.01401    eval-logloss:0.08741
[82]    train-logloss:0.01377    eval-logloss:0.08849
[83]    train-logloss:0.01357    eval-logloss:0.08858
[84]    train-logloss:0.01341    eval-logloss:0.08807
[85]    train-logloss:0.01325    eval-logloss:0.08764
[86]    train-logloss:0.01311    eval-logloss:0.08742
[87]    train-logloss:0.01293    eval-logloss:0.08761
[88]    train-logloss:0.01271    eval-logloss:0.08707
[89]    train-logloss:0.01254    eval-logloss:0.08727
[90]    train-logloss:0.01235    eval-logloss:0.08716
[91]    train-logloss:0.01223    eval-logloss:0.08696
[92]    train-logloss:0.01206    eval-logloss:0.08717
[93]    train-logloss:0.01193    eval-logloss:0.08707
[94]    train-logloss:0.01182    eval-logloss:0.08659
[95]    train-logloss:0.01165    eval-logloss:0.08612
[96]    train-logloss:0.01148    eval-logloss:0.08714
[97]    train-logloss:0.01136    eval-logloss:0.08677
[98]    train-logloss:0.01124    eval-logloss:0.08669
[99]    train-logloss:0.01113    eval-logloss:0.08655
[100]    train-logloss:0.01100    eval-logloss:0.08650
[101]    train-logloss:0.01085    eval-logloss:0.08641
[102]    train-logloss:0.01076    eval-logloss:0.08629
[103]    train-logloss:0.01064    eval-logloss:0.08626
[104]    train-logloss:0.01050    eval-logloss:0.08683
[105]    train-logloss:0.01039    eval-logloss:0.08677
[106]    train-logloss:0.01030    eval-logloss:0.08732
[107]    train-logloss:0.01020    eval-logloss:0.08730
[108]    train-logloss:0.01007    eval-logloss:0.08728
[109]    train-logloss:0.01000    eval-logloss:0.08730
[110]    train-logloss:0.00991    eval-logloss:0.08729
[111]    train-logloss:0.00980    eval-logloss:0.08800
[112]    train-logloss:0.00971    eval-logloss:0.08794
[113]    train-logloss:0.00963    eval-logloss:0.08784
[114]    train-logloss:0.00956    eval-logloss:0.08807
[115]    train-logloss:0.00948    eval-logloss:0.08765
[116]    train-logloss:0.00942    eval-logloss:0.08730
[117]    train-logloss:0.00931    eval-logloss:0.08780
[118]    train-logloss:0.00923    eval-logloss:0.08775
[119]    train-logloss:0.00915    eval-logloss:0.08768
[120]    train-logloss:0.00912    eval-logloss:0.08763
[121]    train-logloss:0.00902    eval-logloss:0.08757
[122]    train-logloss:0.00897    eval-logloss:0.08755
[123]    train-logloss:0.00890    eval-logloss:0.08716
[124]    train-logloss:0.00884    eval-logloss:0.08767
[125]    train-logloss:0.00880    eval-logloss:0.08774
[126]    train-logloss:0.00871    eval-logloss:0.08828
[127]    train-logloss:0.00864    eval-logloss:0.08831
[128]    train-logloss:0.00861    eval-logloss:0.08827
[129]    train-logloss:0.00856    eval-logloss:0.08789
[130]    train-logloss:0.00846    eval-logloss:0.08886
[131]    train-logloss:0.00842    eval-logloss:0.08868
[132]    train-logloss:0.00839    eval-logloss:0.08874
[133]    train-logloss:0.00830    eval-logloss:0.08922
[134]    train-logloss:0.00827    eval-logloss:0.08918
[135]    train-logloss:0.00822    eval-logloss:0.08882
[136]    train-logloss:0.00816    eval-logloss:0.08851
[137]    train-logloss:0.00808    eval-logloss:0.08848
[138]    train-logloss:0.00805    eval-logloss:0.08839
[139]    train-logloss:0.00797    eval-logloss:0.08915
[140]    train-logloss:0.00795    eval-logloss:0.08911
[141]    train-logloss:0.00790    eval-logloss:0.08876
[142]    train-logloss:0.00787    eval-logloss:0.08868
[143]    train-logloss:0.00785    eval-logloss:0.08839
[144]    train-logloss:0.00778    eval-logloss:0.08927
[145]    train-logloss:0.00775    eval-logloss:0.08924
[146]    train-logloss:0.00773    eval-logloss:0.08914
[147]    train-logloss:0.00769    eval-logloss:0.08891
[148]    train-logloss:0.00762    eval-logloss:0.08942
[149]    train-logloss:0.00760    eval-logloss:0.08939
[150]    train-logloss:0.00758    eval-logloss:0.08911
[151]    train-logloss:0.00752    eval-logloss:0.08873
[152]    train-logloss:0.00750    eval-logloss:0.08872
[153]    train-logloss:0.00746    eval-logloss:0.08848
[154]    train-logloss:0.00741    eval-logloss:0.08847
[155]    train-logloss:0.00739    eval-logloss:0.08854
[156]    train-logloss:0.00737    eval-logloss:0.08852
[157]    train-logloss:0.00734    eval-logloss:0.08855
[158]    train-logloss:0.00732    eval-logloss:0.08828
[159]    train-logloss:0.00730    eval-logloss:0.08830
[160]    train-logloss:0.00728    eval-logloss:0.08828
[161]    train-logloss:0.00726    eval-logloss:0.08801
[162]    train-logloss:0.00724    eval-logloss:0.08776
[163]    train-logloss:0.00722    eval-logloss:0.08778
[164]    train-logloss:0.00720    eval-logloss:0.08778
[165]    train-logloss:0.00718    eval-logloss:0.08752
[166]    train-logloss:0.00716    eval-logloss:0.08754
[167]    train-logloss:0.00714    eval-logloss:0.08764
[168]    train-logloss:0.00712    eval-logloss:0.08739
[169]    train-logloss:0.00710    eval-logloss:0.08738
[170]    train-logloss:0.00708    eval-logloss:0.08730
[171]    train-logloss:0.00707    eval-logloss:0.08737
[172]    train-logloss:0.00705    eval-logloss:0.08740
[173]    train-logloss:0.00703    eval-logloss:0.08739
[174]    train-logloss:0.00701    eval-logloss:0.08713
[175]    train-logloss:0.00699    eval-logloss:0.08716
[176]    train-logloss:0.00697    eval-logloss:0.08696
[177]    train-logloss:0.00696    eval-logloss:0.08705
[178]    train-logloss:0.00694    eval-logloss:0.08697
[179]    train-logloss:0.00692    eval-logloss:0.08697
[180]    train-logloss:0.00690    eval-logloss:0.08704
[181]    train-logloss:0.00688    eval-logloss:0.08680
[182]    train-logloss:0.00687    eval-logloss:0.08683
[183]    train-logloss:0.00685    eval-logloss:0.08658
[184]    train-logloss:0.00683    eval-logloss:0.08659
[185]    train-logloss:0.00681    eval-logloss:0.08661
[186]    train-logloss:0.00680    eval-logloss:0.08637
[187]    train-logloss:0.00678    eval-logloss:0.08637
[188]    train-logloss:0.00676    eval-logloss:0.08630
[189]    train-logloss:0.00675    eval-logloss:0.08610
[190]    train-logloss:0.00673    eval-logloss:0.08602
[191]    train-logloss:0.00671    eval-logloss:0.08605
[192]    train-logloss:0.00670    eval-logloss:0.08615
[193]    train-logloss:0.00668    eval-logloss:0.08592
[194]    train-logloss:0.00667    eval-logloss:0.08592
[195]    train-logloss:0.00665    eval-logloss:0.08598
[196]    train-logloss:0.00663    eval-logloss:0.08601
[197]    train-logloss:0.00662    eval-logloss:0.08592
[198]    train-logloss:0.00660    eval-logloss:0.08585
[199]    train-logloss:0.00659    eval-logloss:0.08587
[200]    train-logloss:0.00657    eval-logloss:0.08589
[201]    train-logloss:0.00656    eval-logloss:0.08595
[202]    train-logloss:0.00654    eval-logloss:0.08573
[203]    train-logloss:0.00653    eval-logloss:0.08573
[204]    train-logloss:0.00651    eval-logloss:0.08575
[205]    train-logloss:0.00650    eval-logloss:0.08582
[206]    train-logloss:0.00648    eval-logloss:0.08584
[207]    train-logloss:0.00647    eval-logloss:0.08578
[208]    train-logloss:0.00645    eval-logloss:0.08569
[209]    train-logloss:0.00644    eval-logloss:0.08571
[210]    train-logloss:0.00643    eval-logloss:0.08581
[211]    train-logloss:0.00641    eval-logloss:0.08559
[212]    train-logloss:0.00640    eval-logloss:0.08580
[213]    train-logloss:0.00639    eval-logloss:0.08581
[214]    train-logloss:0.00637    eval-logloss:0.08574
[215]    train-logloss:0.00636    eval-logloss:0.08566
[216]    train-logloss:0.00634    eval-logloss:0.08584
[217]    train-logloss:0.00633    eval-logloss:0.08563
[218]    train-logloss:0.00632    eval-logloss:0.08573
[219]    train-logloss:0.00631    eval-logloss:0.08578
[220]    train-logloss:0.00629    eval-logloss:0.08579
[221]    train-logloss:0.00628    eval-logloss:0.08582
[222]    train-logloss:0.00627    eval-logloss:0.08576
[223]    train-logloss:0.00626    eval-logloss:0.08567
[224]    train-logloss:0.00624    eval-logloss:0.08586
[225]    train-logloss:0.00623    eval-logloss:0.08587
[226]    train-logloss:0.00622    eval-logloss:0.08593
[227]    train-logloss:0.00621    eval-logloss:0.08595
[228]    train-logloss:0.00619    eval-logloss:0.08587
[229]    train-logloss:0.00618    eval-logloss:0.08606
[230]    train-logloss:0.00617    eval-logloss:0.08600
[231]    train-logloss:0.00616    eval-logloss:0.08592
[232]    train-logloss:0.00615    eval-logloss:0.08610
[233]    train-logloss:0.00613    eval-logloss:0.08611
[234]    train-logloss:0.00612    eval-logloss:0.08617
[235]    train-logloss:0.00611    eval-logloss:0.08626
[236]    train-logloss:0.00610    eval-logloss:0.08629
[237]    train-logloss:0.00609    eval-logloss:0.08622
[238]    train-logloss:0.00608    eval-logloss:0.08639
[239]    train-logloss:0.00607    eval-logloss:0.08634
[240]    train-logloss:0.00606    eval-logloss:0.08618
[241]    train-logloss:0.00605    eval-logloss:0.08619
[242]    train-logloss:0.00604    eval-logloss:0.08625
[243]    train-logloss:0.00602    eval-logloss:0.08626
[244]    train-logloss:0.00601    eval-logloss:0.08629
[245]    train-logloss:0.00600    eval-logloss:0.08622
[246]    train-logloss:0.00599    eval-logloss:0.08640
[247]    train-logloss:0.00598    eval-logloss:0.08635
[248]    train-logloss:0.00597    eval-logloss:0.08628
[249]    train-logloss:0.00596    eval-logloss:0.08645
[250]    train-logloss:0.00595    eval-logloss:0.08629
[251]    train-logloss:0.00594    eval-logloss:0.08631
[252]    train-logloss:0.00593    eval-logloss:0.08636
[253]    train-logloss:0.00592    eval-logloss:0.08639
[254]    train-logloss:0.00591    eval-logloss:0.08649
[255]    train-logloss:0.00590    eval-logloss:0.08644
[256]    train-logloss:0.00589    eval-logloss:0.08629
[257]    train-logloss:0.00588    eval-logloss:0.08646
[258]    train-logloss:0.00587    eval-logloss:0.08639
[259]    train-logloss:0.00586    eval-logloss:0.08644
[260]    train-logloss:0.00585    eval-logloss:0.08646
[261]    train-logloss:0.00585    eval-logloss:0.08649
[262]    train-logloss:0.00584    eval-logloss:0.08644
[263]    train-logloss:0.00583    eval-logloss:0.08647
[264]    train-logloss:0.00582    eval-logloss:0.08632
[265]    train-logloss:0.00581    eval-logloss:0.08649
[266]    train-logloss:0.00580    eval-logloss:0.08654
[267]    train-logloss:0.00579    eval-logloss:0.08647
[268]    train-logloss:0.00578    eval-logloss:0.08650
[269]    train-logloss:0.00577    eval-logloss:0.08652
[270]    train-logloss:0.00576    eval-logloss:0.08669
[271]    train-logloss:0.00575    eval-logloss:0.08674
[272]    train-logloss:0.00575    eval-logloss:0.08683
[273]    train-logloss:0.00574    eval-logloss:0.08668
[274]    train-logloss:0.00573    eval-logloss:0.08664
[275]    train-logloss:0.00572    eval-logloss:0.08650
[276]    train-logloss:0.00571    eval-logloss:0.08636
[277]    train-logloss:0.00570    eval-logloss:0.08652
[278]    train-logloss:0.00570    eval-logloss:0.08657
[279]    train-logloss:0.00569    eval-logloss:0.08659
[280]    train-logloss:0.00568    eval-logloss:0.08668
[281]    train-logloss:0.00567    eval-logloss:0.08664
[282]    train-logloss:0.00566    eval-logloss:0.08650
[283]    train-logloss:0.00566    eval-logloss:0.08636
[284]    train-logloss:0.00565    eval-logloss:0.08640
[285]    train-logloss:0.00564    eval-logloss:0.08643
[286]    train-logloss:0.00563    eval-logloss:0.08646
[287]    train-logloss:0.00562    eval-logloss:0.08650
[288]    train-logloss:0.00562    eval-logloss:0.08637
[289]    train-logloss:0.00561    eval-logloss:0.08646
[290]    train-logloss:0.00560    eval-logloss:0.08645
[291]    train-logloss:0.00559    eval-logloss:0.08632
[292]    train-logloss:0.00558    eval-logloss:0.08628
[293]    train-logloss:0.00558    eval-logloss:0.08615
[294]    train-logloss:0.00557    eval-logloss:0.08620
[295]    train-logloss:0.00556    eval-logloss:0.08622
[296]    train-logloss:0.00556    eval-logloss:0.08631
[297]    train-logloss:0.00555    eval-logloss:0.08618
[298]    train-logloss:0.00554    eval-logloss:0.08626
[299]    train-logloss:0.00553    eval-logloss:0.08613
[300]    train-logloss:0.00553    eval-logloss:0.08618
[301]    train-logloss:0.00552    eval-logloss:0.08605
[302]    train-logloss:0.00551    eval-logloss:0.08602
[303]    train-logloss:0.00551    eval-logloss:0.08610
[304]    train-logloss:0.00550    eval-logloss:0.08598
[305]    train-logloss:0.00549    eval-logloss:0.08606
[306]    train-logloss:0.00548    eval-logloss:0.08597
[307]    train-logloss:0.00548    eval-logloss:0.08600
[308]    train-logloss:0.00547    eval-logloss:0.08600
[309]    train-logloss:0.00546    eval-logloss:0.08588
[310]    train-logloss:0.00546    eval-logloss:0.08592
[311]    train-logloss:0.00545    eval-logloss:0.08595
[312]    train-logloss:0.00544    eval-logloss:0.08603
[313]    train-logloss:0.00544    eval-logloss:0.08611
[314]    train-logloss:0.00543    eval-logloss:0.08599
[315]    train-logloss:0.00542    eval-logloss:0.08590
[316]    train-logloss:0.00542    eval-logloss:0.08595
[317]    train-logloss:0.00541    eval-logloss:0.08598
[318]    train-logloss:0.00540    eval-logloss:0.08600
[319]    train-logloss:0.00540    eval-logloss:0.08588
[320]    train-logloss:0.00539    eval-logloss:0.08597
[321]    train-logloss:0.00539    eval-logloss:0.08605
[322]    train-logloss:0.00538    eval-logloss:0.08609
[323]    train-logloss:0.00537    eval-logloss:0.08598
[324]    train-logloss:0.00537    eval-logloss:0.08598
[325]    train-logloss:0.00536    eval-logloss:0.08590
[326]    train-logloss:0.00535    eval-logloss:0.08578
[327]    train-logloss:0.00535    eval-logloss:0.08586
[328]    train-logloss:0.00534    eval-logloss:0.08594
[329]    train-logloss:0.00534    eval-logloss:0.08582
[330]    train-logloss:0.00533    eval-logloss:0.08587
[331]    train-logloss:0.00532    eval-logloss:0.08589
[332]    train-logloss:0.00532    eval-logloss:0.08592
[333]    train-logloss:0.00531    eval-logloss:0.08584
[334]    train-logloss:0.00531    eval-logloss:0.08574
[335]    train-logloss:0.00530    eval-logloss:0.08582
[336]    train-logloss:0.00529    eval-logloss:0.08589
[337]    train-logloss:0.00529    eval-logloss:0.08594
[338]    train-logloss:0.00528    eval-logloss:0.08583
[339]    train-logloss:0.00528    eval-logloss:0.08591
[340]    train-logloss:0.00527    eval-logloss:0.08583
[341]    train-logloss:0.00526    eval-logloss:0.08573
[342]    train-logloss:0.00526    eval-logloss:0.08568
[343]    train-logloss:0.00525    eval-logloss:0.08572
[344]    train-logloss:0.00525    eval-logloss:0.08580
[345]    train-logloss:0.00524    eval-logloss:0.08582
[346]    train-logloss:0.00524    eval-logloss:0.08571
[347]    train-logloss:0.00523    eval-logloss:0.08579
[348]    train-logloss:0.00523    eval-logloss:0.08583
[349]    train-logloss:0.00522    eval-logloss:0.08573
[350]    train-logloss:0.00522    eval-logloss:0.08566
[351]    train-logloss:0.00521    eval-logloss:0.08573
[352]    train-logloss:0.00521    eval-logloss:0.08581
[353]    train-logloss:0.00520    eval-logloss:0.08571
[354]    train-logloss:0.00519    eval-logloss:0.08566
[355]    train-logloss:0.00519    eval-logloss:0.08570
[356]    train-logloss:0.00518    eval-logloss:0.08563
[357]    train-logloss:0.00518    eval-logloss:0.08553
[358]    train-logloss:0.00517    eval-logloss:0.08560
[359]    train-logloss:0.00517    eval-logloss:0.08568
[360]    train-logloss:0.00516    eval-logloss:0.08558
[361]    train-logloss:0.00516    eval-logloss:0.08560
[362]    train-logloss:0.00515    eval-logloss:0.08564
[363]    train-logloss:0.00515    eval-logloss:0.08571
[364]    train-logloss:0.00514    eval-logloss:0.08579
[365]    train-logloss:0.00514    eval-logloss:0.08569
[366]    train-logloss:0.00513    eval-logloss:0.08573
[367]    train-logloss:0.00513    eval-logloss:0.08568
[368]    train-logloss:0.00512    eval-logloss:0.08559
[369]    train-logloss:0.00512    eval-logloss:0.08552
[370]    train-logloss:0.00511    eval-logloss:0.08559
[371]    train-logloss:0.00511    eval-logloss:0.08550
[372]    train-logloss:0.00511    eval-logloss:0.08556
[373]    train-logloss:0.00510    eval-logloss:0.08561
[374]    train-logloss:0.00510    eval-logloss:0.08563
[375]    train-logloss:0.00509    eval-logloss:0.08553
[376]    train-logloss:0.00509    eval-logloss:0.08561
[377]    train-logloss:0.00508    eval-logloss:0.08567
[378]    train-logloss:0.00508    eval-logloss:0.08571
[379]    train-logloss:0.00507    eval-logloss:0.08562
[380]    train-logloss:0.00507    eval-logloss:0.08558
[381]    train-logloss:0.00506    eval-logloss:0.08562
[382]    train-logloss:0.00506    eval-logloss:0.08564
[383]    train-logloss:0.00505    eval-logloss:0.08555
[384]    train-logloss:0.00505    eval-logloss:0.08562
[385]    train-logloss:0.00505    eval-logloss:0.08562
[386]    train-logloss:0.00504    eval-logloss:0.08555
[387]    train-logloss:0.00504    eval-logloss:0.08546
[388]    train-logloss:0.00503    eval-logloss:0.08550
[389]    train-logloss:0.00503    eval-logloss:0.08546
[390]    train-logloss:0.00502    eval-logloss:0.08532
[391]    train-logloss:0.00502    eval-logloss:0.08539
[392]    train-logloss:0.00502    eval-logloss:0.08530
[393]    train-logloss:0.00501    eval-logloss:0.08537
[394]    train-logloss:0.00501    eval-logloss:0.08530
[395]    train-logloss:0.00500    eval-logloss:0.08537
[396]    train-logloss:0.00500    eval-logloss:0.08528
[397]    train-logloss:0.00500    eval-logloss:0.08532
[398]    train-logloss:0.00499    eval-logloss:0.08528
[399]    train-logloss:0.00499    eval-logloss:0.08520
1
2
3
4
5
6
7
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])
predict( ) 수행 결괏값을 10개만 표시, 예측 확률 값으로 표시됨
[0.95  0.003 0.9   0.086 0.993 1.    1.    0.999 0.998 0.   ]
예측값 10개만 표시: [1, 0, 1, 0, 1, 1, 1, 1, 1, 0]
1
get_clf_eval(y_test , preds, pred_probs)
---------------------------------------------------------------------------

NameError                                 Traceback (most recent call last)

<ipython-input-10-4ed56bef7ded> in <module>
----> 1 get_clf_eval(y_test , preds, pred_probs)


NameError: name 'get_clf_eval' is not defined
1
2
3
4
5
import matplotlib.pyplot as plt
%matplotlib inline

fig, ax = plt.subplots(figsize=(10, 12))
plot_importance(xgb_model, ax=ax)

2. 파이썬 래퍼 XGBoost 하이퍼 파라미터

파라미터의 유형

  1. 일반 파라미터 : 일반적으로 실행 시 스레드의 개수나 냐ㅣ둣 모드 등의 선택을위한 파라미터로서 디폴트 파라미터 값을 바꾸는 경우는 거의 없다.
  2. 부스터 파라미터 : 트리 최적화, 부스팅, regularization 등의 관련 파라미터들을 지칭.
  3. 학습 태스크 파라미터 : 학습 수행 시의 객체 함수, 평가를 위한 지표등을 설정하는 파라미터.

주요 일반 파라미터

  1. booster: gbtree(나무 기반 모델) or gblinear (회귀 기반 모델)선택, 디폴트는 gbtree
  2. silent : 출력 메시지를 나타내고 싶지 않을 경우 1로 설정 , 디폴트 = 0
  3. nthread : cpu의 실행 스레드 개수를 조정, 디폴트는 cpu의 전체 스레드를 다 사용하는 것.

주요 부스터 파라미터
8.png

regularization(정규화) : 과적합 모델을 일반화 해주는 기법

  • L1 Regularization (lasso): 기존 함수에 계수의 절댓값에 가중치를 곱한 것을 더해주는 것
  • L2 Regularization (ridge) : 기존함수에 계수의 제곱의 가중치를 곱한 것을 더해주는 것

학습 태스크 파라미터
9.png

  • log loss : 로그 우도에 -1을 곱한 값
    우도, 가능도(liklelihood) : 어떤 값이 관측 되었을때, 이것이 어던 확률 분포에서 온건지에대한 확률
  • ROC: 분류모델의 성능을 보여주는 그래프
  • AUC: ROC 곡선의 아래 면적 (1일때 가장 좋음)

3. 과적합 제어

과적합을 제어하는 방법

  • eta 값을 낮춘다. (0.01 ~ 0.1) → eta 값을 낮추면 num_round(n_estimator)를 반대로 높여주어야 한다.
  • max_depth 값을 낮춘다.
  • min_child_weight 값을 높인다.
  • gamma 값을 높인다.
  • subsample과 colsample_bytree를 낮춘다.

XGBoost는 자체적으로 교차 검증, 성능평가, 피처 중요도 등의 시각화 기능을 가지고 있다. 또한 다른 여러가지 성능을 향상시키는 기능을 가지고 있다.

Ex) Early Stopping 조기 중단 기능

GBM의 경우 n_estimators에 지정된 횟수만큼 학습을 끝까지 수행하지만, XGB의 경우 오류가 더 이상 개선되지 않으면 수행을 중지

Ex) n_estimators 를 200으로 설정하고, 조기 중단 파라미터 값을 50으로 설정하면, 1부터 200회까지 부스팅을 반복하다가 50회를 반복하는 동안 학습오류가 감소하지 않으면 더 이상 부스팅을 진행하지 않고 종료합니다.

07. LightGBM

1. LightGBM

XGBoost는 GBM보다는 빠르지만 여전히 학습시간이 오래 걸리고, 대용량 데이터로 학습 성능을 기대하려면 높은 병렬도로 학습을 진행해야 한다.

LightGBM의 장점

  • XGBoost보다 학습에 걸리는 시간이 훨씬 적다.

  • 메모리 사용량도 상대적으로 적다.

  • 기능상의 다양상도 XGBoost보다 약간 더 많다.

    ex. 카테고리형 피처의 자동 변환(원ㅡ핫 인코딩 사용하지않는)과 이에 따른 최적 분할이다.

  • XGBoost와 마찬가지로 대용량 데이터에 대한 뛰어난 성능 및 병렬컴퓨팅 기능을 제공하고 최근에는 추가로GPU까지 지원한다.

XGBoost의 장점은 계승하고 단점은 보완하는 방식으로 개발되었다.

LightGBM의 단점

  • 적은(10,000건 이하)의 데이터 셋에 적용할 경우 과적합 발생 쉽다.

    → 오버피팅에 더 강하지만 균형을 맞추기 위한 시간이 필요하다.

  • LightGBM : 리프 중심 트리 분할(Leaf Wise) 방식 사용

→ 트리의 균형을 맞추지 않고 최대 손실값(max delta loss)를 가지는 리프 노드를 지속적으로 분할하며 트리 깊이 확장하면서 트리의 깊이가 깊어지고 비대칭적 규칙 트리 생성한다.

→ 학습을 반복할 수록 균형트리분할방식보다 예측 오류 손실을 최소화할 수 있다.

패키지 설명

  1. 패키지명 : ‘lightgbm’
  2. 초기에 lightgbm은 독자적인 모듈로 설계되었으나 편의를 위해 scikit-learn wrapper로 호환이 가능하게 추가로 설계되었다. 패키지 내에 파이썬 래퍼, 사이킷런 래퍼 모두 내장하고있다. 사이킷런 래퍼 LightGBM클래스는 분류를 위한 LGBMClassifier클래스와 회귀를 위한 LGBMRegressor클래스이다.
  3. fit( ), predict( ) 기반의 학습 및 예측과 사이킷런이 제공하는 다양한 기능 활용이 가능하다.

→ 사이킷런에 익숙하다면 별도의 파이썬 래퍼 클래스를 사용하지 않아도 된다.

Light GBM은 leaf-wise 방식을 취하고 있기 때문에 수렴이 굉장히 빠르지만, 파라미터 조정에 실패할 경우 과적합을 초래할 수 있다.

2.LightGBM 설치

아나콘다로 쉽게 설치 가능하다. 단, 윈도우에 설치할 경우에는 Visual Studio Build tool 2015 이상이 먼저 설치돼 있어야한다. 그 후에 OS 터미널에서 conda명령어를 수행한다.

(윈도우10에서는 아나콘다 프롬프트→관리자 권한으로 실행→ conda명령어 수행)

1
conda install -c conda-forge lightgbm

도중에 나오는 Proceed([y]/n)에서 y를 입력하고 엔터를 누른다.

3. LightGBM 하이퍼 파라미터

XGBoost와 많은 부분이 유사하다. 주의할 점은 위의 트리분할 방식차이에 따라 이러한 트리 특성에 맞는 하이퍼 파라미터 설정이 필요하다는 점이다.(예를들어 max_depth가 매우 크게 가진다는 것)

주요파라미터
10.png

Learning Task 파라미터

objective : 최솟값을 가져야 할 손실함수 정의. 회귀, 다중클래스분류, 이진 분류인지에따라 지정

튜닝방안

num_leaves(트리의 최대 리프 개수)를 중심으로 min_data_in_leaf와 max_depth를 함께 조정하면서 복잡도를 줄이는 것이 기본 튜닝 방안

과적합을 방지하기 위해 num_leaves는 2^(max_depth)보다 작아야 한다. 예를 들어 max_depth가 7이기 때문에, 2^(max_depth)=128이 되는데, 이 때 num_leaves를 이보다 작은 70~80 정도로 설정하는 것이 낫다.

  1. learning_rate는 DOWN, n_estimators는 UP (물론 너무 키우면 과적합)

learning_rate는 후반부에 건드리는 것이 좋은데, 초반부터 너무 작은 학습률을 지정하면 효율이 크게 떨어질 수 있기 때문이다.

  1. reg_lambda, reg_alpha와 같은 regularization적용
  2. 학습데이터에 사용할 피처개수나 데이터 샘플링 레코드 개수 줄이기 위해 colsample_bytree, subsample 적용

4. 파이썬 래퍼 LightGBM vs 사이킷런 래퍼 XGBoost vs 사이킷런 래퍼 LightGBM하이퍼 파라미터

개요

  1. XGBoost가 사이킷런 규칙에 따라 자신의 하이퍼 파라미터 변경함
  2. LightGBM은 XGBoost와 기능이 많이 유사해서 사이킷런 래퍼의 파라미터를 XGBoost에 맞춰서 변경함

11.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# LightGBM의 파이썬 패키지인 lightgbm에서 LGBMClassifier 임포트
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]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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))
1
get_clf_eval(y_test, preds, pred_proba)
1
2
3
4
5
6
7
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)
Share