분류(Classification)

부천대 IOT 응용소프트웨어를 수강하는 학생들을 위해 강의내용을 정리했습니다. 강의내용은 모두 파이썬 머신러닝 완벽 가이드를 참고하였습니다.

분류(Classification)는 학습 데이터로 주어진 데이터 피처와 레이블값을 머신러닝 알고리즘으로 학습(패턴인식)하여 모델을 생성하고, 이렇게 생성된 모델에 새로운 데이터 값이 주어졌을때 미지의 레이블(분류) 값을 예측한다.

자주 사용되는 분류 알고리즘은 다음과 같다.

  • 나이브 베이즈(Naive Bayes)

  • 로지스틱회귀분석(Logistic Regression)

  • 규칙기반의 결정트리(Decision Tree)

  • 서포트 벡터 머신(Support Vector Machine)

  • 최소근접(Nearest Neighbor)

  • 심층연결 기반의 신경망(Neural Network)

  • 앙상블(Ensemble)

결정트리(Decision Tree)

결정트리(Decision Tree)는 쉽고 유연하게 적용될수 있는 분류 알고리즘이다. 또한 데이터의 스케일링이나 정규화 등 사전가공의 영향이 매우 적다. 하지만 예측 성능을 향상시키기 위해 복잡한 규칙 구조를 가져 과적합(overfitting)이 발생할 수 있어 예측 성능이 저하될 수 있다. 그렇지만 이러한 단점이 오히려 앙상블(Ensemble)에서 장점으로 작용이 된다.

앙상블은 예측성능이 낮 여러약한 학습기(weak learner)를 결합해 확률적으로 보완과 오류가 발생한 부분에 대한 가중치를 계속 업데이트해가며 예측 성능을 향상시키는데, 결정트리가 좋은 약한 학습기가 된다.

결정트리는 스무고개와 비슷하게 데이터에 있는 규칙을 학습을 통해 자동으로 찾아내는 트리(Tree) 기반 분류규칙을 만든다. 따라서 결정트리는 초기에 데이터를 어떤 기준을 바탕으로 분류규칙을 만드느냐에 따라 성능이 크게 달라지게 된다.

위 그림의 결정트리의 구조는 다음과 같다.

결정트리에서 가장 상위의 규칙노드인 루트노드(Root Node)는어떤 기준에 의해 분할을 한다.

그 기준으로 분할된 값이 적합하면 왼쪽노드의 규칙노드(Decision Node)로, 그렇지 않으면 오른쪽의 규칙노드로 이동을 한다. 예를들어 그 기준 값이 적합했다고 하자. 그러면 왼쪽 규칙노드로 이동하게 될 것이고, 그 규칙노드는 다시 또 어떤 기준에 의해 분할이 된다. 그 분할된 값이 균일하면 더이상 분할하지 않고 리프노드(Leaf Node)가 만들어지게 된다. 이렇게 새로운 규칙 조건에 의해 리프노드가 생성된 그을 서브트리(Sub tree)라고 부르며, 더이상 분류가 되지 않을 때까지 반복과정을 거치게 된다.

주의할 점은 트리의 깊이(depth)가 깊어질수록 결정 나무의 예측 성능이 떨어질 가능성이 높으니 적절한 깊이에서 자를 필요가 있다.

그렇다면 예측 성능이 높은 결정트리를 만들려면 어떻게 해야 할까?

데이터를 분류 시 최대한 많은 데이터 세트가 해당 분류에 속할 수 있도록 결정 노드(Decision Node)의 규칙이 정해져야 한다. 이를 위해 트리를 최대한 균일한 데이터 세트를 구성할 수 있도록 분할(split) 해야한다.

균일한 데이터란 무엇일까?

첫번 째 집합은 하마, 독수리, 너구리, 강아지, 코브라로 되어있다. 이 경우 데이터가 다양(동물의 종류)하지만 균일하지 못하다. 반면 두번 째 집합은 너구리와 강아지로만 구성되어있다. 첫번 째 집합에 비해 데이터가 다양하지는 않지만 균일다.

