본문 바로가기
scikit-learn

[scikit-learn] 분류(Classification) 모델 실전 비교

by PredictLab | 데이터 예측 연구소 2025. 4. 22.

1. 서론

머신러닝에서 가장 기본적이면서도 중요한 문제 유형 중 하나는 분류(Classification)입니다. 타겟 변수가 범주형일 때, 우리는 이 데이터를 통해 새 샘플이 어떤 클래스에 속할지 예측하고자 합니다. 이 글에서는 대표적인 분류 알고리즘 5가지를 소개하고, 동일한 데이터셋에서 비교 분석함으로써 각 모델의 특성과 성능 차이를 실감할 수 있도록 구성했습니다.

소개할 분류 모델은 Logistic Regression, K-Nearest Neighbors, SVC, Decision Tree, Random Forest이며, 각각의 이론적 개요, 사용법, 그리고 실전 적용 예제까지 함께 다룰 예정입니다.

2. 주요 모델 소개

2-1. Logistic Regression

Logistic Regression은 가장 기본적이면서 널리 사용되는 선형 분류 알고리즘입니다. 이름에 '회귀'가 들어가 있지만, 출력값이 클래스 확률로 변환되기 때문에 분류 문제에 적합합니다. 특히 이진 분류 문제에서 해석력이 뛰어나며, 피처와 클래스 간 선형 관계가 있는 경우 높은 성능을 보입니다.

from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline

# 데이터 로드
X, y = load_iris(return_X_y=True)

# 파이프라인 구성
pipe = Pipeline([
    ('scaler', StandardScaler()),
    ('clf', LogisticRegression(max_iter=200))
])

# 교차검증 정확도
scores = cross_val_score(pipe, X, y, cv=5, scoring='accuracy')
print("Logistic Regression 평균 정확도:", scores.mean())

위 예제는 Iris 데이터셋을 사용하여 로지스틱 회귀 모델을 평가한 것입니다. StandardScaler로 스케일링 후 학습하며, cross_val_score로 5-폴드 교차검증 평균 정확도를 계산합니다.

실전 팁: 피처 수가 많고 상관관계가 있는 경우 penalty='l1' 또는 'elasticnet'를 사용해 정규화를 적용해보는 것도 좋은 방법입니다.

2-2. K-Nearest Neighbors

K-Nearest Neighbors (KNN)는 가장 직관적인 분류 알고리즘 중 하나로, 새로운 샘플이 주어졌을 때 가장 가까운 K개의 이웃 데이터를 참조해 다수결로 분류를 결정합니다. 사전 학습이 필요 없는 instance-based learning 방식이며, 거리 계산에 따라 분류가 이루어지므로 스케일 조정이 중요합니다.

from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline

# 데이터 로드
X, y = load_iris(return_X_y=True)

# 파이프라인 구성
pipe = Pipeline([
    ('scaler', StandardScaler()),
    ('clf', KNeighborsClassifier(n_neighbors=5))
])

# 교차검증 정확도
scores = cross_val_score(pipe, X, y, cv=5, scoring='accuracy')
print("KNN 평균 정확도:", scores.mean())

KNN은 데이터의 밀도나 분포에 민감하므로 데이터 전처리, 특히 스케일링이 필수적입니다. n_neighbors 값은 일반적으로 홀수로 설정하며, 데이터에 따라 적절한 값을 튜닝해야 성능을 극대화할 수 있습니다.

실전 팁: 고차원 데이터에서는 KNN의 성능이 급격히 저하될 수 있으며, 이 경우 PCA 같은 차원 축소 기법과 함께 사용하는 것이 좋습니다.

2-3. SVC (Support Vector Classifier)

Support Vector Classifier (SVC)는 서포트 벡터 머신(SVM) 기반의 분류 모델로, 결정 경계(margin)를 최대화하는 초평면을 찾아 분류를 수행합니다. 선형적으로 분리되지 않는 데이터에도 커널 함수를 적용해 고차원 공간으로 매핑함으로써 유연한 결정 경계를 형성할 수 있습니다.

from sklearn.svm import SVC
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline

# 데이터 로드
X, y = load_iris(return_X_y=True)

# 파이프라인 구성
pipe = Pipeline([
    ('scaler', StandardScaler()),
    ('clf', SVC(kernel='rbf', C=1.0, gamma='scale'))
])

# 교차검증 정확도
scores = cross_val_score(pipe, X, y, cv=5, scoring='accuracy')
print("SVC 평균 정확도:", scores.mean())

