머신러닝 알고리즘 앙상블(Ensemble)모형 .01

데비드·2021년 6월 3일
0

알고리즘

목록 보기
2/3
post-thumbnail

앙상블(Ensemble) 모형

기본적으로 앙상블 모형은 여러 예측 알고리즘을 결합함으로써 더욱 뛰어난 예측 모형을 만드는 것을 목적으로 한다. 앙상블 모형의 개념은 대중의 지혜(Wisdom of the crowd)에서 비롯된다고 볼 수 있는데, 이는 어떠한 현상에 대한 답을 얻고자 할 때 한 명의 전문가보다 다수의 일반인의 의견을 종합하는 것이 더 나은 경우가 있다는 가정으로부터 시작된다.

이미지, 영상, 음성 데이터와 같은 비정형 데이터의 처리에는 딥러닝 알고리즘이 뛰어난 성능을 보이지만 정형화 데이터의 처리에는 앙상블 모형이 성능이 좋다고 한다.

알고리즘의 이론상 회귀 모델과 분류 모델에서 모두 사용 가능하지만 개인적으로 분류 문제에서의 성능이 뛰어난 편이라고 생각한다.

1-1. 투표 기반 분류기와 큰 수의 법칙(Law of Large Numbers)

한 명의 전문가보다 다수의 일반인이 나을 수 있다는 논리에 의문이 생길 수 있다. 물론 현실에서 이러한 일이 반드시 이루어진다는 보장은 없다. 머신러닝의 경우 통계의 문제이고, 통계란 확률의 문제이기 때문에 이와 같은 논리가 적용될 수 있다고 생각하는 편이 옳다.
앙상블 모형을 설명하기 위해 한 명의 전문가와 다수의 일반인이라는 예를 들었을 뿐이다. 머신러닝 모델을 예로 든다면 성능이 좋은(예측 결과가 좋은) 머신러닝 모델 하나를 고려하는 것보다, 성능이 조금 떨어지는(예측 결과가 좋지 않은) 머신러닝 모델 여러 개를 종합하여 최종적인 예측 모델을 뽑아내는 것이 더 뛰어난 성능을 보일 수 있다는 의미이다. 최종 예측 모델을 구축해나가는 과정은 여러가지 방법이 있으며(Votting, Bagging 등) 이는 뒤에 다시 설명하고자 한다.

큰 수의 법칙을 예로 들면 확률의 문제라는 것을 좀 더 쉽게 이해할 수 있다.

동전을 던져서 앞면과 뒷면이 나올 확률을 구한다고 생각해보자. 다만 이 동전은 균형이 살짝 맞지 않아서 앞면이 나올 확률이 뒷면이 나올 확률보다 조금 더 높다. 확률적으로는 앞면이 나올 확률이 51%, 뒷면이 나올 확률이 49%이다.
수학적으로 계산했을 때 이 동전을 100번을 던진다면 앞면이 51번, 뒷면은 49번이 나오게 된다. 1000번을 던진다면 앞면이 510번, 뒷면이 490번이 나오게 될 것이다.

다시 말해, 시행 횟수를 증가시킬수록 동전의 앞면이 나올 확률이 점점 더 커진다. 이는 수학적 계산식을 통해 계산할 수 있지만