위 그림을 예시로 각 집합에서 내가 어떤 동물이 나올지 예측하는 상황이 주어졌다. 두번 째 집합에서는 데이터가 균일하여 너구리로 예측할 확률이 높다. 반면에 첫번 째 집합의 경우 데이터가 균일하지 않 어떤 동물이 나올지 예측하기 어렵다.

이와 같이 규노드는 정보 균일도가 높은 데이터 세트를 먼저 규칙 조건을 생성하여 분할한다.

즉 규칙노에서 균일도가 높은 데이터 셋으로 분할할 수록 조건에 맞는 서브 데이터 셋을 생성하고, 생성한 리프노드도 계속해서 정보 균일도가 높도록 조건으로 분할하게 된다. 이 과정을 통해 데이터를 예측한다. 이처럼 정보의 균일도를 측정하는 분리기준으로 지니계수와 엔트로피가 있다.

정보 균일도 측정기준

엔트로피( Entropy Index)

정보이득은 데이터의 집합 셋의 혼잡도를 의미하는 엔트로피를 기반으로 한다.

다양한 값들이 얽혀 있으면 엔트로피가 높고, 같은 값이 섞여 있으면 엔트로피가 낮다.

정보이득지수는 1에서 엔트로피를 뺀 값(1- 엔트로피지수)으로, 정보이득 지수로 분할을 정하는데, 정보이득이 높은 속성으로 분할한다.

지니계수(Gini Index)

경제학에서 불평등지수를 나타낼 때 사용하는 계수인 지니계수는 부모 노드(Parent Node)의 지니 지수를 가장 많이 감소시키는 설명변수와 분리 값을 기준으로 자식노드(Leaf Node)를 형성한다.

지니계수가 낮을수록 데이터 균일도가 높아지기에 지니계수가 낮은 속성을 기준으로 분할한다.

규칙노드생성 프로세스

결정 트리 규칙 노드 생성 프로세스는 다음과 같다.

데이터 집합의 모든 아이템이 같은 분류에 속하는지 확인한다.

같은 분류에 속하면 리프노드로 만들어 분류 결정한다. 그렇지 않으면 정보이득이나 지니계수를 이용해 데이터를 분할하는데 가장 좋은 속성을 찾고 해당 속성과 분할 기준으로 데이터를 분할해 규칙 브랜치 노드를 생성한다. 데이터의 집합 분류가 결정될 때 까지 이 일련의 과정을 계속 수행한다.

결정트리의 특징

결정트리의 장점은 쉽고 직관적이다. 피쳐 스케일링이나 정규화 등 사전 가공 영향도가 크지 않다.

하지만 단점으로는 과적합으로 인해 성능이 떨어지므로, 적절한 트리 크기를 사전에 제한이 필요하다.

결정트리 실습

Graphviz 설치

Graphviz를 이용해 파이썬 결정트리 모델을 시각화는 실습을 가져보자.

해당사이트에 접속하여 자신의 OS 환경에 맞는 버전을 다운로드한다.

다운로드한 다음 설치 시 수동으로 Path를 잡아줘야 한다.

설치가 완료되면, 파이썬에서 graphviz를 실행할 수 있도록 anaconda prompt를 관리자 권한으로 실행하여, pip install graphviz 를 입력한다.

다음 내PC -> 속성 -> 고급 시스템설정 ->환경변수 순으로 클릭하고, 사용자 변수에서 Path의 편집을 누른다.

환경변수편집창이 확인되면 새로만들기를 누르고, C:\Program Files\Graphviz\bin 를 넣어준다.

여기서 끝이 아니다. 한번 더 시스템 변수의 Path에서도 환경변수편집에서

C:\Program Files\Graphviz\bin\dot.exe 를 넣어준다.