기본 커널은 rbf이며, 선형 문제에는 linear 커널도 사용할 수 있습니다. C는 마진 오류 허용 정도, gamma는 결정 경계의 복잡도를 조절하는 핵심 하이퍼파라미터입니다.

실전 팁: SVC는 작은 데이터셋에서는 뛰어난 성능을 보이지만, 데이터가 많아지면 학습 시간이 급격히 증가합니다. 대용량 데이터에는 LinearSVC 또는 SGDClassifier와 같은 대안도 고려해볼 수 있습니다.

2-4. Decision Tree

Decision Tree는 데이터를 분할하면서 의사결정을 해나가는 트리 기반 모델입니다. 피처의 임계값을 기준으로 데이터를 구분하는 방식으로 직관적이며, 시각화와 해석이 쉬운 장점이 있습니다. 과적합의 위험이 있어 적절한 깊이 제한이나 가지치기(pruning)가 중요합니다.

from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split, cross_val_score

# 데이터 로드
X, y = load_iris(return_X_y=True)

# 모델 정의
model = DecisionTreeClassifier(max_depth=3, random_state=42)

# 교차검증
scores = cross_val_score(model, X, y, cv=5, scoring='accuracy')
print("Decision Tree 평균 정확도:", scores.mean())

위 예제에서는 최대 깊이 3으로 제한한 결정트리 모델을 사용하였습니다. 트리 모델은 전처리 없이도 사용 가능하므로 간편하며, 각 분할 기준은 불순도 지표(Gini 지수, 엔트로피 등)를 기반으로 계산됩니다.

실전 팁: DecisionTreeClassifier는 시각화 기능이 탁월해 plot_tree() 함수 등을 통해 트리 구조를 직접 확인하며 모델을 해석할 수 있습니다. 단, 복잡한 트리는 과적합을 유발하므로 max_depth, min_samples_split 등으로 제어하는 것이 중요합니다.

2-5. Random Forest

Random Forest는 여러 개의 결정 트리를 앙상블하여 예측 성능을 높이는 모델입니다. 각각의 트리는 데이터의 일부 샘플과 피처를 랜덤하게 선택하여 학습하며, 최종 예측은 모든 트리의 예측 결과를 평균(회귀) 또는 다수결(분류)로 결정합니다. 과적합을 줄이고 일반화 성능이 뛰어난 것이 특징입니다.

from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import cross_val_score

# 데이터 로드
X, y = load_iris(return_X_y=True)

# 모델 정의
model = RandomForestClassifier(n_estimators=100, max_depth=4, random_state=42)

# 교차검증
scores = cross_val_score(model, X, y, cv=5, scoring='accuracy')
print("Random Forest 평균 정확도:", scores.mean())

랜덤 포레스트는 개별 트리보다 더 나은 성능을 제공하면서도 과적합을 방지하는 데 효과적입니다. n_estimators는 트리 개수, max_features는 각 트리에서 사용할 피처 수를 조절합니다.

실전 팁: 피처 중요도는 feature_importances_ 속성으로 확인할 수 있으며, 모델 해석에도 활용됩니다. 예측 성능이 높은 만큼 학습 및 예측 속도는 트리 개수와 비례하므로 적절히 조정해야 합니다.

3. 결론

이번 글에서는 대표적인 분류 알고리즘 5가지(Logistic Regression, KNN, SVC, Decision Tree, Random Forest)를 동일한 데이터셋에 적용해보고, 각각의 구조, 작동 원리, 코드 구현, 교차검증 결과까지 비교해보았습니다. 각 모델은 데이터 특성에 따라 강점이 다르므로 하나의 모델만 고집하기보다 다양한 모델을 실험하며 최적의 조합을 찾는 것이 중요합니다.

데이터가 선형적으로 구분된다면 로지스틱 회귀나 SVM이 효과적일 수 있고, 데이터의 분포나 경계가 복잡하다면 결정 트리 기반의 앙상블 모델이 더 나은 성능을 보일 수 있습니다. KNN은 직관적이고 구현이 쉬우며, 데이터의 구조를 잘 반영할 수 있지만 고차원에서는 비효율적일 수 있다는 점도 유의해야 합니다.

결국 분류 모델을 선택할 때는 단순히 정확도만 보지 말고, 데이터의 특성과 해석 가능성, 처리 시간 등을 종합적으로 고려하여 의사결정하는 것이 중요합니다.