HSEOM GeckoHSEOM
Instagram

흑섬 TECH 블로그 - 데이터 기반 브리딩 기술

레오파드게코 브리딩에 데이터 분석과 AI 기술을 접목합니다. Python, NumPy를 활용한 체중 관리, 성장 추이 분석, 환경 데이터 시각화 등 실무에서 직접 사용하는 기술을 일반인도 이해하기 쉽게 설명합니다.

주요 카테고리

AI 카테고리

AI와 머신러닝을 활용한 레오파드게코 브리딩 기술과 데이터 분석 방법을 공유합니다.

28개의 글이 있습니다.

[머신러닝 중급 1편] 과적합과 과소적합 — 모델이 시험 문제만 외우면 생기는 일

처음 머신러닝을 배울 때 '과적합'이 뭔 소린지 감이 안 왔습니다. 잘 맞추면 좋은 거 아닌가? 근데, 직접 코드를 돌려보고 나서야 이해했던 경험이 있습니다. degree 하나 바꿨을 뿐인데 그래프가 미친 듯이 요동치는 걸 보고.. 과적합·과소적합의 차이, 편향-분산 트레이드오프, 학습 곡선까지 직접 실행하면서 정리합니다.

카테고리: AI

작성일: 2026-03-07T11:00:00

예상 읽기 시간: 20

Back to Tech
AI·20min read·

[머신러닝 중급 1편] 과적합과 과소적합 — 모델이 시험 문제만 외우면 생기는 일

처음 머신러닝을 배울 때 '과적합'이 뭔 소린지 감이 안 왔습니다. 잘 맞추면 좋은 거 아닌가? 근데, 직접 코드를 돌려보고 나서야 이해했던 경험이 있습니다. degree 하나 바꿨을 뿐인데 그래프가 미친 듯이 요동치는 걸 보고.. 과적합·과소적합의 차이, 편향-분산 트레이드오프, 학습 곡선까지 직접 실행하면서 정리합니다.

시작하며 — 시험 공부의 딜레마

솔직히 말하면, 처음 머신러닝을 배울 때 과적합이라는 단어가 와닿지 않았습니다.
"훈련 데이터에 너무 맞춰졌다"는 게 대체 무슨 뜻이지? 잘 맞추면 좋은 거 아닌가?
그러다 직접 모델을 돌려보고 나서야 이해했습니다.ㅋㅋ..

학교 다닐 때, 기출문제만 달달 외워서 모의고사 100점 맞는 친구 있었잖아요.
근데 실전 수능에서는 망하는 그 케이스.
문제를 외운 거지, 풀이법을 배운 게 아니었기 때문입니다.

머신러닝 모델도 똑같은 실수를 합니다.
훈련 데이터에 너무 딱 맞춰진 모델 — 이걸 과적합(Overfitting)이라고 해요.
이번 편에서는 제가 직접 코드를 돌려보면서 "아, 이게 과적합이구나" 느꼈던 과정을 같이 공유합니다.


과소적합 vs 적정 vs 과적합 — 한눈에 비교

과소적합 / 적정 / 과적합 모델 비교 — 다항 회귀 커브

다항 회귀(Polynomial Regression)로 세 가지 모델을 비교해봤습니다.
degree(차수) 값 하나 바꿨을 뿐인데, 모델 성격이 완전히 달라지더라고요.

degree=1 (과소적합) — 직선 하나로 전체를 설명. 너무 단순해서 패턴을 못 잡음
degree=5 (적정) — 데이터의 실제 패턴을 잘 따라감
degree=15 (과적합) — 노이즈까지 전부 외워서 구불구불. 새 데이터에서 망함
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import Pipeline
import numpy as np

# 각 degree별 모델 학습
for degree in [1, 5, 15]:
    model = Pipeline([
        ('poly', PolynomialFeatures(degree=degree)),
        ('linear', LinearRegression())
    ])
    model.fit(X_train, y_train)
    train_score = model.score(X_train, y_train)
    test_score  = model.score(X_test, y_test)
    print(f"degree={degree:2d} | train={train_score:.3f} | test={test_score:.3f}")

직접 주피터에서 돌려봤습니다. degree=1은 뭐.. 직선이라 패턴을 아예 못 잡고,
degree=15는 보자마자 "아 이건 아닌데" 싶었어요. 곡선이 미친 듯이 요동칩니다.

주피터 실행 결과 — 다항 회귀 degree=1, 5, 15 비교 그래프
왼쪽(degree=1)은 너무 심플해서 데이터 패턴을 놓치고,
오른쪽(degree=15)은 모든 점을 지나려고 난리를 치고 있죠.
가운데(degree=5)가 그나마 자연스럽게 흐름을 따라가는 적정 수준입니다.
처음 이 그래프를 봤을 때 과적합이 뭔지 바로 체감됐어요.

편향-분산 트레이드오프

위에서 과소적합과 과적합을 봤는데, 사실 이 둘은 동전의 양면입니다.
한쪽을 줄이면 다른 쪽이 올라가는 구조예요. 처음엔 "그냥 둘 다 줄이면 되는 거 아닌가?" 싶었는데,
공부할수록 그게 안 된다는 걸 깨달았습니다. 이걸 편향-분산 트레이드오프라고 합니다.

편향(Bias) — 모델이 얼마나 잘못된 가정을 하는가. 높으면 과소적합
분산(Variance) — 데이터가 조금 바뀌어도 예측이 크게 흔들리는가. 높으면 과적합
Total Error = Bias² + Variance + Irreducible Noise