마지막으로 관리자 권한으로 cmd를 열고 dot -version 을 입력하면 정상적으로 설치가 완료된 것을 확인할 수 있다.

주피터 노트북 파일을 실행하고 위의 파일을 실행해보길 바란다.

Graphviz로 시각화 결과 일부를 해석해보겠다.

첫번째 120개의 데이터 수에서 value 값을 보면 setosa 40 개, versicolor 37개, virginica가 43개로 , virginica가 제일 많았다 (class = virginica). petal with를 0.8 이하를 기준으로 규칙을 적용하여 분할을 시도 하였더니 sample수가 40개였고 그 중에 setosa가 40개 나왔다. 나머지는 각각 0개였으므로 더이상 분해할 필요가 없어 리프 노드가 결정 되었다. 그런데 False 노드는 아직 리프노드가 결정되지 않았다.

sample 수 80개 중 setosa를 제외한 나머지 versicolor가 37개, virginica가 43개였고, 이를 다시 petal length 4.75값을 기준으로 분할을 시도했다.

아래그림은 가지수를 조절한 것이니 파라미터를 바꿔보며 실행해보길 바란다.

결정트리 실습 2

이번에는 UCI에서 제공하는 사용자 행동 인식 데이터 세트를 가지고 결정 트리실습을 진행하겠다.

스마트폰 센서에서 수집된 피처 세트를 기반으로 결정트리를 이용해 사람의 동작을 예측하는 것이 목표다.

위의 사이트에 접속하여 Data Folder를 클릭하고 Dataset.zip 파일을 다운로드 한다.

다음 아래 권철민 저자분께서 파이썬머신러닝 완벽가이드에서 제공한 기본 코드 파일을 기반으로

각 코드가 어떤의미를 담고 있는지 주석처리하여 정리했다.

앙상블(Ensemble)

어떠한 난제를 접했을 때 집단지성을 발휘하여 해결했던 경험이 있을 것이다.이처럼 여러 명의 전문집단을 구성해 다양한 의견을 수렴하고 결정하듯이 앙상블은 여러개의 분류 모델을 생성하고 예측을 결합해 최종예측을 도출하는 기법을 말한다.

이러한 앙상블은 다양한 분류기의 예측결과를 결합함으로써 단일 분류기보다 신뢰성이 높은 예측값을 얻는다.

앙상블의 유형은 일반적으로 보팅(Voting), 배깅(Bagging), 부스팅(Boosting) 세 가지의 유형으로 나눌 수 있다. 이외에도 스태킹(Stacking)등의 기법이 있다.

보팅(Voting)은 서로다른 여러 분류모델이 투표를 통해 최종 예측 결과를 결정하는 방식이다.

배깅(Bagging)은 데이터 샘플링(Bootstrap) 을 통해 모델을 학습시키고 결과를 집계(Aggregating) 하는 방법으로 보팅과는 다르게 모두 같은 유형의 알고리즘 기반의 분류기를 사용한다. 대표적인 배깅의 알고리즘으로는 의사결정 트리(Decison Tree),랜덤포레스트(Random Forest)가 있다.

부스팅(Boosting)은 분류기가 예측이 틀린 데이터에 대해서 올바르게 예측할 수 있도록 다음 분류기에게 가중치(weight)를 부여하는 방법으로 대표적인 알고리즘으로 에이다 부스팅(Adaptive Boosting), 그래디언트 부스팅(Gradient Boosting), XGBoost, LightGBM 등이 있다.

정형 데이터의 분류나 회귀에서는 GBM(Gradient Boosting Machine) 부스팅 계열의 앙상블이 전반적으로 높은 예측성능을 나타낸다. 특히 XGBoost, LightGBM 은 Kaggle, Dacon 등 데이터분석경연대회에서 우수한 성적을 거둔 팀들이 많이 한 모델이다.

앙상블의 특징

앙상블의 특징은 단일모델의 약점을 다수의 모델들을 결합하여 보완했다.

