
머신러닝을 처음 배울 때 가장 많이 마주치는 예제가 붓꽃(Iris) 데이터셋 분류입니다. 하지만 대부분의 글이 KNN이나 로지스틱 회귀 하나만 다루고 끝나서, “그래서 어떤 알고리즘이 더 나은지”는 알기 어렵습니다. 이 글에서는 scikit-learn으로 만드는 첫 분류 모델을 목표로, 로지스틱 회귀·KNN·결정트리·SVM·랜덤포레스트 5개 알고리즘을 동일한 조건에서 학습시키고 정확도를 직접 비교합니다. 코드를 그대로 실행해 볼 수 있도록 전체 스크립트와 예상 출력까지 정리했습니다.
붓꽃 데이터셋과 실험 설계
붓꽃 데이터셋은 sklearn.datasets.load_iris()로 불러올 수 있는 내장 데이터로, 꽃받침 길이·너비, 꽃잎 길이·너비 4개 특성(feature)과 Setosa·Versicolor·Virginica 3개 품종(target)으로 구성됩니다. 샘플 수는 150개, 품종별로 정확히 50개씩 균등하게 들어 있어 클래스 불균형 문제 없이 분류 알고리즘 비교 실습에 적합합니다.
공정한 비교를 위해 다섯 개 모델 모두 같은 train_test_split 결과를 사용해야 합니다. random_state를 고정하지 않으면 알고리즘 간 차이가 아니라 데이터 분할 차이 때문에 정확도가 달라질 수 있기 때문입니다. 아래 코드에서는 test_size=0.2, random_state=42로 고정해서 전체 150개 중 120개를 학습, 30개를 테스트에 사용합니다.
비교 대상은 LogisticRegression, KNeighborsClassifier, DecisionTreeClassifier, SVC, RandomForestClassifier 다섯 가지입니다. 모두 scikit-learn의 fit(X_train, y_train) → predict(X_test) 파라다임을 동일하게 따르기 때문에, 반복문 하나로 5개 모델을 한 번에 학습시키고 평가할 수 있습니다.
5개 알고리즘 동시 학습 코드
아래 코드는 데이터 로드부터 5개 모델 학습, 정확도 산출까지 전체 과정을 담고 있습니다. accuracy_score로 정확도를 계산하고, 딕셔너리에 모델명과 결과를 저장해 마지막에 한 번에 출력합니다.

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
# 데이터 로드
iris = load_iris()
X, y = iris.data, iris.target
# 학습/테스트 분할 (8:2, 고정 시드)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
models = {
"LogisticRegression": LogisticRegression(max_iter=200),
"KNN(k=5)": KNeighborsClassifier(n_neighbors=5),
"DecisionTree": DecisionTreeClassifier(random_state=42),
"SVM(rbf)": SVC(kernel="rbf"),
"RandomForest": RandomForestClassifier(n_estimators=100, random_state=42),
}
results = {}
for name, model in models.items():
model.fit(X_train, y_train)
pred = model.predict(X_test)
acc = accuracy_score(y_test, pred)
results[name] = acc
for name, acc in sorted(results.items(), key=lambda x: -x[1]):
print(f"{name:20s} accuracy = {acc:.4f}")
LogisticRegression에 max_iter=200을 준 이유는 기본값(100)으로는 수렴 경고(ConvergenceWarning)가 뜰 수 있기 때문입니다. 특성 스케일을 표준화하지 않은 상태에서는 반복 횟수를 늘려주는 편이 안전합니다.
정확도 비교 결과와 해석
random_state=42로 고정한 위 코드를 실행하면, 붓꽃처럼 클래스 간 경계가 비교적 뚜렷한 데이터에서는 5개 모델 모두 테스트셋(30개 샘플) 기준 90% 이상의 높은 정확도를 보이는 것이 일반적입니다. 특히 Setosa 품종은 다른 두 품종과 꽃잎 크기 차이가 커서 어떤 알고리즘을 쓰든 거의 100% 분류되고, 정확도 차이는 대부분 Versicolor와 Virginica를 구분하는 경계 부근 샘플에서 갈립니다.
| 알고리즘 | 핵심 아이디어 | 이 실험에서의 특징 |
|---|---|---|
| LogisticRegression | 선형 결정 경계 + 시그모이드 | 특성이 선형적으로 잘 분리되는 붓꽃에서 안정적 |
| KNN | 가까운 k개 이웃의 다수결 | n_neighbors 값에 따라 결과가 민감하게 변함 |
| DecisionTree | 특성 기준 분기 반복 | 해석은 쉽지만 과적합 위험 존재 |
| SVM(rbf) | 커널로 비선형 경계 형성 | 소규모 데이터에서 정확도가 높게 나오는 경우가 많음 |
| RandomForest | 여러 트리의 앙상블 | 단일 트리보다 일반화 성능이 안정적 |
실제로 결과 차이를 만들고 싶다면 n_neighbors를 3~15 사이로 바꿔보거나, test_size를 0.3으로 늘려 테스트 샘플 수를 45개로 키워보는 것을 추천합니다. 테스트 샘플이 30개뿐이면 한두 개 오분류만으로도 정확도가 3.3%p씩 뛰기 때문에, 알고리즘 성능 차이보다 표본 크기 효과가 더 크게 보일 수 있습니다.
교차 검증으로 더 신뢰도 높이기
단일 train_test_split 결과만으로 알고리즘 우열을 판단하는 것은 위험합니다. 분할 방식(seed)이 바뀌면 순위가 뒤바뀔 수 있기 때문입니다. 이를 보완하는 방법이 cross_val_score를 이용한 K-폴드 교차 검증입니다.
from sklearn.model_selection import cross_val_score
for name, model in models.items():
scores = cross_val_score(model, X, y, cv=5)
print(f"{name:20s} mean={scores.mean():.4f} std={scores.std():.4f}")

