회귀 진단
이상점
> house <- read.csv('house_sales.csv', sep='\t')
> zip_groups <- house %>%
+     mutate(resid = residuals(house_lm)) %>%
+     group_by(ZipCode) %>%
+     summarize(med_resid = median(resid),
+               cnt = n()) %>%
+     # sort the zip codes by the median residual
+     arrange(med_resid) %>%
+     mutate(cum_cnt = cumsum(cnt),
+            ZipGroup = factor(ntile(cum_cnt, 5)))
> house <- house %>%
+     left_join(select(zip_groups, ZipCode, ZipGroup), by='ZipCode')
> house_98105 <- house[house$ZipCode == 98105,]
> lm_98105 <- lm(AdjSalePrice ~ SqFtTotLiving + SqFtLot + Bathrooms + Bedrooms + BldgGrade, data=house_98105)
> lm_98105
Call:
lm(formula = AdjSalePrice ~ SqFtTotLiving + SqFtLot + Bathrooms + 
    Bedrooms + BldgGrade, data = house_98105)
Coefficients:
  (Intercept)  SqFtTotLiving        SqFtLot      Bathrooms       Bedrooms      BldgGrade  
   -772549.86         209.60          38.93        2282.26      -26320.27      130000.10  
> sresid <- rstandard(lm_98105)
> idx <- order(sresid, decreasing=FALSE)
> sresid[idx[1]]
    24333 
-4.326732 
> resid(lm_98105)[idx[1]]
    24333 
-757753.6 
- 결과를 보면 표준오차의 4배 이상이나 회귀식과 차이가 남
 
- 이에 해당하는 추정값은 $757,753. 이 특잇값에 해당하는 레코드는 디음과 같음
 
> house_98105[idx[1], c('AdjSalePrice', 'SqFtTotLiving', 'SqFtLot', 'Bathrooms', 'Bedrooms', 'BldgGrade')]
      AdjSalePrice SqFtTotLiving SqFtLot Bathrooms Bedrooms BldgGrade
24333       119748          2900    7276         3        6         7
- 빅데이터의 경우, 새로운 데이터를 예측하기 위한 회귀분석에서 이상점이 그렇게 문제가 되지 는 않는다. 
 
- 그러나 이상점을 찾는 것이 주목적인 이상점 검출의 경우 이 값들이 매우 중요해진다. 
 
- 이상점은 사기 사건이나 갑작스러운 사건 발생과도 관련이 있다. 
 
- 따라서 이상점을 발견하는 것은 아주 중요한 사업 가치가 될 수 있다
 
영향값
- 주영향관측값(influential observation): 회귀모델에서 제외됐을 때중요한 변화를 가져오는 값
 
- 회귀분석에서, 잔차가 크다고 해서 모두 이런 값이 되지는 않는다.
 
> seed <- 11
> set.seed(seed)
> x <- rnorm(25)
> y <- -x/5 + rnorm(25)
> x[1] <- 8
> y[1] <- 8
> plot(x, y, xlab='', ylab='', pch=16)
> model <- lm(y~x)
> abline(a=model$coefficients[1], b=model$coefficients[2], col="blue", lwd=3)
> model <- lm(y[-1]~x[-1])
> abline(a=model$coefficients[1], b=model$coefficients[2], col="red", lwd=3, lty=2)
- 빨간색 점선은 오른쪽 위의 한 점을 제거했을 때의 회귀선
 
- 오른쪽 위의 데이터 값은 회귀 결과에 큰 영향을 주지만 큰 이상점으로 나타난 것은 아니다.
 
- 이 데이터 값은 회귀에 대한 높은 레버리지(leverage)를 가진 것으로 볼 수 있다
 
- 햇 값(hat-value): \(2(P=1)/n\) 이상의 값들은 레버리지가 높은 데이터로 판단
 