그래서 비슷한 유형의 모델을 합치는것 보다는, 성능이 떨어지더라도 SVM이나 선형계열의 Classfier 같이 이질적인 유형의 모델을 섞어 앙상블을 만들면 전체적 성능을 높이는데 도움을 줄 수 있다.

이전시간에 배운 과적합 문제를 야기시킬 수 있는 결정트리 알고리즘들(ex) Random Forest, GBM)이 약한 학습기로 후보군으로 사용되어 이들을 보완하고 여러 분류모델과 결합하면 성능이 뛰어나다.

보팅의 유형

보팅은 하드보팅(Hard voting)소프트보팅(Soft voting)으로 나뉜다.

반장선거에서 반장 후보 여러명 중 투표를 통해 다수의 표를 받은 후보 1명이 반장이 선출되던 경험이 있을 것이다. 이와 유사하게 하드보팅각 분류기가 예측한 결과를 다수결로 최종 클래스(class)로 결정하는 방식이다. 아래 왼쪽그림을 보면 4개의 Classifier가 있다. 각각 Classifier가 예측을 1,2,1,1 로 했다면 다수결 원칙에 따라 1을 예측하는 것이다.

소프트 보팅각 분류기가 예측한 확률을 평균하여 결정하는 방식이다.

이때 predict_proba() 메소드를 이용해 클래스(class)별 확률을 결정한다.

아래 오른쪽 그림을 보면 각각의 clasifier가 class 1 일 확률을 0.7, 0.2, 0.8, 0.9 모두 더한 다음, classifier 갯수만큼 나눈다. 즉 평균을 구한 것인데 0.7+0.2+0.8+0.9 = 2.6 / 4 했을 때 0.65가 나온다. 이와 같은 방식으로 class2 일 확률을 구하면 0.35가 나온다. 따라서 class 1일 확률이 더 크므로 class1로 예측을 한다.

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

보팅 실습

권철민님의 파이썬머신러닝 완벽가이드에서 제공한 코드를 이용해 실습을 진행해 보겠다.

배깅(Bagging)-RandomForest

배깅의 대표적인 알고리즘인 랜덤포레스트는 앙상블 알고리즘 중에서 수행 속도가 빠르고, 다양한 영역에서 높은 예측 성능을 보이고 있다. 랜덤 포레스트는 여러 개의 결정 트리 분류기가 배깅 방식으로 데이터를 샘플링하여 개별적으로 학습을 수행 후 보팅을 통해 예측 결정을 한다.

랜덤포레스트 샘플링 방식

통계학에서는 여러 개의 작은 dataset을 임의로 만들어 개별 평균의 분포도를 측정하는 샘플링하는 부트스트래핑 방식이 있다. 랜덤 포레스트의 Subset 데이터는 이러한 부트스트래핑(bootstrapping) 방법을 이용해 여러 개의 dataset을 중첩하여 만들어지게 된다. 이렇게 만들어진 Subset의 데이터는 개별 데이터들의 중첩을 허용하고, 데이터 수는 전체 dataset의 수와 동일하게 만들어진다.

부스팅(Boosting)

부스팅 알고리즘은 여러 개의 약한 학습기(weak learner)를 순차적으로 학습/예측하며 잘못 예측한 데이터에 가중치 부여를 통해 오류를 개선해 나가면서 학습하는 방식이다. 순차적으로 진행하다보니 학습속도가 다른 알고리즘에 비해 느리다.

부스팅의 대표적인 구현은 AdaBoost(Adaptive boosting)과 그래디언트 부스트(Gradient Boost)가 있다. 에이다 부스트(AdaBoost)는 오류 데이터에 가중치를 부여하면서 부스팅을 수행하는 대표적인 알고리즘이다.

Adaboosting 작동원리

Yoav Freund & Robert Schapire가 제안한 Adaboosting에 대해 알아보겠다.

위 그림과 같이 "+"와 "-"로 구성된 피쳐 dataset을 가지고 +와 -를 분류하고자 한다.

