민프
[AI | ML] [분류기] Random Forest에 대해서 알아보자 - 1. 보팅편(Voting) 본문
분류기와 관련해서 이전 포스팅에서는 SVM, KNN, Deicision Tree에 대해서 알아보았는데요
이번 포스팅에서는 마지막으로 Random Forest에 대해서 알아보겠습니다.
영어를 직역해보자면
무작위 숲? 무작위로 무엇을 만든다는 것 인가?..
일단 알아보면서 이름이 기술과 어떤 연관이 있는지에 대해서 알아보았습니다.
(Leo Breiman Random Forests 논문을 참고하였습니다.)
Random Forest 의 역사
Random Forest는 Leo Breiman이 2001년에 발표한 논문에서 제안한 기법으로, 여러 가지 결정 트리(decision tree)를 결합하여 예측 정확도를 높이기 위한 앙상블 방법입니다. 이 모델은 이전의 몇 가지 앙상블 및 트리 기반 학습 방법을 개선하는 과정에서 발전했습니다.
이전에 포스팅 해드렸던 Decision Tree는 단순하고 직관적인 알고리즘이지만, 과적합(overfitting)이 발생하기 쉬워 데이터데 민감하다는 단점이 있었습니다. 또한 단일 트리는 데이터의 작은 변화에도 예측 성능이 급격하게 달라질 수 있었습니다.
1. 이전 기술들의 배경 및 한계점
Random Forest가 등장하기 전, 주로 사용되던 기법에는 Bagging, Boosting, 그리고 단일 결정 트리 모델이 있었습니다. 이 기법들은 각각 장점이 있었지만, 현실적인 한계도 존재했습니다.
- 단일 결정 트리: 결정 트리는 직관적이고 해석 가능하다는 장점이 있지만, 데이터에 민감하여 작은 변화에도 불안정해지고 과적합(overfitting)될 가능성이 높습니다.
- Bagging (Bootstrap Aggregating): Breiman이 제안한 이 기법은 학습 데이터에서 여러 번 샘플링을 통해 다수의 트리를 만들고 예측을 결합하여 과적합을 줄이는 방법입니다. 그러나 Bagging을 통해 생성되는 트리들 간의 독립성은 확보되지만 상관성을 줄이기는 어렵습니다.
- Boosting: Adaboost 등의 Boosting 기법은 오차가 큰 데이터 포인트에 더 많은 가중치를 부여하면서 일련의 트리를 생성해 예측력을 높입니다. 그러나, 이 과정에서 노이즈에 매우 민감해질 수 있으며 계산 복잡도가 높습니다.
2. Random Forest의 등장 이유?
Breiman은 이러한 문제들을 해결하기 위해 특징(feature) 무작위 선택과 다수의 트리를 결합하는 Random Forest를 제안했습니다. Random Forest는 트리를 생성할 때마다 각 노드에서 랜덤하게 일부 특징을 선택하여 최적의 분할을 결정하고, 이처럼 생성된 다수의 트리를 모아 최종 예측을 산출합니다. 이를 통해 모델의 안정성과 정확도를 동시에 높이면서 예측 성능을 높일 수 있습니다.
Random Forest 란?
먼저 위키백과에 따르면 다음과 같이 나와있습니다.
기계 학습에서의 랜덤 포레스트(영어: random forest)는 분류, 회귀 분석 등에 사용되는 앙상블 학습 방법의 일종으로, 훈련 과정에서 구성한 다수의 결정 트리로부터 부류(분류) 또는 평균 예측치(회귀 분석)를 출력함으로써 동작한다.
- 위키백과
자 그럼 위 논문 내용과 위키백과의 내용을 한줄 정리해보자면 Random Forest는 아래와 같을 것 같습니다.
"랜덤 포레스트(Random Forest)"라는 이름은 여러 개의 결정 트리(Decision Trees)로 이루어진 앙상블 모델을 의미합니다.
여기서 "포레스트(forest)"는 다수의 트리가 모여 이루는 숲을, "랜덤(random)"은 각 트리가 훈련 데이터의 특징(feature)과 샘플을 무작위로 선택해 학습하는 방식을 나타냅니다.
여기에서 앙상블 학습 방법, 앙상블 모델이라는게 나오게 되는데 이게 무엇일까요?
이것을 알아야 다음으로 넘어갈 수 있을 것 같습니다.
그럼 먼저 앙상블 학습을 알아보고 난 후 Random Forest에 대한 글을 이어서 진행하도록 하겠습니다.
ensemble learing(앙상블 학습법)
먼저 위키백과에 따른 앙상블 학습법 정의 입니다.
통계학과 기계 학습에서 앙상블 학습법(영어: ensemble learning method)은 학습 알고리즘(learning algorithm)들을 따로 쓰는 경우에 비해 더 좋은 예측 성능을 얻기위해 다수의 학습 알고리즘을 사용하는 방법이다.
- 위키백과
즉, 앙상블 학습은 여러 학습자를 결합하여 예측 성능을 향상 시키는 것 인데요
IBM의 글에서 보면 이 기법을 위원회 기반 학습이라고 부르는 경우도 있다고 합니다.
그럼 저만의 한줄 정의를 정리해보겠습니다.
앙상블 학습(Ensemble Learing) 기법이란
여러 개의 모델(개별 학습기)을 결합하여서 최종적인 예측 성능을 높이는 머신러닝 기법입니다.
이렇게 개별 학습기가 예측한 결과를 모아서 최종 예측값을 도출함으로써, 하나의 모델을 사용할 때보다 더 높은 정확도와 안정성을 얻을 수 있습니다. 앙상블 학습은 분류(classification), 회귀(regression), 그리고 다양한 예측 문제에서 효과적으로 사용됩니다.
1-2. 앙상블 학습의 종류
앙상블 학습에는 여러 가지 방법이 있으며, 대표적인 방법으로 보팅(Voting), 배깅(Bagging), 부스팅(Boosting), 스태킹(Stacking) 등이 있습니다.
먼저 보팅(Voting)에 대해서 알아보겠습니다.
1) Voting(보팅)
IT위키에서 Voting에 대한 위 사진을 가져와봤습니다.
사진에서와 같이 Voting은 하나의 데이터 셋에 다양한 모델들(Logistic Regression, Random Forest, SVM 등)을 결합하여 최종 예측 결과를 산출하는 과정 을 말합니다.
이 Voting 방식에는 Hard Voting과 Soft Voting 두 가지 주요 기법이 있으며, 각기 다른 방법으로 여러 모델의 예측 결과를 결합하여 최종 예측을 도출합니다.
아래에서 더 자세히 설명해보겠습니다.
1-2) Voting - Hard Voting
모델이 예측한 클래스 레이블을 집계하여, 가장 많이 예측된 클래스를 최종 예측으로 결정하는 방법입니다. 다수결의 원칙에 따라 최종 예측을 산출하므로, 직관적이고 구현이 간단합니다.
- 동작 방식
여러 모델이 각각 입력 데이터에 대해 예측을 수행하여 클래스 레이블을 출력합니다. 각 모델이 예측한 클래스 레이블을 집계하여, 가장 많이 선택된 클래스를 최종 예측값으로 정합니다.
아래 IT위키에서 가져온 Hard Voting방식의 예시 사진을 보며 말씀드리겠습니다.
근데 사진에서 좀 이상한게 보이실 겁니다.
제가 분명 위에서 "Voting은 하나의 데이터 셋에 다양한 모델들(Logistic Regression, Random Forest, SVM 등)을 결합하여 최종 예측 결과를 산출하는 과정 을 말합니다" 이라고 했는데 위 사진에서는 Traning Data 하나로 묶인 건 맞는데 왜 Sample Data가 여러개지? 생각이 들텐데요.
- Sample Data가 나뉘어 있는 이유
Voting 기법에서는 기본적으로 하나의 Training Data를 사용합니다. 그러나 배깅(Bagging)을 적용하면, 이 Training Data를 여러 개의 서브셋(Sample Data)으로 나눠 각 Classifier가 다른 부분을 학습하게 합니다. 이는 Voting 모델이 더욱 안정적인 예측을 할 수 있게 도와줍니다.
따라서 하나의 데이터셋(Training Data)에서 출발하지만, 이를 여러 Sample Data로 나누어 사용하는 것이며, Voting 기법의 최종 목표는 이러한 개별 모델들의 예측을 결합하여 단일 모델보다 더 높은 예측 성능을 얻는 것입니다.
- 위 사진에서 Training Data와 Sample Data의 관계
- Training Data는 전체 학습 데이터입니다. 모든 Sample Data는 이 Training Data로부터 무작위로 샘플링된 데이터 집합입니다.
- Sample Data 1, 2, 3, 4는 Training Data에서 중복을 허용하여 무작위로 선택된 데이터의 일부로, 각각 다른 서브셋입니다. 즉, Training Data는 동일하지만, 각 Classifier는 서로 다른 Sample Data를 학습하게 됩니다. 이는 하나의 데이터셋을 여러 번 샘플링한 것으로, 배깅(Bagging) 기법에서 자주 사용하는 방식입니다.
- 각 Classifier는 서로 다른 Sample Data로 학습되기 때문에, 같은 Training Data에서 출발했지만 약간씩 다른 데이터로 모델을 훈련하게 됩니다. 이는 각 Classifier의 예측 결과가 다양성을 가지게 하고, 이를 결합하여 더 안정적이고 일반화된 예측을 도출할 수 있도록 돕습니다.
자 이제 TrainData와 Sample Data에 대해서 궁금증을 풀었으니 Hard Voting방식의 예시 사진을 보며 계속해서 말씀드리겠습니다.
- 예시 설명
- Classifier 1은 Sample Data 1을 학습하고, 해당 데이터에 대해 클래스 1로 예측했습니다.
- Classifier 2는 Sample Data 2를 학습하고, 해당 데이터에 대해 클래스 2로 예측했습니다.
- Classifier 3은 Sample Data 3을 학습하고, 해당 데이터에 대해 클래스 1로 예측했습니다.
- Classifier 4는 Sample Data 4를 학습하고, 해당 데이터에 대해 클래스 1로 예측했습니다.
- 최종 예측
- 각 클래스의 예측 빈도를 다수결 방식으로 집계합니다.
- 클래스 1 예측 횟수: 3회
- 클래스 2 예측 횟수: 1회
- 클래스 1이 더 많이 선택되었기 때문에 최종 예측은 클래스 1이 됩니다.
- 여기에서 알 수 있는 Hard Voting의 장점
Hard Voting은 각 분류기의 확률 값이 필요 없고, 단순한 다수결을 통해 최종 예측을 도출하므로 계산이 간단하고 빠르게 처리할 수 있고, 또한, 여러 분류기의 결과를 결합함으로써 과적합을 방지하고 안정적인 예측 결과를 제공할 수 있습니다.
1-2) Voting - Soft Voting
Soft Voting은 각 분류기(Classifier)가 예측한 클래스의 확률 값을 사용하여 최종 예측을 결정하는 방법입니다. 마찬가지로 아래에서 이 이미지에 대해 단계별로 자세하게 설명하겠습니다.
위 사진에서 Sample Data, Training Data의 관계를 아시고 싶으시면 Hard Voting쪽을 다시 참고해주세요.
- 예시 설명
- Training Data:
- Training Data는 전체 학습 데이터이며, 이로부터 여러 개의 Sample Data를 만들어 각각의 분류기를 학습시킵니다.
- Sample Data 1, 2, 3, 4는 Training Data에서 무작위로 샘플링된 데이터로, 각기 다른 부분 집합입니다. 이로 인해 각 분류기는 서로 다른 데이터 샘플을 학습하게 됩니다.
- Classifier 1, 2, 3, 4:
- 각 Classifier는 개별 Sample Data로 학습되었습니다. 이는 배깅(Bagging) 기법의 일환으로, 각 분류기가 조금씩 다른 데이터 서브셋을 학습하여 다양한 예측 패턴을 가지도록 합니다.
- 예를 들어, Classifier 1은 Sample Data 1로 학습하고, Classifier 2는 Sample Data 2로 학습하는 식입니다.
- 각 Classifier의 확률 예측:
- Soft Voting에서는 각 Classifier가 예측한 클래스별 확률 값을 사용하여 최종 예측을 결정합니다.
- 예를 들어, Classifier 1은 클래스 1일 확률을 0.7, 클래스 2일 확률을 0.3으로 예측했습니다.
- 나머지 Classifier도 각각의 클래스에 대한 확률을 예측하여 출력합니다:
- Classifier 2: 클래스 1 = 0.2, 클래스 2 = 0.8
- Classifier 3: 클래스 1 = 0.8, 클래스 2 = 0.2
- Classifier 4: 클래스 1 = 0.9, 클래스 2 = 0.1
- 확률 값의 합산:
- Soft Voting에서는 각 분류기가 예측한 클래스의 확률 값을 합산하여, 최종 예측에 반영합니다.
- 각 클래스별 확률을 합산하면 다음과 같습니다:
- 클래스 1의 총 확률 = 0.7+0.2+0.8+0.9=2.60.7 + 0.2 + 0.8 + 0.9 = 2.6
- 클래스 2의 총 확률 = 0.3+0.8+0.2+0.1=1.40.3 + 0.8 + 0.2 + 0.1 = 1.4
- 최종 예측:
- Soft Voting에서는 확률 값이 더 높은 클래스를 최종 예측으로 선택합니다.
- 클래스 1의 총 확률(2.6)이 클래스 2의 총 확률(1.4)보다 높기 때문에, 최종 예측은 클래스 1이 됩니다.
여기까지 Hard Voting과 Soft Voting에 대해서 알아보았는데요 간단하게 비교해보자면 아래 차트와 같습니다.
Soft Voting vs Hard Voting
특징 | Soft Voting | Hard Voting |
결합기준 | 각 분류기가 예측한 클래스 확률 값을 합산하거나 평균하여 확률이 가장 높은 클래스를 선택 | 각 분류기가 예측한 클래스 레이블을 집계하여, 다수결 원칙에 따라 최종 클래스를 결정 |
장점 | 모델의 예측 확률 값을 반영하여 신뢰도 높은 결합 가능 | 계산이 간단하고, 확률 값이 필요 없어서 빠르게 처리할 수 있음 |
단점 | 확률 예측이 가능한 모델만 사용할 수 있어, 모델 선택에 제약이 있음 | 단순히 다수결로 결정하므로 모델의 신뢰도를 반영하지 못함 |
적용 사례 | 분류기들이 예측 확률을 제공할 수 있고, 개별 모델의 신뢰도를 반영해야 하는 경우에 유리 | 확률 값이 필요 없고, 단순 다수결로 안정적인 예측을 얻고자 할 때 유리 |
계산 비용 | Hard Voting보다 비용이 높음 (확률 계산이 필요하기 때문) | Soft Voting보다 비용이 적음 |
실제로 코드 적용을 했을 때 계산 비용에 따른 동작 시간이 얼마나 다를지는 모르겠지만
정확도 차이가 엄청난게 아니라면 Hard Voting으로 빠르고, 단순하게 끝내는 것도 좋을 것 같습니다.
코드 적용
import 를 아래와 같이 해줍니다.
이전에 포스팅 했었던 분류기들은 필수적으로 추가해줬습니다. (KNN, Decision Tree, SVM)
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.neighbors import KNeighborsClassifier // KNN 모델 사용
from sklearn.tree import DecisionTreeClassifier // Deicision Tree 모델 사용
from sklearn.svm import SVC // SVC(SVM) 모델 사용
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import VotingClassifier // VotingClassfier 클래스 사용
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import classification_report, accuracy_score // 점수 추출
데이터 셋을 아래와 같이 넣어줬습니다.
저는 제가 가지고 있는 운동데이터들을 넣었습니다.
# Train CSV 파일 로드
df_train = pd.read_csv(bootstrap_csvs_out_folder)
# Test CSV 파일 로드
df_test = pd.read_csv(bootstrap_csvs_out_test_folder)
아래 각 분류기들을 정의해줍니다.
# 분류기 정의
knn1 = KNeighborsClassifier(n_neighbors=3)
knn2 = KNeighborsClassifier(n_neighbors=5)
decision_tree = DecisionTreeClassifier(random_state=42)
svm = SVC(probability=True, random_state=42) # Soft Voting을 위해 probability=True 설정
# Soft Voting 적용
soft_voting_model = VotingClassifier(
estimators=[('knn1', knn1), ('knn2', knn2), ('decision_tree', decision_tree), ('svm', svm)],
voting='soft'
)
# Hard Voting 적용
hard_voting_model = VotingClassifier(
estimators=[('knn1', knn1), ('knn2', knn2), ('decision_tree', decision_tree), ('svm', svm)],
voting='hard'
)
성능 평가에 대한 부분을 넣어줍니다.
# Soft Voting 성능 평가
print("Soft Voting - Classification Report:")
print(classification_report(y_test, y_test_pred_soft))
accuracy_soft = accuracy_score(y_test, y_test_pred_soft)
print(f"Soft Voting - Accuracy: {accuracy_soft * 100:.2f}%")
# Hard Voting 성능 평가
print("\nHard Voting - Classification Report:")
print(classification_report(y_test, y_test_pred_hard))
accuracy_hard = accuracy_score(y_test, y_test_pred_hard)
print(f"Hard Voting - Accuracy: {accuracy_hard * 100:.2f}%")
# Soft Voting - 각 샘플에 대한 클래스별 확률 출력
print("\nTest Data Predictions (Soft Voting):")
for i in range(len(y_test)):
actual_class = y_test[i]
predicted_class = y_test_pred_soft[i]
probs = {label: prob for label, prob in zip(soft_voting_model.classes_, soft_probs[i])}
correct = "Correct" if predicted_class == actual_class else "Incorrect"
print(f"Test Sample {i+1}: Actual: {actual_class}, Predicted: {predicted_class} (Soft Voting) - {correct}")
print(f"Class Probabilities: {probs}")
# Hard Voting - 각 샘플에 대해 개별 분류기의 예측 결과 출력
print("\nTest Data Predictions (Hard Voting):")
for i in range(len(y_test)):
predictions = []
actual_class = y_test[i]
for clf_name, clf in hard_voting_model.named_estimators_.items():
pred = clf.predict(X_test_scaled[i].reshape(1, -1))[0]
predictions.append((clf_name, pred))
predicted_class = y_test_pred_hard[i]
correct = "Correct" if predicted_class == actual_class else "Incorrect"
print(f"Test Sample {i+1}: Actual: {actual_class}, Final Prediction: {predicted_class} (Hard Voting) - {correct}")
print(f"Individual Classifier Predictions: {predictions}")
아래는 출력 결과 입니다. SVM, KNN, Decision Tree모두 90점대를 기록했었는데 이건 100%이네요.
로그를 보아하니 100% 다 정답으로 맞춘 것 같네요. 성능은 확실한 것 같습니다.
Soft Voting - Classification Report:
precision recall f1-score support
sphinx_down 1.00 1.00 1.00 77
sphinx_up 1.00 1.00 1.00 77
accuracy 1.00 154
macro avg 1.00 1.00 1.00 154
weighted avg 1.00 1.00 1.00 154
Soft Voting - Accuracy: 100.00%
Hard Voting - Classification Report:
precision recall f1-score support
sphinx_down 1.00 1.00 1.00 77
sphinx_up 1.00 1.00 1.00 77
accuracy 1.00 154
macro avg 1.00 1.00 1.00 154
weighted avg 1.00 1.00 1.00 154
Hard Voting - Accuracy: 100.00%
Class Probabilities: {'ham_go': 0.03365311139705488,
'ham_ready': 0.25514979651604447, 'sphinx_down': 0.013600036983965197,
'sphinx_up': 0.6816899499814477, 'squat_down': 0.005928184019974004,
'squat_up': 0.009978921101513698}
Test Sample 154: Actual: sphinx_up, Predicted: sphinx_up (Soft Voting) - Correct
Individual Classifier Predictions: [('knn1', 2), ('knn2', 2),
('decision_tree', 2), ('svm', 2)]
Test Sample 37: Actual: sphinx_down,
Final Prediction: sphinx_down (Hard Voting) - Correct
참고링크
https://link.springer.com/article/10.1023/A:1010933404324
https://ko.wikipedia.org/wiki/%EB%9E%9C%EB%8D%A4_%ED%8F%AC%EB%A0%88%EC%8A%A4%ED%8A%B8
https://ko.wikipedia.org/wiki/%EC%95%99%EC%83%81%EB%B8%94_%ED%95%99%EC%8A%B5%EB%B2%95
https://www.ibm.com/kr-ko/topics/ensemble-learning
https://itwiki.kr/w/%EC%95%99%EC%83%81%EB%B8%94_%EA%B8%B0%EB%B2%95
'[AI | ML]' 카테고리의 다른 글
[AI | ML] [분류기] Random Forest에 대해서 알아보자 - 3. Random Forest 편 (마지막) (11) | 2024.10.28 |
---|---|
[AI | ML] [분류기] Random Forest에 대해서 알아보자 - 2. 배깅편(bagging) (2) | 2024.10.28 |
[AI | ML] [HPE] Landmarks 정보 (2D, 3D) 선택에 대한 고찰 (8) | 2024.10.23 |
[AI | ML] [분류기] Decision Tree (결정 트리)에 대해서 알아보자 (14) | 2024.10.23 |
[AI | ML] [분류기] SVM (Support Vector Machine)에 대해서 알아보자 (4) | 2024.10.02 |