13.1 포아송 회귀 (Poisson Regression)
다음과 같은 영국 의사들을 상대로 한 자료가 있다.
참고로 R에서 “tbl_df” class는reshape이나 subsetting시 문제가 발생할 수 있으므로 아래와 같이 class를 “data.frame”으로 해두는 것이 좋다.
class(doctors) = "data.frame" # tbl_df class has problem with reshape or subsetting
class(beetle) = "data.frame" # tbl_df class has problem with reshape or subsetting
class(Cars) = "data.frame" # tbl_df class has problem with reshape or subsetting
doctors
age smoking deaths person-years
1 35 to 44 smoker 32 52407
2 45 to 54 smoker 104 43248
3 55 to 64 smoker 206 28612
4 65 to 74 smoker 186 12663
5 75 to 84 smoker 102 5317
6 35 to 44 non-smoker 2 18790
7 45 to 54 non-smoker 12 10673
8 55 to 64 non-smoker 28 5710
9 65 to 74 non-smoker 28 2585
10 75 to 84 non-smoker 31 1462
흡연 여부가 사망과 어떤 연관이 있는지 연령과 함께 모형화해 보고자 한다. 그러기 위해 우선 연령군을 1 ~ 5의 숫자로 코딩하고, smoker를 1로, non-smoker를 0으로 코딩한다.
그래프를 그려보면 연령에 따라 직선적으로 증가하는 것이 아니라, 약간 아래로 꺽이는 것을 볼 수 있다. 따라서, age의 제곱항도 넣어서 모형화하면 다음과 같다.
"Age"] = as.numeric(as.ordered(doctors$age))
doctors[,"Smoke"] = as.numeric(doctors$smoking == "smoker")
doctors[,"ni"] = doctors$'person-years'
doctors[, doctors
age smoking deaths person-years Age Smoke ni
1 35 to 44 smoker 32 52407 1 1 52407
2 45 to 54 smoker 104 43248 2 1 43248
3 55 to 64 smoker 206 28612 3 1 28612
4 65 to 74 smoker 186 12663 4 1 12663
5 75 to 84 smoker 102 5317 5 1 5317
6 35 to 44 non-smoker 2 18790 1 0 18790
7 45 to 54 non-smoker 12 10673 2 0 10673
8 55 to 64 non-smoker 28 5710 3 0 5710
9 65 to 74 non-smoker 28 2585 4 0 2585
10 75 to 84 non-smoker 31 1462 5 0 1462
= glm(deaths ~ Smoke + Age + I(Age*Age) + offset(log(ni)), "poisson", doctors)
r1 summary(r1)
Call:
glm(formula = deaths ~ Smoke + Age + I(Age * Age) + offset(log(ni)),
family = "poisson", data = doctors)
Deviance Residuals:
Min 1Q Median 3Q Max
-2.14815 -0.71275 0.02995 0.33549 1.92253
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -9.83396 0.29516 -33.317 < 2e-16 ***
Smoke 0.35452 0.10737 3.302 0.000961 ***
Age 2.09471 0.18119 11.561 < 2e-16 ***
I(Age * Age) -0.19438 0.02715 -7.159 8.14e-13 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
(Dispersion parameter for poisson family taken to be 1)
Null deviance: 935.067 on 9 degrees of freedom
Residual deviance: 12.176 on 6 degrees of freedom
AIC: 75.243
Number of Fisher Scoring iterations: 4
일반화 선형 모형의 경우 잔차의 종류가 다양하다.
$fitted.values # y hat r1
1 2 3 4 5 6 7 8 9 10
26.781 100.199 203.739 187.868 111.413 6.736 17.347 28.523 26.904 21.491
residuals(r1, type="deviance")
1 2 3 4 5 6 7 8 9 10
0.9782 0.3773 0.1581 -0.1365 -0.9048 -2.1482 -1.3600 -0.0982 0.2100 1.9225
residuals(r1, type="pearson")
1 2 3 4 5 6 7 8 9 10
1.0085 0.3797 0.1584 -0.1363 -0.8918 -1.8248 -1.2838 -0.0979 0.2114 2.0513
rstandard(r1, type="deviance")
1 2 3 4 5 6 7 8 9 10
1.4361 0.4872 0.2348 -0.1815 -1.8414 -2.3738 -1.5304 -0.1196 0.2499 2.3218
rstandard(r1, type="pearson") # preferred, use this
1 2 3 4 5 6 7 8 9 10
1.4807 0.4902 0.2352 -0.1812 -1.8149 -2.0164 -1.4446 -0.1192 0.2515 2.4773
위의 결과는 다음과 같이 계산된다.
Objective function을 계산하기 편하게 하기 위해, y 값, n 값, sum of log factorial (yi)를 다음과 같이 미리 준비해 둔다.
= doctors[,"deaths"]
y = doctors[,"ni"]
ni = sum(lfactorial(y)) sumlfacty
Design matrix는 다음과 같다.
= model.matrix(~ Smoke + Age + I(Age*Age), data=doctors) ; X X
(Intercept) Smoke Age I(Age * Age)
1 1 1 1 1
2 1 1 2 4
3 1 1 3 9
4 1 1 4 16
5 1 1 5 25
6 1 0 1 1
7 1 0 2 4
8 1 0 3 9
9 1 0 4 16
10 1 0 5 25
attr(,"assign")
[1] 0 1 2 3
Objective function은 -log likelihood로 다음과 같다.
= function(Beta) # -log likelihood function for poisson distribution
LLp
{= log(ni) + X %*% Beta
LogLam = sum(y*LogLam - exp(LogLam)) - sumlfacty
LogLik return(-LogLik)
}
마지막 항 sumlfacty는 optimize 과정에는 불필요하다. 따라서, 이 함수에서는 없애고 나중에 log likelihood를 계산할 때 다시 넣어 주는 것이 더 효율적이다. 하지만, 목적함수값이 -log likelihood가 아니면 생길 수 있는 혼란을 줄이기 위해 포함시켰다.
optim 함수를 이용하여 적합하면 다음과 같다.
= optim(c(1, 1, 1, 1), LLp, method="L-BFGS-B", hessian=TRUE) ; r2 r2
$par
[1] -9.8372498 0.3544376 2.0970299 -0.1947360
$value
[1] 33.62183
$counts
function gradient
84 84
$convergence
[1] 0
$message
[1] "CONVERGENCE: REL_REDUCTION_OF_F <= FACTR*EPSMCH"
$hessian
[,1] [,2] [,3] [,4]
[1,] 731.0001 630.0001 2489.000 9353.001
[2,] 630.0001 630.0001 2146.930 8052.424
[3,] 2489.0003 2146.9295 9352.531 37601.080
[4,] 9353.0012 8052.4235 37601.080 158764.770
= solve(r2$hessian) ; COV2 COV2
[,1] [,2] [,3] [,4]
[1,] 0.087170563 -0.008217121 -0.048971494 0.006879627
[2,] -0.008217121 0.011528811 -0.001150242 0.000171765
[3,] -0.048971494 -0.001150242 0.032839515 -0.004834250
[4,] 0.006879627 0.000171765 -0.004834250 0.000737221
= sqrt(diag(COV2)) ; SE2 SE2
[1] 0.29524661 0.10737230 0.18121676 0.02715181
Saturated model의 log likelihood와 그 deviance는 다음과 같다.
= sum(y*log(y) - y - lfactorial(y)) ; LLs # LL of saturated model LLs
[1] -27.53397
2*(LLs + r2$value) # Deviance
[1] 12.17572
먼저 적합시킨 모형의 deviance를 이용하여 p-value를 구하면 다음과 같다.
1 - pchisq(2*(LLs + r2$value), length(y) - length(r2$par))
[1] 0.05816164
optim에 의한 적합값과 glm에 의한 적합값이 약간 다름을 알 수 있다. 이는 miminization algorithm에 따라 다른 것이다.
이제 glm에 의한 값을 이용해서 나머지를 계산하면 다음과 같다.
= coef(r1) # beta hat
b = exp(X %*% b) # pi hat
pihat = ni*pihat ; t(yhat) # y hat yhat
1 2 3 4 5 6 7 8 9
[1,] 26.78081 100.1992 203.7388 187.868 111.4132 6.735889 17.34677 28.52302 26.9036
10
[1,] 21.49073
Pearson residual은 다음과 같다.
= (y - yhat)/sqrt(yhat) ; t(pr) # Pearson residual pr
1 2 3 4 5 6 7 8
[1,] 1.008536 0.3796996 0.1584157 -0.1362827 -0.8918021 -1.824753 -1.283755 -0.09793023
9 10
[1,] 0.2113798 2.051265
모형의 deviance와 deviance residual은 다음과 같이 구할 수 있다.
= 2*(y*log(y/yhat) - (y - yhat)) ; sum(Di) # deviance Di
[1] 12.17555
= sign(y - yhat)*sqrt(Di) ; t(dr) # deviance residual dr
1 2 3 4 5 6 7 8
[1,] 0.9781824 0.3773363 0.158124 -0.1365095 -0.9048239 -2.148154 -1.359981 -0.09823183
9 10
[1,] 0.2099679 1.922531
NULL model (intercept만 있는 모형)의 deviance는 다음과 같이도 구할 수 있다.
= model.matrix(~ 1, data=doctors)
X = optim(1, LLp, method="L-BFGS-B") ; r3 r3
$par
[1] -5.514416
$value
[1] 495.0676
$counts
function gradient
17 17
$convergence
[1] 0
$message
[1] "CONVERGENCE: REL_REDUCTION_OF_F <= FACTR*EPSMCH"
2*(LLs + r3$value) # null deviance of r0
[1] 935.0673
그런데, 자세히 보면 age에 따른 curve의 기울기가 흡연 여부에 따라 다른 것을 볼 수 있다. 따라서, 이에 대한 상호작용항(interaction term)을 추가하면 다음과 같다.
= glm(deaths ~ Smoke + Age + I(Age*Age) + Age:Smoke + offset(log(ni)), "poisson", doctors)
r4 summary(r4)
Call:
glm(formula = deaths ~ Smoke + Age + I(Age * Age) + Age:Smoke +
offset(log(ni)), family = "poisson", data = doctors)
Deviance Residuals:
1 2 3 4 5 6 7 8
0.43820 -0.27329 -0.15265 0.23393 -0.05700 -0.83049 0.13404 0.64107
9 10
-0.41058 -0.01275
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -10.79176 0.45008 -23.978 < 2e-16 ***
Smoke 1.44097 0.37220 3.872 0.000108 ***
Age 2.37648 0.20795 11.428 < 2e-16 ***
I(Age * Age) -0.19768 0.02737 -7.223 5.08e-13 ***
Smoke:Age -0.30755 0.09704 -3.169 0.001528 **
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
(Dispersion parameter for poisson family taken to be 1)
Null deviance: 935.0673 on 9 degrees of freedom
Residual deviance: 1.6354 on 5 degrees of freedom
AIC: 66.703
Number of Fisher Scoring iterations: 4
추정된 \(\beta\) 계수들로 odds ratio를 구하면 다음과 같다.
exp(r4$coef[-1])
Smoke Age I(Age * Age) Smoke:Age
4.2247998 10.7669184 0.8206353 0.7352475
Interaction term이 있는 모형과 없는 모형은 다음과 같이 비교할 수 있다.
= anova(r1, r4) ; c1 c1
Analysis of Deviance Table
Model 1: deaths ~ Smoke + Age + I(Age * Age) + offset(log(ni))
Model 2: deaths ~ Smoke + Age + I(Age * Age) + Age:Smoke + offset(log(ni))
Resid. Df Resid. Dev Df Deviance
1 6 12.1755
2 5 1.6354 1 10.54
1 - pchisq(c1[2, "Deviance"], c1[2, "Df"])
[1] 0.001168073
통계적으로 유의한 차이가 있으므로 더 복잡한 모형인 상호작용이 있는 모형을 선택한다.