- 쿡 거리(Cook's distance): 레버리지와 잔차의 크기를 합쳐서 영향력을 판단하며 경험적으로 \(4/(n-P-1)\)보다 크면 영향력이 높다고 판단
 
- 영향력 그림(influence plot) 또는 거품그림(bubble plot): 표준화잔차와 햇 값, 쿡 거리를 모두 한번에 표현하는 그림
 
- 우편번호가 98105인 킹 카운티 주택 데이터에 대한 영향력 그림
 
> std_resid <- rstandard(lm_98105)
> cooks_D <- cooks.distance(lm_98105)
> hat_values <- hatvalues(lm_98105)
> plot(hat_values, std_resid, cex=10*sqrt(cooks_D))
> abline(h=c(-2.5, 2.5), lty=2)

- 회귀에서 몇몇 데이터 포인트가 정말로 큰 영향력을 보임을 알 수 있다. 
 
- 쿡 거리는 cooks.distance 힘수를 사용해 계산하고 hatvalues 함수를 이용해 회귀 진단을 구할 수 있다. 
 
- 햇 값은 \(x\)축, 잔차 정보는 \(y\)축에 위치하며, 쿡 거리에 해당하는 값은 원의 크기로 표현된다
 
- 전체 데이터를 모두 사용했을 때와 영향력이 가장 큰 데이터를 제거하고 구한 회귀 결과 비교
 
- Bathrooms 변수의 회귀계수가 크게 변한다
 
- 데이터의 규모가 작을 경우에만 영향력이 큰 관측 데이터를 확인하는 작업이 유용하며
 
- 빅데이터의 경우에는 어떤 한 값이 회귀식에 큰 변화를 주기란 쉽지 않기 때문이다
 
이분산성
- 데이터 과학자가 신경쓰는 것 한 가지는 잔차에 대한 가정을 기반으로 예상 값에 대한 신뢰구간을 계산하는 방법
 
- 이분산성(heteroskedasticity): 다양한 범위의 예측값에 따라 잔차의 분산이 일정하지 않은 것
 
- 어떤 일부분에서의 오차가 다른 곳보다 훨씬 크게 나타나는 것
 
- 우편번호가 98105인  킹 카운티 주택 회귀모델에서 절대잔차와 예측값의 관계
 
- 잔차의 분산은 고가의 주택일수록 증가하는 경향이 있다
 
- 이 회귀모델은 주택가격이 너무 높거나 너무 낮은 경우에는 예측을 잘하지 못하므로 모델이 다소 불완전하다
 
> df <- data.frame(resid = residuals(lm_98105), pred = predict(lm_98105))
> ggplot(df, aes(pred, abs(resid))) + geom_point() + geom_smooth() 
`geom_smooth()` using method = 'loess' and formula 'y ~ x'

- 정규분포보다 확연히 더 긴 꼬리를 가지며 , 더 큰 잔차에 대해 약간의 왜곡을 보인다.
 

편잔차그림과 비선형성
- 편잔차그림(partial residual plot): 예측모델이 예측변수와 결과변수 간의 관계를 얼마나 잘 설명하는지 시각화하는 방법
 
- 이상점의 검출과 함께 데이터 과학자들에게 가장 중요한 모델 진단 방법
 
- 하나의 예측변수와 응답변수 사이의 관계를 모든 다른 예측 변수로부터 분리하는 것
 
- 편잔차는 단일 예측변수를 기반으로 한 예측값과 전체를 고려한 회귀식의 실제 잔차를 결합하여 ‘만든 결과’
 
- 예측변수 \(X_i\)의 편잔치는 일반 잔차에 \(X_i\)와 연관된 회귀항을 더한 값
 
\begin{eqnarray} \textrm{partial residual} = \textrm{residual} + \hat{b}_iX_i\end{eqnarray}
- R의 predict 힘수를 이용해서 개별 회귀항 \(\hat{b}_iX_i\)를 얻을 수 있다.
 
> terms <- predict(lm_98105, type='terms')
> partial_resid <- resid(lm_98105) + terms
> partial_resid
      SqFtTotLiving      SqFtLot   Bathrooms     Bedrooms     BldgGrade
1036    -9582.44883 -357174.9708 -450660.995 -524932.2009 -412036.63955
1769  -189558.76910  -78529.9327 -159020.193 -174374.6343 -114119.61053
1770   -98583.94036   11964.9452  -63853.317  -52887.4899 -148952.83461
1771  -130174.59786  -92384.0872 -187669.007 -176703.1797 -272768.52442
1783   306968.80331   48451.3706  -96567.562 -142236.2342   74339.15810
1784   -28140.43476 -121486.4246 -132131.685 -122877.5562  -88942.80121
1785   571952.99093  266306.1851  276268.714  284381.7110  448316.56574
- 편잔차그림에서 \(x\)축은 \(X_i\)를, \(y\)축은 편잔차를 의미
 
> df <- data.frame(SqFtTotLiving = house_98105[, 'SqFtTotLiving'], Terms = terms[, 'SqFtTotLiving'], PartialResid = partial_resid[, 'SqFtTotLiving'])
> ggplot(df, aes(SqFtTotLiving, PartialResid)) + geom_point(shape=1) + scale_shape(solid = FALSE) + geom_smooth(linetype=2) + geom_line(aes(SqFtTotLiving, Terms))  
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
- 편잔차는 SqFtTotLiving 변수가 주택 가격에 얼마나 영향을 미치는지 보여준다. 
 
- SqFtTotLiving 변수와 가격 사이의 관계는 분명히 비선형이다. 
 
- 1,000제곱피트보다 작은 평수의 집에 대해서는 가격을 원래보다 낮게 추정
 
- 2,000∼3.000제곱피트 집에 대해서는 더 높게 추정
 
- 4 , 000제곱피트 이상에 관해서는 데이터 개수가 너무 적어 뭐라고 결론을 내릴 수가 없다.
 