(이항 분포의 확률 질량 함수식에 따라 1,000번 시행의 경우 앞면이 더 많이 등장할 확률은 약 75%(1 - scipy.stats.binom.cdf(499, 1000, 0.51), 10,000번 시행의 경우 앞면이 더 많이 등장할 확률은 약 97%(1 - scipy.stats.binom.cdf(4999, 10000, 0.51)에 달한다.)

쉽게 정리하자면 동전을 던지는 횟수가 많아질수록 동전의 앞면이 등장할 확률이 크게 증가한다고 볼 수 있다.

앙상블 모형에 적용해 생각해본다면

시행횟수 = 앙상블 모형에 적용 된 모델의 갯수
앞면이 더 많이 나올 확률 = 앙상블 모형의 정확도

로 정리할 수 있다.

아래로는 앙상블 기법 중 자주 사용하는 기법을 예제와 함께 풀어 설명했다.

1-2. 투표 기반 분류기 (Votting)

위의 큰 수의 법칙에 대해 이해했다면 앙상블 기법 중 하나인 투표 기반 분류기를 구현할 수 있다.

대중의 지혜, 큰 수의 법칙의 논리에 따라 투표 기반 분류기는 여러 분류기의 예측을 모아 가장 많이 선택된 클래스를 예측하는 것이다.

iris 데이터셋에서 세 가지 모델(LogisticRegression, RandomForest, SupportVectorMachine)을 사용해 투표 기반 분류 모델을 만드는 예제를 풀어보자.

from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.ensemble import VotingClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

iris = load_iris()
X = iris.data
Y = iris.target
X_train, x_test, Y_train, y_test = train_test_split(X, Y, test_size=0.3, random_state=88)

rf = RandomForestClassifier()
lr = LogisticRegression()
svm = SVC()
voting = VotingClassifier(estimators=[('rf', rf), ('lr', lr), ('svm', svm)], voting='hard')

# voting 값이 'hard'일 경우에는 직접 투표, 'soft'일 경우에는 간접 투표 방식으로 모델이 생성된다.
# 간접 투표 방식은 확률이 높은 투표에 비중을 더 두기 때문에 직접 투표보다 성능이 좋다.
# 단, 이를 위해서는 사용된 모델이 모두 확률 예측이 가능해야 한다.

voting.fit(X_train, Y_train)

for model in (rf, lr, svm, voting):
    model.fit(X_train, Y_train)
    y_pred = model.predict(x_test)
    print(model.__class__.__name__, ' : ', round(accuracy_score(y_test, y_pred), 4))

# 출력 결과
RandomForestClassifier  :  0.9111
LogisticRegression  :  0.9111
SVC  :  0.9333
VotingClassifier  :  0.9556

투표 기반 분류 모델이 기존의 세 모델보다 성능이 더 좋은 것을 확인할 수 있었다.

1-3. 직접 투표(Hard Votting)와 간접 투표(Soft Votting)

위의 예제에서는 직접 투표(Hard Votting)를 사용한 투표 기반 분류기의 생성 과정이다. VotingClassifier 메서드에서 voting값을 'hard'로 주면 직접 투표, 'soft'로 주면 간접 투표 방식의 분류기를 생성할 수 있는데, 두 방식의 차이점은 다음과 같이 간단히 요약할 수 있다.

  • Hard Votting : 다수결의 원칙과 유사한 방식
    예측한 결과값들 중 다수의 분류기가 선택한 예측값을 최종 예측값으로 선정한다.
  • Soft Votting : 분류기의 레이블 값의 결정 확률을 모두 더하고 이를 평균해서, 이들 중 가장 높은 레이블 값을 최종 예측값으로 선정한다.

간접 투표(Soft Votting) 방식은 확률이 높은 투표에 더 많은 비중을 두기 때문에 일반적으로 더 좋은 성능을 기대할 수 있다.
이 방식을 사용할 경우 각 분류기의 레이블 값의 평균을 구해야 하기 때문에, 적용하는 머신러닝 모델에 predict_proba() 메서드가 있는 경우에만 사용이 가능하다.

아래는 Soft Votting 방식을 활용해 생성한 분류기이다.

from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.ensemble import VotingClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

iris = load_iris()
X = iris.data
Y = iris.target
X_train, x_test, Y_train, y_test = train_test_split(X, Y, test_size=0.3, random_state=22)

rf = RandomForestClassifier()
lr = LogisticRegression()
svm = SVC(probability = True)

# SVC는 predict_proba() 메서드를 제공하지 않는다.
# 따라서 probability = True 값을 적용하여 확률 계산이 가능하도록 설정
# probability = True 값을 설정하면 훈련 속도는 느려지지만 SVC 모델 자체의 성능은 올라간다.

voting = VotingClassifier(estimators=[('rf', rf), ('lr', lr), ('svm', svm)], voting='soft')


voting.fit(X_train, Y_train)

for model in (rf, lr, svm, voting):
    model.fit(X_train, Y_train)
    y_pred = model.predict(x_test)
    print(model.__class__.__name__, ' : ', round(accuracy_score(y_test, y_pred), 4))

>>> 출력 결과
RandomForestClassifier  :  0.9333
LogisticRegression  :  0.9556
SVC  :  0.9333
VotingClassifier  :  0.9556

1-4. Votting 정리

주의해야 할 점은 투표 기반 분류기를 생성한다고 해서 기존의 머신러닝 모듈보다 항상 좋은 성능을 기대할 수는 없다는 점이다. 데이터의 특성에 따라 기존의 머신러닝 모듈이 더 좋은 성능을 보일 수도 있다. 따라서 데이터의 과적합을 방지하면서 최적의 결과값이 나오도록 유연한 대처를 하는 것이 필요하다.

투표 기반 분류기의 전제는 적용되는 머신러닝 모듈이 독립적이어야 한다는 것이다.
동전을 던질 때 각각의 시행은 모두 독립적이라는 것을 생각하면 쉽게 이해할 수 있다. 마찬가지로 투표 기반 분류기에 적용되는 머신러닝 모듈은 서로에게 영향을 주지 않으면서 독립적으로 시행되어야 한다.

쉽게 말해서 같은 머신러닝 모듈을 사용하지 말아야 한다는 뜻이다. 동일한 예측값을 가지는 머신러닝 모듈을 중복으로 사용할 경우 편향된 결과값을 낼 수 있기 때문이라고 생각할 수 있다.

이는 뒤에서 다룰 앙상블 기법인 Bagging과 차이가 있다. Bagging의 경우에는 같은 유형은 단일 알고리즘 내에서 데이터 샘플링에 차별화를 두는 방식이다. 이에 대해서는 Bagging 파트에서 다뤄보려고 한다.

0개의 댓글