모델을 복잡하게 만들면 편향은 낮아지지만 분산이 높아집니다.
반대로 단순하게 만들면 분산은 낮아지지만 편향이 높아집니다.
최적 지점을 찾는 것이 머신러닝의 핵심 과제입니다.


학습 곡선 — 과적합을 시각적으로 진단한다

학습 곡선 — train vs validation score

학습 곡선(Learning Curve)은 훈련 데이터 크기에 따른 train/validation 점수 변화를 보여줍니다.
두 곡선의 관계로 현재 상태를 진단할 수 있습니다.

두 곡선이 수렴 → 적정 (Good Fit)
두 곡선 모두 낮음 → 과소적합 (Underfitting)
두 곡선이 벌어짐 → 과적합 (Overfitting)

여기서 헷갈리기 쉬운 포인트가 하나 있습니다.
그래프 왼쪽(데이터가 적을 때)에도 두 곡선이 벌어져 있거든요. 근데 이건 과적합이 아닙니다.
학습 데이터가 적으면 train은 당연히 높고 val은 낮아요. 데이터가 늘면서 좁혀지는 건 정상적인 흐름입니다.

진짜 과적합 신호는 "좁혀지다가 다시 벌어지는" 구간입니다.
데이터를 더 줘도 갭이 안 줄거나, 오히려 다시 커지기 시작하면 — 그게 과적합이 시작된 지점이에요.
위 그래프에서 빨간 영역이 바로 그 구간입니다.

from sklearn.model_selection import learning_curve
import matplotlib.pyplot as plt
import numpy as np

train_sizes, train_scores, val_scores = learning_curve(
    model, X, y,
    train_sizes=np.linspace(0.1, 1.0, 7),
    cv=5,
    scoring='accuracy'
)

train_mean = train_scores.mean(axis=1)
val_mean   = val_scores.mean(axis=1)

plt.plot(train_sizes, train_mean, label='Train score', color='#4FD1C5')
plt.plot(train_sizes, val_mean,   label='Validation score', color='#E6BE50')
plt.xlabel('Training set size')
plt.ylabel('Score')
plt.legend()
plt.show()

직접 돌려보니까 이런 결과가 나왔습니다. 처음에는 "이게 뭐지?" 싶었는데, 잘 보면 재밌어요.

주피터 실행 결과 — 학습 곡선 (Train error vs Validation error)
데이터가 적을 때는 Train error와 Validation error 차이가 확 벌어집니다.
데이터가 늘어나면서 두 곡선이 점점 가까워지는 게 보이죠?
이게 안 좁혀지고 계속 벌어져 있으면 — 과적합 신호입니다.
저도 처음엔 그래프만 봐서는 감이 안 왔는데, 직접 degree를 바꿔가면서 학습 곡선을 여러 번 그려보니까 확실히 느껴지더라고요.

과적합 해결 방법 4가지

과적합 해결 방법 4가지 — 데이터 증강, 정규화, 모델 단순화, 교차검증

과적합을 잡는 방법은 여러 가지가 있는데, 실제로 써보니 상황에 따라 효과가 다릅니다.
제가 정리한 4가지 방법입니다.

1. 더 많은 데이터

가장 확실한 해결책입니다. 데이터가 다양할수록 모델이 패턴을 제대로 배울 확률이 올라가요.
현실에서는 데이터를 무한정 구할 수 없으니 데이터 증강(Augmentation)으로 보완하는 경우가 많습니다.

2. 정규화 (Regularization)

가중치에 패널티를 부여해서 모델이 너무 복잡해지지 않도록 막는 방법입니다.
L1(Lasso)은 불필요한 특성을 아예 제거하고, L2(Ridge)는 가중치를 전체적으로 줄여요.
이 부분은 내용이 많아서 다음 편(3편)에서 따로 정리할 예정입니다.

3. 모델 단순화

결정 트리 깊이를 제한하거나, 특성 수를 줄이거나, 뉴럴넷 레이어를 줄이는 방법입니다.
max_depth, max_features 같은 파라미터를 조절하면 됩니다.
위에서 degree=15를 5로 낮춘 것도 결국 모델 단순화의 한 예시입니다.

4. 교차 검증 (Cross-Validation)

데이터를 여러 묶음으로 나눠서 돌아가며 학습/검증을 반복하는 방법입니다.
한 번의 train/test 분리보다 훨씬 안정적인 성능 측정이 가능합니다.

from sklearn.model_selection import cross_val_score

scores = cross_val_score(model, X, y, cv=5, scoring='accuracy')
print(f"CV scores: {scores}")
print(f"Mean: {scores.mean():.3f} ± {scores.std():.3f}")

정리

처음에 과적합이라는 개념이 추상적으로 느껴졌는데,
직접 degree를 바꿔가면서 그래프를 그려보니까 바로 이해가 됐습니다.
역시 머신러닝은 직접 돌려봐야 감이 와요.

1. 과적합 — 훈련 데이터에 너무 맞춰져서 새 데이터에서 실패한다
2. 학습 곡선 — train/validation 점수 차이로 지금 모델 상태를 진단할 수 있다
3. 해결책 — 데이터 늘리기 / 정규화 / 모델 단순화 / 교차검증

다음 편(2편)에서는 서포트 벡터 머신(SVM)을 다룹니다.
두 그룹 사이의 가장 넓은 길을 찾는 알고리즘인데, 마진 최대화와 커널 트릭 개념이 생각보다 직관적이에요.
다음 편에서 같이 정리해보겠습니다.

#과적합#과소적합#편향분산트레이드오프#교차검증#학습곡선#sklearn#python