본문 바로가기

공부 일지 #35 | 머신러닝: 앙상블과 RandomForest, 교차검증

@studying:)2025. 9. 14. 08:23

학습날짜: 2025.09.09


1. 앙상블 학습 기법

  • 여러 개 ML 모델을 결합해 학습/예측하는 방법임
  • 단일 모델보다 일반적으로 성능이 높음
  • 최신 앙상블 기법은 정형 데이터에서 딥러닝에 필적함

1.1. Voting

  • 서로 다른 ML 모델을 동일한 데이터로 학습
  • 예측 결과를 합쳐서 최종 결정
  • Hard voting: 단순 다수결
  • Soft voting: 예측 확률 평균
#앙상블(voting) 실습을 사용하기 위한 import
from sklearn.ensemble import VotingClassifier        # 앙상블 모델 (보팅)
from sklearn.linear_model import LogisticRegression  # 선형 모델 - 로지스틱 회귀
from sklearn.tree import DecisionTreeClassifier      # 결정트리 분류기
from sklearn.neighbors import KNeighborsClassifier   # 최근접 이웃 분류기 (KNN)
from sklearn.model_selection import train_test_split # train/test 데이터 분할 함수
from sklearn.metrics import accuracy_score           # 분류 정확도 평가 함수

from sklearn.datasets import load_breast_cancer      # 유방암 데이터셋 (이진 분류용 예제 데이터)

# load dataset
cancer = load_breast_cancer()

X = cancer["data"]
y = cancer["target"]

# dataset 분할
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=12)

# 개별 분류기 모델 생성
lr = LogisticRegression(random_state=12, max_iter=100)
dt = DecisionTreeClassifier(random_state=12, max_depth= 5)
knn = KNeighborsClassifier(n_neighbors=5)

# 앙상블 voting object 생성
voting = VotingClassifier(estimators=[("LR",lr), ("DT",dt), ("KNN", knn)], voting ="soft")

# voting 메커니즘 안의 모델들을 학습
voting.fit(x_train, y_train)

# 예측
y_pred = voting.predict(x_test)

# 검증
accuracy_score(y_test, y_pred)
'''
0.9298245614035088
'''

1.2. Bagging

  • Bootstrap Aggregating의 약자
  • 데이터셋에서 복원추출로 샘플링
  • 동일 모델을 독립적으로 여러 번 학습
# Bagging; RandomForest 실습
from sklearn.ensemble import RandomForestClassifier # 랜덤포레스트 분류기 (배깅 기반 앙상블)

# 모델 객체생성(랜덤포레스트, max_depth=5로 제한)
rf = RandomForestClassifier(random_state=12, max_depth=5)

# 학습
rf.fit(x_train, y_train)

# 예측
y_pred = rf.predict(x_test)

# 검증
print(accuracy_score(y_test, y_pred))
'''
0.9239766081871345
'''

1.3. Boosting

  • Bagging과 유사하지만 순차적으로 학습
  • 이전 단계 결과를 바탕으로 다음 단계 가중치 부여
  • 성능은 가장 높지만 학습 속도 느림
  • 주요 기법: AdaBoost, GradientBoost, XGBoost
    • Ada: 잘못 분류된 샘플에 높은 가중치
    • Gradient: 잔차를 줄이는 방식
    • XGB: Gradient 방식을 개선한 방식
      • 정규화, 병렬처리, 교차검증 내장(자동으로 최적 파라미터 튜닝)
      • 성능 좋지만 튜닝 난이도 높음
'''
1. AdaBoost
- AdaBoost (약한 분류기를 순차적으로 학습, 잘못 분류된 샘플에 가중치 부여)
- learning_rate: 학습 속도 및 가중치 크기 조절
'''
from sklearn.ensemble import AdaBoostClassifier

ada = AdaBoostClassifier(n_estimators=100, random_state=12)  # default=50
ada.fit(x_train, y_train)
y_pred = ada.predict(x_test)

accuracy_score(y_test, y_pred)
'''
0.9298245614035088
Boosting 알고리즘이 항상 더 좋은 건 아님 → 데이터 특성에 따라 다름
'''

'''
2. Gradient Boosting
? Gradient Boosting (잔차를 줄이는 방식으로 학습)
'''
from sklearn.ensemble import GradientBoostingClassifier

gb = GradientBoostingClassifier(learning_rate=0.1, n_estimators=100, # default 값
                                max_depth = 5,
                                random_state=12)                            
gb.fit(x_train, y_train)
y_pred = gb.predict(x_test)

accuracy_score(y_test, y_pred)
'''
0.9239766081871345
'''

'''
3. XGBboost
? Gradient Boosting 개선 버전, 정규화/병렬처리/CV 내장
'''
!pip install xgboost

from xgboost import XGBClassifier
earning_rate=0.1, n_estimators=100, max_depth = 3, random_state = 12,
                    reg_alpha = 0.5, # L1정규화 정도
                    reg_lambda = 1.0, # L2정규화 정도
                    eval_metric = "logloss") # 손실 함수 지정 / n_jobs = None 건드리지 않음
xgb.fit(x_train, y_train)
y_pred = xgb.predict(x_test)

accuracy_score(y_test, y_pred)
'''
0.935672514619883

보다시피 XGBoost 모델은 하이퍼파라미터가 매우 많음 
→ 그래서 GridSearchCV 같은 기법으로 최적화(튜닝)해야 함!
'''


