비선형 회귀 모델 선택: 다항식·스플라인·GAM의 적용 기준
비선형 회귀에서 다항 회귀, 스플라인 회귀, GAM을 선택하는 기준과 복잡도 제어, 검증 및 운영 진단 방법을 정리한다.
2026-08-14 · 최초 발행 2025-10-14
직선 가정이 깨지는 지점에서 모델을 고른다
입력과 출력의 관계가 직선으로 설명되지 않을 때 사용하는 회귀 접근을 비선형 회귀라고 부른다. 매개변수에는 선형이지만 기저함수로 입력을 확장하는 모델과, 매개변수 자체에도 비선형인 모델로 나눌 수 있다. 실무에서는 해석 가능성과 안정성을 이유로 기저함수 기반의 선형-매개변수 모델을 주로 사용한다.
다항 회귀는 원 변수의 거듭제곱과 상호작용 항을 추가해 비선형성을 근사한다. 차수가 높아질수록 표현력은 커지지만 과적합과 수치 불안정성도 함께 증가하므로 표준화와 Ridge/Lasso 정규화가 필요하다.
스플라인 회귀는 구간별 다항식을 매끄럽게 이어 유연한 함수 형태를 만든다. 고정 노드와 저차 다항식을 사용하는 회귀 스플라인, 곡률 패널티와 λ로 매끄러움을 제어하는 평활 스플라인으로 구분할 수 있다. 자연 스플라인은 경계 조건을 둬 외삽 안정성을 높이는 선택지다.
GAM(Generalized Additive Models)은 다음과 같은 가법 구조를 사용한다.
g(E[y|x]) = β0 + Σ fj(xj)
각 fj는 스플라인 같은 매끄러운 함수로 추정하며, 가우시안·포아송·이항 등의 분포와 log, logit 등의 링크 함수를 선택할 수 있다. 벌점화 회귀와 백피팅으로 추정하고, 효과적 자유도(EDF)로 복잡도를 관리한다.
유연성은 제어 장치와 함께 써야 한다
입력 공간은 다항식, B-스플라인, 자연 스플라인 같은 기저함수로 확장한다. Ridge/Lasso 정규화나 매끄러움 패널티는 분산을 낮추고 과적합을 억제하는 역할을 한다.
복잡도를 조절하는 핵심 값은 다항 차수 p, 스플라인의 매듭 수와 위치, 평활화 계수 λ, GAM의 EDF다. 교차검증, GCV, AICc를 이용해 데이터에 맞는 값을 탐색한다.
GAM과 스플라인은 변수별 부분효과 곡선을 확인할 수 있어 해석에 유리하다. 단조성이나 볼록성 같은 형태 제약을 적용하면 도메인 지식을 반영하면서 모델을 더 안정적으로 만들 수 있다.
고차 다항식은 다중공선성과 수치 불안정성에 취약하다. 스플라인과 GAM은 국소적인 유연성과 패널티를 제공하지만, 변수 수와 기저 수가 늘수록 계산 비용도 증가한다.
탐색·검증·배포로 이어지는 모델링 흐름
데이터를 적재한 뒤 누락치와 이상치를 처리하고 표준화 계획을 세운다. 목표 변수의 분포를 확인해 손실과 링크 가정을 정한다.
비선형성은 잔차와 예측치의 관계, 변수별 LOWESS, 상호작용 스캔으로 점검한다. 모델은 다항 회귀에서 스플라인, GAM 순으로 복잡도를 높여 탐색한다. 차수·매듭·λ·EDF는 CV와 GCV로 선택하고, 정규화 또는 패널티를 적용한 뒤 변수 중요도와 부분효과를 확인한다.
성능은 K-Fold로 검증하며, 시계열에서는 롤링 CV를 사용한다. 잔차의 독립성·등분산성, 외삽 민감도, 과적합 여부를 진단한 뒤 추정 파이프라인을 고정한다. 배포 단계에서는 입력 검증과 모니터링 지표도 함께 구성한다.
과적합이 나타나면 λ를 높이고 차수나 매듭을 줄이며 조기종료를 적용한다. 경계 밖의 외삽이 불안정하면 자연 스플라인이나 입력 클리핑을 검토한다. 다중공선성에는 정규화 강화, 기저 수 축소, 변수 선택이 대응 수단이다. GAM의 동시상관(concurvity)은 기저 차수를 낮추고 상호작용을 최소화하는 방식으로 다룬다.
반응곡선부터 리스크 스코어까지
마케팅 반응곡선에서는 지출 대비 수익의 체감효과를 GAM이나 스플라인으로 추정해 채널별 한계수익을 계산한다. 이는 예산 배분 최적화와 증분 리프트 추정에 활용할 수 있다.
전환 확률과 클릭률 예측에는 이항 GAM(Logit)을 적용해 비선형 효과를 반영할 수 있다. 부분효과를 통해 임계 구간을 파악하고, 피처 스케일링 부담을 줄이면서 해석 가능성도 확보한다.
수요나 부하 예측에서는 온도·프로모션처럼 시계열 외 요인이 미치는 비선형 효과를 스플라인으로 모델링한다. 외삽 안정성이 중요하면 자연 스플라인을 적용한다.
의료·신용 리스크 스코어링에서는 단조 제약 GAM으로 임상·규제 친화적인 모델을 구성할 수 있다. 과적합 통제와 설명 책임 강화가 함께 요구되는 경우에 적합하다.
모델별 강점과 운영 부담
| 항목 | 다항 회귀 | 스플라인 회귀 | GAM |
|---|---|---|---|
| 표현력/유연성 | 중간(차수↑ 시 증가) | 높음(국소 적응) | 높음(변수별 비선형+분포/링크) |
| 해석 가능성 | 중간(계수 해석 난해) | 높음(부분효과 곡선) | 높음(부분효과·EDF) |
| 안정성/외삽 | 낮음(고차수 민감) | 중간~높음(자연 스플라인) | 중간(가법 구조, 경계 주의) |
| 일관성/정규화 | Ridge/Lasso 필수 | 평활 패널티/매듭 선택 | 평활 패널티·백피팅 |
| 운영 편의 | 매우 쉬움 | 보통(매듭/λ 관리) | 보통(분포/링크/EDF 관리) |
| 확장성/속도 | 빠름 | 빠름~보통(기저 수 의존) | 보통(데이터·기저 수 의존) |
Python으로 비교하는 다항 회귀·스플라인·GAM
전제조건은 Python 3.10+, scikit-learn ≥ 1.3, pyGAM ≥ 0.8.0, numpy/pandas다. 예제는 2개 변수 X와 연속형 y를 사용한다.
# pip install scikit-learn pygam numpy pandas
import numpy as np
from sklearn.model_selection import KFold, cross_val_score
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler, PolynomialFeatures
from sklearn.linear_model import RidgeCV
from sklearn.preprocessing import SplineTransformer
from pygam import LinearGAM, s
# 샘플 데이터 생성
rng = np.random.RandomState(42)
n = 1500
x1 = np.linspace(0, 10, n)
x2 = rng.uniform(0, 5, n)
y = 3*np.sin(x1) + 0.5*(x2-2.5)**2 + rng.normal(0, 0.5, n)
X = np.c_[x1, x2]
cv = KFold(n_splits=5, shuffle=True, random_state=42)
# 1) 다항 회귀 + Ridge
poly_model = Pipeline([
("poly", PolynomialFeatures(degree=4, include_bias=False)),
("scaler", StandardScaler()),
("ridge", RidgeCV(alphas=np.logspace(-3, 3, 13), cv=cv))
])
poly_rmse = (-cross_val_score(poly_model, X, y, cv=cv,
scoring="neg_root_mean_squared_error")).mean()
poly_model.fit(X, y)
# 2) 스플라인 회귀 (B-스플라인 + Ridge)
spline_model = Pipeline([
("spline", SplineTransformer(degree=3, n_knots=12, knots="quantile",
extrapolation="linear")), # 경계 안정성
("ridge", RidgeCV(alphas=np.logspace(-3, 3, 13), cv=cv))
])
spline_rmse = (-cross_val_score(spline_model, X, y, cv=cv,
scoring="neg_root_mean_squared_error")).mean()
spline_model.fit(X, y)
# 3) GAM (가우시안, 가법 스무딩)
gam = LinearGAM(s(0, n_splines=15) + s(1, n_splines=10))
gam.gridsearch(X, y, lam=np.logspace(-2, 3, 10), cv=cv)
# RMSE 계산
from sklearn.metrics import mean_squared_error
gam_rmse = np.mean([
mean_squared_error(y[te], gam.fit(X[tr], y[tr]).predict(X[te]), squared=False)
for tr, te in cv.split(X)
])
print(f"RMSE | Polynomial+Ridge: {poly_rmse:.3f}, Spline+Ridge: {spline_rmse:.3f}, GAM: {gam_rmse:.3f}")
다항 회귀에서는 고차수를 피하고 일반적으로 ≤ 4를 유지하며, 상호작용은 최소화하고 Ridge를 우선 적용한다. 스플라인은 매듭을 분위수 기반으로 초기화하고 자연 또는 선형 외삽을 선택해 경계를 안정화한다. GAM은 과도한 EDF를 피하고 변수 수가 늘면 기저 수를 제어하며 동시상관 진단(concurvity)을 수행한다.
성능 개선과 설명 가능성의 균형
데이터와 도메인에 따라 RMSE/MAE는 1030% 개선되고, AUC/LogLoss는 0.020.05p 수준의 개선 폭을 기대할 수 있다. 자연 스플라인을 외삽 구간에 적용하면 예측 분산이 20% 이상 감소하는 사례도 빈발한다.
부분효과를 기반으로 설명력을 높이고 임계점과 포화 효과를 명시적으로 식별할 수 있다. 패널티 기반의 복잡도 제어는 재현 가능성과 배포 안정성에도 기여한다.
다항 회귀는 단순한 근사에, 스플라인은 국소적 유연성에, GAM은 가법 구조와 분포·링크의 유연성에 강점이 있다. 기저 설계와 복잡도 제어를 중심에 두고, 자연 스플라인·정규화·제약을 조합해 안정성과 성능을 함께 관리한다.