회귀 분석에서 선형·로지스틱 모델을 진단하는 방법

선형·로지스틱 회귀의 가정과 VIF, 잔차 진단, 칼리브레이션을 함께 점검하는 회귀 분석 실무 흐름을 정리한다.

2026-08-14 · 최초 발행 2025-10-14

회귀 모델의 품질은 진단 과정에서 결정된다

회귀 분석은 연속형 또는 이진형 타깃과 설명변수의 관계를 정량화하는 방법이다. 단순·다중 선형 회귀와 로지스틱 회귀를 선택한 뒤에는 계수만 해석할 것이 아니라, 다중공선성·잔차·칼리브레이션까지 연결해 검증해야 한다.

선형 회귀는 연속형 타깃과 1개 또는 여러 설명변수의 선형 관계를 추정한다. 최소제곱법(OLS)으로 계수를 구하며, 선형성·독립성·등분산성·정규성·무공선성을 가정한다.

로지스틱 회귀는 이진 타깃의 로그오즈(logit)를 선형 모델로 다룬다. 확률은 P(y=1|x)=σ(Xβ)로 표현하며 최대우도추정(MLE)을 사용한다. 로그오즈와 특징 사이의 선형성, 독립성, 무공선성이 주요 가정이다.

공선성과 잔차를 모델 학습 과정에 포함하기

VIF(Variance Inflation Factor)는 설명변수 간 다중공선성의 정도를 수치화한다.

VIF_j = 1 / (1 - R_j^2)

VIF>5는 경고 신호이며, >10은 심각한 공선성으로 보고 변수 제거·변환·정규화를 고려한다. 공선성이 높으면 계수의 분산이 커지고 결과가 불안정해질 수 있다. 변수를 결합하거나 주성분을 이용해 차원을 줄이고, Ridge·Lasso·ElasticNet 같은 정규화 기법을 적용하는 방식이 있다. 다만 정규화는 해석성을 낮추는 대신 일반화 성능과 안정성을 높이는 트레이드오프가 있다.

데이터 전처리 단계에서는 결측치 처리, 스케일링, 범주 인코딩, 상호작용항과 다항항 설계가 함께 이뤄진다. 선형성·등분산성·독립성 가정이 맞지 않으면 로그·Box-Cox 변환, 가중회귀, 강건 추정을 적용할 수 있다. 로지스틱 회귀에서 클래스 불균형이 있으면 class_weight, 리샘플링, 임계값 최적화로 보정한다.

선형 회귀의 계수는 타깃 조건부 기댓값의 변화량을 추정한 값이다. 신뢰구간과 유의성(p-value)으로 영향력을 검토하되, R^2·MAE·RMSE 같은 예측 성능과 가정 진단을 분리하지 않아야 한다. 로지스틱 회귀의 계수는 오즈비 Exp(β)로 읽을 수 있으며, 성능은 AUC·LogLoss·F1로 보고 비용민감도에 따라 분류 임계값을 조정한다.

연속값 예측과 이진 분류에서 달라지는 점

구분 선형 회귀 로지스틱 회귀
타깃 유형 연속형 이진형
목적함수 SSE 최소화(OLS) 로그우도 최대화
핵심 가정 선형성, 등분산, 정규성, 독립성 로그오즈-특징 선형성, 독립성
평가 지표 R^2, RMSE/MAE AUC, LogLoss, F1/PR
이상치 민감도 큼(제곱오차) 중간(로그우도), 완전분리에 민감
운영 편의 해석 용이, 가정 위배 시 왜곡 임계값/칼리브레이션 필요, 분류 임계 관리

적합·진단·개선을 순환시키는 흐름

연속 타깃이진 타깃아니오입력 데이터전처리: 결측/스케일/인코딩VIF 계산 특징 선택/정규화문제 유형선형 회귀 적합(OLS/WLS)로지스틱 회귀 적합(정규화옵션)잔차 진단: Q-Q, BP, DW,Cook진단: AUC, 칼리브레이션,deviance 잔차이상/가정 위배?조치:변수/변환/정규화/강건/재표본교차검증/검증셋 성능배포: 스케일러+모델파이프라인모니터링: 드리프트/PSI, 성능경보

잔차의 패턴과 분포, 영향점을 확인한 결과는 데이터 변환·특징 재설계·이상치 처리·강건 추정으로 이어진다. 교차검증과 부트스트랩을 통해 불확실성을 추정하고, 재현 가능한 개선 주기를 만드는 것이 운영 단계의 핵심이다.

선형 회귀에서 VIF와 잔차를 확인하는 코드

전제조건은 Python 3.10+, numpy, pandas, scikit-learn 1.3+, statsmodels 0.14+, matplotlib, seaborn이다.

설치 예: pip install numpy pandas scikit-learn statsmodels matplotlib seaborn

import numpy as np, pandas as pd, matplotlib.pyplot as plt, seaborn as sns
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import statsmodels.api as sm
from statsmodels.stats.outliers_influence import variance_inflation_factor, OLSInfluence
from statsmodels.stats.diagnostic import het_breuschpagan
from statsmodels.stats.stattools import durbin_watson

# 데이터 로드
data = fetch_california_housing(as_frame=True)
X = data.frame.drop(columns=['MedHouseVal'])
y = data.frame['MedHouseVal']