cv=5는 데이터를 5등분해서 매번 다른 4개 폴드로 학습하고 나머지 1개 폴드로 검증하는 방식입니다. 이렇게 하면 5번의 정확도 평균과 표준편차를 함께 얻을 수 있어, 특정 분할에서 우연히 잘 맞은 것인지 실제로 안정적인 성능인지 구분할 수 있습니다. 표준편차가 크게 나오는 모델은 데이터 분할에 민감하다는 뜻이므로, 실무에 적용하기 전에는 평균 정확도뿐 아니라 표준편차도 함께 확인하는 것이 좋습니다.
scikit-learn 공식 문서의 지도학습 알고리즘 목록과 model_selection 모듈 문서에서 각 모델의 하이퍼파라미터와 교차 검증 옵션을 더 자세히 확인할 수 있습니다.
마무리: 다음 단계로 무엇을 해볼까
지금까지 load_iris()로 데이터를 불러와 5개 분류 알고리즘을 동일한 조건에서 학습시키고, accuracy_score와 cross_val_score 두 가지 방식으로 성능을 비교하는 과정을 다뤘습니다. 붓꽃 데이터는 클래스가 뚜렷하게 구분되는 편이라 대부분의 알고리즘이 높은 정확도를 내지만, 실제 데이터에서는 이런 차이가 훨씬 크게 벌어집니다.
다음 단계로는 StandardScaler로 특성을 표준화한 뒤 같은 비교를 다시 해보거나, confusion_matrix로 어떤 품종이 서로 헷갈리는지 구체적으로 확인해보는 것을 추천합니다. 또한 GridSearchCV를 이용해 KNN의 n_neighbors나 SVM의 C, gamma 값을 탐색해보면, 하이퍼파라미터 튜닝이 정확도에 미치는 영향을 직접 체감할 수 있습니다.
자주 묻는 질문(FAQ)
Q1. 정확도가 알고리즘마다 똑같이 나오는데 정상인가요?
붓꽃 데이터는 샘플 수가 적고(150개) 클래스 간 구분이 뚜렷해서, 테스트셋이 30개일 경우 여러 알고리즘이 동일한 정확도를 보이는 것이 흔합니다. 차이를 보고 싶다면 cross_val_score로 여러 번 검증하거나 test_size를 조정해보세요.
Q2. 어떤 알고리즘을 실무에서 우선 써야 하나요?
데이터셋 크기, 특성 개수, 해석 필요 여부에 따라 다릅니다. 해석이 중요하면 DecisionTree나 LogisticRegression, 성능과 안정성이 우선이면 RandomForest나 SVM을 먼저 시도해보는 것이 일반적인 접근입니다.
Q3. max_iter 경고는 왜 나오고 어떻게 해결하나요?
LogisticRegression은 내부적으로 반복 최적화(기본 solver는 lbfgs)를 수행하는데, 특성 스케일이 크거나 반복 횟수가 부족하면 수렴하지 못했다는 ConvergenceWarning이 발생합니다. max_iter 값을 늘리거나 StandardScaler로 특성을 표준화하면 대부분 해결됩니다.