첫번째 약 분류기에서 약한 학습기인, 결정 그루터기가 하나의 결정경계를 가지고 +와 -를 나누고 있다.

위쪽의 3개의 +들은 잘못 분류가 되어 가중치가 높아진다.

중간의 두번째 분류기에서는 오른쪽의 - 두 개만 분류가 되었고 결정경계를 기준으로 왼쪽의 -들은 잘못 분류가 되었다. 다시 가중치가 높아지고 학습된 3개의 Weight를 결합해서 + -를 구분할 수 있는 강 분류기를 만들었다. 즉 Weak Learner들의 앙상블을 결합하여 만들면 1개의 weak learner 분류기를 사용할 때보다 정확도가 높아진 것을 알 수 있다.

Gradient Boosting

GBM(Gradient Boosting Machine)은 AdaBoost과 같이 오차를 보정하고 예측기를 순차적으로 추가한다.

하지만 Adaboosting처럼 반복마다 샘플의 가중치를 수정하지 않고, 이전 예측기가 만든 잔여 오차(residual error)에 새로운 예측기를 학습시킨다. 다시말하면 가중치 업데이트를 경사하강법(Gradient Descent)을 이용하여 오차를 최소화할 수 있도록 가중치를 업데이트해간다.

XGBoost(eXtra Gradient Boost)

트리 기반의 앙상블 학습에서 가장 각광받고 있는 알고리즘 중 하나인 XGBoost를 소개하겠다.

Kaggle과 같은 경진대회에서 자주 쓰이는 XG부스트는 분류(XGBClassifier)뿐만 아니라 회귀(XGBRegressor)에서도 예측성능이 뛰어나고, Light GBM에 비해서는 느리지만 일반 GBM 대비 빠른 수행시간을 보장한다.

또한 일반 GBM 모델에 없었던 규제(Regularization)기능 탑재, 가지치기(Tree Pruning) 기능 등 추가되었고, 더이상 오류가 감소되지 않을 때 조기중단(Early Stopping) 자체 내장된 교차검증과, 결손값 자체처리가 가능하다.

XGBoost의 핵심 라이브러리는 초기에 C/C++로 작성되어있어 파이썬에 제공되는 XGBoost 패키지는 대부분 C/C++ 핵심 라이브러리를 호출한다. XGBoost 는 초기에 파이썬에서 사이킷런(Scikitlearn)과 호환되지 않는 독자적인 패키지였지만 시간이 지남에 따라 파이썬 기반의 머신러닝 사용자들이 사이킷런을 사용이 늘면서 XGBoost는 사이킷런과 호환 가능한 래퍼 클래스(Wrapper class)를 제공하고 있다.

XGBoost의 Early Stopping

신경망에서 많이쓰는 Early Stopping 기능은 XGBoost에서도 쓰이는데, 이 기능은 모델이 너무 학습(Train) 데이터에 몰두하여 구조가 복잡해지던가 혹은 Validation, Test 셋에서 과적합이 발생하는 경우를 사전에 방지하고자 특정반복횟수만큼 더이상 비용함수가 감소하지 않으면 반복횟수를 다 수행하지 않고 도중에 종료한다. 따라서 학습 시간을 단축 시킬 수 있고, 최적화 튜닝단계에서 적절하게 사용된다.

주의할 점이 있다면 반복 횟수를 너무 단축해버리면 예측 성능 최적화가 안되어 학습이 종료될 수 있다.

조기 중단 설정을 위한 주요 파라미터로는 최대 반복횟수를 지정하는 earlystoppingrounds, 반복 수행 시 사용하는 비용 평가지표인eval_metric, 평가 검증(validation) 을 수행하는 eval_set이 있다.

실습

먼저 anaconda prompt (관리자 모드)창을 열고, conda install -c anaconda py-xgboost 를 입력하면 XGBoost가 설치된다. 의존성(dependency)로 인해 설치시간이 길다.