# 스케일링(계수 안정화 및 VIF 계산 편의)
scaler = StandardScaler()
X_scaled = pd.DataFrame(scaler.fit_transform(X), columns=X.columns)

# VIF 계산
vif_df = pd.DataFrame({
    'feature': X_scaled.columns,
    'VIF': [variance_inflation_factor(X_scaled.values, i) for i in range(X_scaled.shape[1])]
})
print(vif_df.sort_values('VIF', ascending=False))

# 학습/검증 분리
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)

# OLS 적합
X_train_const = sm.add_constant(X_train)
ols = sm.OLS(y_train, X_train_const).fit()
print(ols.summary())

# 잔차 진단
resid = ols.resid
fig, ax = plt.subplots(1, 2, figsize=(10,4))
sns.scatterplot(x=ols.fittedvalues, y=resid, ax=ax[0])
ax[0].axhline(0, color='red'); ax[0].set_title('잔차 vs 예측값'); ax[0].set_xlabel('Fitted'); ax[0].set_ylabel('Residuals')
sm.qqplot(resid, line='45', ax=ax[1]); ax[1].set_title('Q-Q Plot')
plt.tight_layout(); plt.show()

# 등분산성(Breusch-Pagan), 독립성(Durbin-Watson)
bp = het_breuschpagan(resid, X_train_const)
print(f'Breusch-Pagan: LM={bp[0]:.3f}, p={bp[1]:.3g}, F={bp[2]:.3f}, p={bp[3]:.3g}')
dw = durbin_watson(resid)
print(f'Durbin-Watson={dw:.3f}')

# 영향점(Cook's distance)
influence = OLSInfluence(ols)
cooks = influence.cooks_distance[0]
print('Cook top-5 indices:', np.argsort(cooks)[-5:][::-1])

VIF>5인 변수는 제거하거나 결합하고, Ridge 회귀로 정규화할 수 있다. Breusch-Pagan 검정이 유의하면 HC3 강건 표준오차 또는 WLS를 검토한다. Q-Q 플롯의 편차가 크면 로그·Box-Cox 변환과 이상치 점검이 필요하다.

확률 예측은 칼리브레이션까지 확인한다

from sklearn.datasets import load_breast_cancer
from sklearn.pipeline import make_pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score, roc_curve, PrecisionRecallDisplay

X, y = load_breast_cancer(return_X_y=True, as_frame=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, random_state=42)

# 스케일링 포함 파이프라인 + L2 정규화
clf = make_pipeline(StandardScaler(),
                    LogisticRegression(max_iter=200, penalty='l2', solver='lbfgs'))
clf.fit(X_train, y_train)

proba = clf.predict_proba(X_test)[:,1]
auc = roc_auc_score(y_test, proba)
print(f'AUC={auc:.3f}')

fpr, tpr, _ = roc_curve(y_test, proba)
plt.plot(fpr, tpr, label=f'AUC={auc:.3f}')
plt.plot([0,1],[0,1],'--', color='gray'); plt.legend(); plt.xlabel('FPR'); plt.ylabel('TPR'); plt.title('ROC'); plt.show()

# 임계값 조정 예시(Youden J 최대)
youden_idx = np.argmax(tpr - fpr)
print('Best threshold (Youden):', _[youden_idx])

# 참고: 완전분리 발생 시 solver='liblinear' 또는 C 감소(강한 정규화) 권장

클래스 불균형이 심하면 class_weight='balanced' 또는 재표본(SMOTE)을 적용하고 임계값을 최적화한다. 완전분리가 감지되면 강한 정규화(C↓), 특성 축소, 페널티 로지스틱을 고려한다.

예측과 의사결정에 쓰이는 회귀 분석

회귀 분석은 매출·수요 같은 연속값을 예측하고, 프로모션·계절성을 반영하거나 가격 탄력성을 추정하는 데 사용된다. 전환 확률과 이탈 위험을 예측해 마케팅 캠페인 대상을 정하고, 임계값으로 비용을 최소화하는 용도에도 적합하다.

신용·리스크 스코어링에서는 부도 확률 PD를 추정하고 칼리브레이션을 유지하며, 규제 준수에 필요한 해석 가능성을 확보한다. 제조 현장에서는 공정 변수와 결함률 또는 특성치의 관계를 분석해 개선 요인을 찾고, 이상치와 변동성을 통제한다. 의료·헬스케어에서는 이진 진단 보조에 쓰이며 ROC-AUC와 감도-특이도 균형, 칼리브레이션을 통해 임상적 신뢰도를 점검한다.

회귀 모델 도입 시 기존 규칙 기반 대비 MAE 1030% 감소, 분류 AUC 0.050.15p 향상이 가능하며 도메인과 데이터 품질에 의존한다. 임계값 최적화와 칼리브레이션은 비용 대비 이익을 높이고 오탐·미탐 비용을 5~20% 절감할 수 있다. 변수 영향 해석은 정책과 전략 의사결정의 근거가 되며, 표준화된 진단 절차는 모델의 신뢰성·재현성과 데이터 거버넌스를 높여 운영 위험을 줄인다.

회귀 분석선형 회귀로지스틱 회귀다중공선성잔차 진단VIF