2. 랜덤포레스트(Random Forest)

  • Bagging 기반 대표 앙상블 모델
  • Base 모델은 Decision Tree
  • 트리 여러 개를 학습시켜 예측 평균

2.1. 장점

  • 과적합 위험이 줄어듦
  • 예측 성능 일반적으로 높음
  • DT 장점 대부분 포함 (해석력 제외)

2.2. 단점

  • 학습 속도 느림
  • Hyperparameter 튜닝 어려움(조합이 많기 때문)

3. 최적의 모델 찾기 (Model Selection)

모델을 단순히 학습시키는 것에서 끝나지 않고,
검증 → 교차검증 → 하이퍼파라미터 튜닝 과정을 거쳐 최적화해야 함


3.1. 단일 검증 방식 (Hold-out Validation)

  • 데이터셋을 train / validation / test로 한 번만 나눠 사용
  • validation으로 모델 성능 개선, test는 최종 확인용
  • 테스트 데이터셋에 과적합된 모델이 만들어져, 최종 검증용으로서의 의미가 사라질 수 있음

3.2. 교차검증 (Cross Validation)

  • hold-out 방식의 한계를 보완하기 위해 등장
  • 여러 세트의 validation 데이터셋을 순환적으로 사용 → 데이터 활용 극대화
  • 다양한 데이터에 최적화된 모델 학습 가능
  • 테스트 데이터셋은 여전히 최종 성능 검증용으로만 사용
  • K-Fold Cross Validation
    • 데이터를 K개의 폴드로 나눠 학습/검증 반복
    • 회귀분석에서 주로 사용
from sklearn.model_selection import KFold

# train/test 분할
X, x_test, y, y_test = train_test_split(X, y, test_size=0.2, random_state= 41)

# K-Fold 교차검증 함수
# 참고: sklearn의 cross_val_score 함수를 사용하면 더 간단하게 교차검증 가능
def exec_kfold2(clf, folds, x_train, y_train):
  kfold = KFold(n_splits=folds)
  scores = []

  for index, (train_index, test_index) in enumerate(kfold.split(x_train)):
    x_tr, x_te = x_train.iloc[train_index, ], x_train.iloc[test_index]
    y_tr, y_te = y_train.values[train_index], y_train.values[test_index]

    clf.fit(x_tr, y_tr)
    y_pred = clf.predict(x_te)

    acc = accuracy_score(y_te, y_pred)
    scores.append(acc)
    print(f"iteration count : {index}, 정확도 : {acc}")

  mean_score = np.mean(scores)
  print(f"Final avg mean score is {mean_score}")
  
# 결정트리 모델 교차검증 실행
dt = DecisionTreeClassifier(random_state=12)
exec_kfold2(dt, 5, X, y)
'''
iteration count : 0, 정확도 : 0.7543859649122807
iteration count : 1, 정확도 : 0.7105263157894737
iteration count : 2, 정확도 : 0.7543859649122807
iteration count : 3, 정확도 : 0.7105263157894737
iteration count : 4, 정확도 : 0.7787610619469026
Final avg mean score is 0.7417171246700822
'''

# 최종 테스트 데이터 검증 (교차검증과 비교)
y_pred = dt.predict(x_test)
accuracy_score(y_test, y_pred)

'''
0.7552447552447552
'''
  • Stratified K-Fold Cross Validation
    • 분류 문제에서 반드시 사용해야 함
    • 클래스(y) 비율 유지하면서 분할

3.3. Grid Search CV

  • 여러 파라미터 조합을 모두 탐색해서 최적값 찾음
  • 성능이 만족할 때까지 학습 → 검증 → 개선 반복
  • 하이퍼파라미터: 데이터로 학습되지 않고 사람이 직접 설정해야 하는 값
    (예: 트리 개수, max_depth, min_samples_split 등)
# 하이퍼파라미터 튜닝을 위한 GridSearchCV 라이브러리 로딩
from sklearn.model_selection import GridSearchCV

# 모델 구현을 위한 라이브러리 로딩
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.tree import DecisionTreeClassifier

# load_iris() 메서드를 이용해 dataset로드
iris = load_iris()

# 학습, 테스트 셋 분할
x_train, x_test, y_train, y_test = train_test_split(iris['data'],
                                                    iris['target'],
                                                    test_size=0.2,
                                                    random_state=121)
# 모델 객체 생성
dt = DecisionTreeClassifier()

# 탐색할 하이퍼파라미터 후보 정의
parameters = {"max_depth": [1,2,3],
              "min_samples_split": [2,3]} # 노드 분할을 위한 최소 샘플 수

# GridSearchCV 객체생성
grid_dt = GridSearchCV(estimator=dt,		# estimator: 학습시킬 모델
                       param_grid=parameters,	# param_grid: 탐색할 하이퍼파라미터 조합
                       cv=3,			# cv: 교차검증 횟수
                       refit=True)		# refit=True → 최적의 파라미터로 다시 학습시킴

# GridSearchCV 수행 (교차검증으로 모든 파라미터 조합 평가)
grid_dt.fit(x_train, y_train)

# 후보 파라미터 셋의 성능 검증 결과 출력
print(f'Optimal parameter: {grid_dt.best_params_}')
print(f'Max accuracy: {grid_dt.best_score_: .4f}')
'''
Optimal parameter: {'max_depth': 3, 'min_samples_split': 2}
Max accuracy:  0.9750
'''
studying:)
@studying:) :: what i studied

studying:) 님의 학습 여정을 기록하는 블로그입니다.

목차