그런데 설치 중에 나와같이 python 3.8 버전을 사용하는 유저는 오류가 생길 수 있다.

이럴경우 anaconda prompt에서 python -m pip install xgboost 를 입력하여 설치한다.

혹은 conda update -n base conda 명령어를 입력하여 업데이트를 진행 후 다시 py-xgboost를 설치한다.

설치가 완료되면 jupyternotebook을 실행하여 XGBoost 버전을 확인한다.

import xgboost

print(xgboost.version)

LightGBM

LightGBM은 XGBoost보다 더 빠른 학습과 예측을 수행하고, 더 작은 메모리를 사용한다.

카테고리형 피처의 자동 변환과 최적분화을 제공한다.

원-핫인코딩을 사용하지 않고도 카테고리형 피처를 최적으로 로 확하고 이에 따른 노드를 분할 수행한다.

이외에도 XGBoost와 같 대용량 데이터에 대한 뛰어난 예측 성능과 병렬 컴퓨팅 기능을 제공하며 최근에는 GPU까지 지원하고 있다.

XGBoost와 마찬가지로 LightGBM은 초창기 파이썬 래퍼용도로 개발됬으나 사이킷런 래펴용도 추가로 개발되었고 lightgbm 패키지 내에 분류와 회귀를 위한 래퍼 모듈을 모두 가지고 있다. LightGBM의 분류용으로는 LGBMClassifier 클래스가 있고, 회귀를 위한 LGBMRegressor 클래스가 있다.

LightGBM도 XGBoost와 동일하게 Early Stopping 기능이 있다.

LightGBM의 트리분할방식

LightGBM은 트리 분할방식이 기존 GBM과 다르다.

일반적으로 XGBoost를 포함한 일반 GBM은 오버피팅 및 depth를 최소화 시키기 위해 균형 트리분할(Level WIde)을 시도하지만, LightGBM은 분할 시도 시, 자식노드가 지속적으로 한방향으로 생성 되더라도 그 자식노드가 분류의 예측오류를 줄여줄 수 있다면 그 방향대로 흘러가 리프중심 트리분할(Leaf Wide)을 시도한다.

실습

LightGBM은 윈도우에서 설치할 시 Visual Studio Build tool 2015 이상이 설치되어있어야 한다.

그 다음, anacondaprompt에서 conda install -c conda-forge lightgbm 를 입력한다.

설치가 완료되면, jupyternotebook에서 LightGBM 버전을 확인한다.

import lightgbm

print(lightgbm.__version__)# 3.2.0

다음 아래 권철민님이 제공하신 LightGBM을 이용한 위스콘신 유방암 예측 예제파일을 다운받아 진행한다.

Stacking Model -Diagram

스태킹은 기존의 앙상블 방법과 같이 여러 분류 모델들을 결합해 예측을 시도하는 면에서 유사하지만, 스태킹은 개별 알고리즘으로 예측한 데이터를 다시 training set으로 사용하여 예측을 수행한다는 점이 다르다. 다시말해 개별 알고리즘의 예측 결과 dataset을 최종적인 메타 dataset으로 만들어 별도 ML 알고리즘으로 최종 학습을 수행하고 테스트 데이터를 기반으로 다시 최종 예측을 수행하는 방식이다. 개별 모델의 예측된 dataset을 기반으로 학습하고 예측하는 방식을 메타 모델이라고 한다.

이러한 스태킹은 각 개별 모델이 독립적이라고 가정하여 이상치(outlier)에 대응력이 높다. 따라서 단일 모델의 오분류율보다 작은 값을 갖게 되어 성능 이 우수하다.

스태킹을 사용하면 성능이 무조건 좋아지냐?

그렇지 않다. 현실 모델에서도 많이 사용되지 않는다.다만 캐글이나 데이콘과 같은 미세한 성능 차이로 승부를 결정하는 대회에서 주로 사용된다.

Reference

  1. 파이썬 머신러닝 완벽 가이드

Last updated