포아송 회귀 (Poisson regression): y가 계수(count)일 때, 직선은 1.4회의 통화를 예측하지만 로그 연결
요약
계수(count) 데이터를 다룰 때 발생하는 OLS의 한계를 설명하고, 이를 해결하기 위한 포아송 회귀(Poisson regression)의 원리를 다룹니다. 로그 연결 함수를 통해 예측값이 항상 양수가 되도록 보장하며, 로그 가능도 극대화를 통한 최적화 과정을 설명합니다.
핵심 포인트
- 계수 데이터는 음수가 될 수 없고 분산이 평균에 따라 변하는 특성이 있음
- 로그 연결 함수(log-link)를 사용하여 예측값을 (0, ∞) 범위로 제한
- 최소제곱법 대신 로그 가능도(log-likelihood) 극대화 방식을 사용
- 포아송 회귀의 기울기(gradient)는 관측값과 예측값의 잔차를 이용한 단순한 형태로 수렴
당신의 타겟이 통화 횟수, 결함, 목표, 청구, 웹사이트 방문과 같은 _계수 (count)_인 순간, 직선은 조용히 거짓말을 합니다. 계수는 음수가 아닌 정수이며, 값이 작을 때 왜곡(skewed)되어 있고, 분산(variance)은 평균과 함께 커집니다. 최소제곱법 (Ordinary Least Squares, OLS)을 적용하면 모델은 기꺼이 -1.4회의 통화를 예측하고 노이즈가 고정된 대칭형 종 모양이라고 가정할 것입니다. 이 두 가지 모두 틀렸습니다. 포아송 회귀 (Poisson regression)는 정확히 이 문제를 위해 구축된 일반화 선형 모델 (Generalized Linear Model, GLM)이며, 저는 사용자가 직접 데이터를 배치할 수 있는 plain-JS 경사 상승법 (gradient ascent)을 사용하여 브라우저에서 실시간으로 이를 적합시키는 데모를 만들었습니다. 다음은 이 과정에서 제가 배운 내용입니다.
모델: 음수가 될 수 없는 로그 연결 함수 (log-link)
각 관측치가 yᵢ ~ Poisson(λᵢ)에서 추출된다고 가정합니다. 선형 예측값 (linear predictor) η = β₀ + β₁x는 어떤 실수든 될 수 있습니다. 따라서 평균에 **로그 연결 함수 (log-link)**를 적용하여 log λ = η로 만들고, 역함수인 λ = e^η를 통해 이를 (0, ∞) 범위로 압축합니다. 계수가 무엇이든 상관없이 기대 계수 (expected count)는 항상 유효한 양의 비율 (positive rate)이 됩니다.
def eta(beta, X): return X @ beta # β₀ + β₁x, 어떤 실수든 가능
def rate(beta, X): return np.exp(eta(beta, X)) # λ = e^η (항상 > 0)
적합 (Fitting) = 포아송 로그 가능도 (Poisson log-likelihood) 극대화
여기에는 최소제곱법이 없습니다. 모델이 관측된 계수에 할당하는 확률을 극대화합니다:
def log_likelihood(beta, X, y):
lam = rate(beta, X)
return np.sum(y * np.log(lam) - lam - gammaln(y + 1))
log(y!) 항은 β에 대해 상수이므로 최적점(optimum)을 이동시키지 않습니다. 이 항은 단지 숫자가 진정한 로그 가능도 (log-likelihood)가 되도록 하기 위해 존재합니다.
기울기 (gradient)는 하나의 아름다운 공식으로 수렴한다
이를 미분하면 복잡한 연쇄 법칙 (chain rule)이 로그 연결 함수 덕분에 완벽하게 상쇄되어, 다음과 같은 "점수 (score)"만 남습니다:
def gradient(beta, X, y):
lam = rate(beta, X)
return X.T @ (y - lam) # ∇LL = Xᵀ(y − λ)
그것은 잔차(residual) — 관측된 계수(observed count)에서 예측된 계수(predicted count)를 뺀 값 — 에 의해 가중치가 부여된 각 특성(feature) 행의 합입니다. 이를 0으로 설정하는 것이 최대 가능도 조건(maximum-likelihood condition)이며, 이는 Σyᵢ = Σλᵢ를 강제합니다. 즉, 적합된 총합(fitted totals)이 관측된 총합(observed totals)과 일치하게 됩니다. 놀라운 점은 선형 회귀(linear regression)와 로지스틱 회귀(logistic regression)가 Xᵀ(y − μ)라는 정확히 동일한 기울기(gradient) 형태를 가진다는 것입니다. y의 분포를 선택하고, β·x를 적절한 범위로 매핑하는 연결 함수(link function)를 선택하면, 당신은 전체 일반화 선형 모델(GLM) 가족을 설명하게 됩니다.
올라가기 — 가능도(likelihood)는 오목(concave)하므로 정점이 하나뿐입니다
경사 상승법(Gradient ascent)은 단 하나의 전역 최댓값(global maximum)을 향해 곧장 언덕 위로 걸어 올라갑니다. 손으로 그린 데이터에서도 완벽하게 작동하게 하려면 두 가지를 고려하십시오. 먼저 좌표들이 동일한 스케일을 공유하도록 x를 표준화(standardize)하고, 그다음 스텝을 대각 곡률(diagonal curvature)인 Σλ·x²로 나누십시오. λ = e^η는 폭발적으로 증가할 수 있기 때문에, 가공되지 않은 고정 학습률(fixed learning rate)은 오버플로(overflow)를 일으키지만, 이러한 자기 스케일링(self-scaling) 방식은 모든 스텝을 안정적으로 유지해 줍니다.
for _ in range(iters):
lam = np.exp(Z @ beta) # λ = e^(Zβ)
grad = Z.T @ (y - lam) # score
...
보상은 해석 가능성(interpretability)입니다
모델이 로그(log) 스케일에서 선형이기 때문에, 계수(coefficients)는 계수(count)에 _곱셈적(multiplicatively)_으로 작용합니다. x가 1단위 증가하면 기대 계수(expected count)는 e^β₁배, 즉 비율비(rate ratio)만큼 곱해집니다. e^β₁ = 1.28은 "x가 +1일 때 ⇒ 이벤트가 28% 더 많이 발생함"을 의미합니다. 그리고 가공되지 않은 계수(raw count)가 아니라 비율(rate) — 예를 들어 보험 연도당 청구 건수와 같이 노출 단위당 발생하는 이벤트 — 을 모델링할 때는 log(exposure)를 고정 오프셋(fixed offset) 열로 추가합니다: log λ = log(exposure) + β·x. 데모에서 제가 주의를 주는 한 가지 사항은 다음과 같습니다: 포아송(Poisson) 모델은 분산(variance)이 평균(mean)과 같다고 가정합니다. 실제 계수 데이터는 종종 과분산(overdispersed, 분산 ≫ 평균)되어 있습니다. 편차(deviance)를 자유도(degrees-of-freedom)로 나누어 확인해 보십시오. 만약 그 값이 1보다 훨씬 크다면, 분산 매개변수(dispersion parameter)를 추가하는 음이항 회귀(Negative Binomial)를 사용하십시오. 만약 0이 쌓여 있다면, 영과잉 모델(zero-inflated model)을 고려하십시오.
제가 얻은 결론은 다음과 같습니다: y가 계수(count)인 순간, 그것에 직선을 맞추지 마십시오. 평균에 로그 연결 함수(log-link)를 적용하면 기하학적 구조가 마침내 데이터와 일치하게 됩니다. 그러면 적합된 곡선은 최소제곱법(OLS)이 기꺼이 빠져드는 불가능한 영역인 0 아래로 결코 내려가지 않을 것입니다.
일부 계수(count) 데이터를 삭제하고, Refit을 누른 뒤, 계수(coefficients)가 로그 가능도(log-likelihood)를 따라 실시간으로 상승하는 모습을 지켜보세요:
https://dev48v.infy.uk/ml/day47-poisson-regression.html
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기