일요일, 5월 21, 2017

[R] 다중 회귀 분석 (Multiple Regression Analysis)


1. 개요
다중 회귀 분석이란 단순 회귀 분석을 기초로 하되, 독립변수를 2개 이상 사용하는 것이다. 즉, 단순 회귀 분석이 1개의 종속변수와 1개의 독립변수 사이의 인과관계를 조사하는 방법이라면, 다중 회귀 분석은 다수의 독립변수가 1개의 종속변수에 미치는 영향을 분석하는 것이라고 생각할 수 있다.
이 글에서는 UsingR 패키지에서 제공하는 babies 데이터셋에 대해 R Script를 사용하여 다중 회귀 분석을 적용하고, 타당성을 검토해보는 과정을 설명한다.

2. 데이터 이해
다중 회귀 분석을 위한 데이터셋으로 UsingR 패키지의 babies를 사용한다. 준비단계로 먼저 R Script를 통해 UsingR 패키지를 설치한 뒤 불러오는 과정을 수행한다.
install.packages("UsingR")
library("UsingR")
babies라고 입력했을 때 데이터가 정상적으로 출력되면 준비가 완료된 것이다.
babies 데이터셋은 23개의 attribute와 1236개의 tuple로 구성되어 있는 데이터이며, 신생아와 부모의 정보들을 담고 있다. 각 attribute들의 내용은 다음과 같다.
id identification number
pluralty 5=single fetus
outcome 1=live birth that survived at least 28 days
date birth date where 1096=January 1, 1961
gestation length of gestation in days
sex infant’s sex 1=male 2=female 9=unknown
wt birth weight in ounces (999 unknown)
parity total number of previous pregnancies including fetal deaths and still births, 99=unknown
race mother’s race 0-5=white 6=mex 7=black 8=asian 9=mixed 99=unknown
age mother’s age in years at termination of pregnancy, 99=unknown
ed mother’s education 0=less than 8th grade, 1=8th-12th grade-did not graduate, 2=HS graduate-no other schooling, 3=HS+trade, 4=HS+some college 5=College graduate, 6&7=Trade school HS unclear, 9=unknown
ht mother’s height in inches to the last completed inch 99=unknown
wt1 mother prepregnancy wt in pounds, 999=unknown
drace father’s race, coding same as mother’s race
dage father’s age, coding same as mother’s age
ded father’s education, coding same as mother’s education
dht father’s height, coding same as for mother’s height
dwt father’s weight coding same as for mother’s weight
marital 1=married, 2=legally separated, 3=divorced, 4=widowed, 5=never married
inc family yearly income in $2500 increments 0=under 2500, 1=2500-4999, ..., 8= 12,500-14,999, 9=15000+, 98=unknown, 99=not asked
smoke does mother smoke? 0=never, 1=smokes now, 2=until current pregnancy, 3=once did, not now, 9=unknown
time If mother quit, how long ago? 0=never smoked, 1=still smokes, 2=during current preg, 3=within 1 yr, 4=1 to 2 years ago, 5=2 to 3 yr ago, 6=3 to 4 yrs ago, 7=5 to 9 yrs ago, 8=10+ yrs ago, 9=quit and don’t know, 98=unknown, 99=not asked
number number of cigs smoked per day for past and current smokers 0=never, 1=1-4, 2=5-9, 3=10-14, 4=15-19, 5=20-29, 6=30-39, 7=40-60, 8=60+, 9=smoke but don’t know, 98=unknown, 99=not asked
다중 회귀 분석을 할 때는 신생아의 몸무게를 종속변수로 설정한다. 즉, wt가 종속변수가 된다.

각 변수들 사이의 관계를 전반적으로 조명해보고 싶다면 산점도를 그려보거나 공분산(Covariance) 혹은 상관계수(Correlation Coefficient)를 구하면 된다.
예를 들어, 신생아의 몸무게와 어머니의 키 사이의 관계를 보기 위해 산점도를 그리려면 plot 함수를 사용하면 된다.
attach(babies)
plot(wt~ht)
만약 여러 변수들 사이의 산점도를 한 번에 보고 싶다면 다음과 같이 변수의 인덱스를 통해 접근해서 한꺼번에 산점도를 그리면 된다.
plot(babies[, 2:7])
그리고 공분산을 구하려면 cov 함수를 사용하면 된다. 이때 공분산이 양수이면 두 변수가 양의 상관관계를 나타냄을 의미하고, 반대로 음수이면 음의 상관관계를 나타냄을 의미한다.
cov(wt, ht)
[1] 12.04483
상관계수는 cor 함수를 통해 구할 수 있다. 상관계수는 [-1, 1] 범위의 값을 가지며, 절대값이 클수록 두 변수가 강한 선형관계를 가지고 있다고 간주한다. 즉, 상관계수가 0인 경우 선형관계가 전혀 없음을 의미한다. 일반적으로 0.3~0.7의 값은 뚜렷한 양적 선형관계, 그리고 0.7~1.0의 값은 강한 양적 선형관계로 간주한다. 음의 선형관계도 부호만 다를 뿐 동일하다.
인자로 complete.obs와 pearson을 입력하면 결측값을 모두 제거한 상태로 피어슨 상관계수를 계산해준다.
cor(wt, ht, use='complete.obs', method='pearson')
[1] 0.1255413
0.1 정도의 값이 나오는 것으로 보아 신생아의 무게와 어머니의 키가 양적 선형관계를 가지긴 하지만, 뚜렷한 양적 선형관계를 가진다고는 볼 수 없다.
좀 더 Formal한 방식으로 상관계수를 검정하려면 cor.test() 함수를 사용하면 된다.
cor.test(wt, ht)
결과에 의하면 두 변수 사이의 상관관계가 전혀 없다는 귀무가설의 검정결과 p-value = 9.569e-06 <= 0.05이므로 귀무가설을 기각할 수 있다.
만약 여러 변수들 사이의 상관관계를 한번에 파악하고 싶다면 역시 변수의 인덱스를 통해 한꺼번에 상관계수를 구하면 된다.
cor(babies[, 7:12])
좀 더 시각적으로 상관계수를 살펴보고자 한다면 corrplot이라는 함수를 사용한다. corrplot을 사용하려면 해당하는 패키지를 먼저 설치해야 한다.
install.packages("corrplot")
library("corrplot")
corrplot(cor(babies[, 7:12]))
이 과정을 진행하면서 N/A같이 의도치 않은 값들이 나오는 경우가 종종 발생할 것이다. 이는 데이터셋 자체에 노이즈 데이터가 포함되어 있거나 의미 없는 변수들이 존재하는 경우가 있기 때문이다. 따라서 전처리 과정을 마친 다음에 다시 상관계수 분석을 진행할 것을 권장한다.

3. 전처리(Preprocessing)
우선 lm함수를 통해 wt를 종속변수로 설정하고 나머지 attribute들을 모두 독립변수로 설정한 뒤 다중 회귀 분석을 적용해본다.
m <- lm(wt ~ ., babies)
summary(m)
독립변수 pluralty, outcome, sex라는 attribute들에 포함된 값이 하나밖에 존재하지 않기 때문에 문제가 발생했음을 알 수 있다. R Script를 통해 실제 저장된 값들을 살펴보면 다음과 같은 결과가 나타난다.
이 세 가지 attribute들 외에도, id같은 경우 Birthweight와는 상관이 없음을 직관적으로 알 수 없기 때문에, 총 네 가지 attribute를 제거한다.
# preprocessing
my_babies <- babies # load babies dataset
# remove meaningless attributes
my_babies <- my_babies[, -1] # remove id
my_babies <- my_babies[, -1] # remove pluralty
my_babies <- my_babies[, -1] # remove outcome
my_babies <- my_babies[, -3] # remove sex
또한 남은 attribute 중에서 parity, race, ed, drace, ded, marital, inc, smoke, time, number는 범주형 데이터에 속한다. attribute들은 종속변수와 선형적인 관계를 유지하지 않을 것으로 예상할 수 있다. 하지만, 어느정도 종속변수에 영향을 미칠 수 있으므로, 모두 제거하지 않고 회귀 분석에 반영하기로 한다.
원래 범주형 데이터는 제거하거나, factor 함수를 사용하여 범주형 데이터라는 사실을 lm함수에게 알려주어야 한다.
예를 들어,
temp <- lm(wt ~ age + dage + factor(race), my_babies)
이렇게 age, dage, race를 독립변수로 설정하고 다중 회귀 분석을 할 때 factor(race)를 호출하여 race라는 attribute가 범주형 데이터임을 명시한다.

이 글에서는 범주형 데이터를 따로 명시하지 않고, 그대로 사용해보기로 한다. 여기서 주의할 점은,  범주형 데이터에 속하는 attribute들과 wt, wt1, dwt 등의 경우 유효하지 않은 값들이 포함되어 있을 수도 있다는 것이다. 예를 들어, wt의 값들 중에서 999는 실제 무게가 999가 아니라, 데이터를 알 수 없음을 의미한다. 따라서 모든 attribute에 대해서 의미가 없는 값들을 포함한 tuple들을 제거한다.
# remove meaningless tuples
my_babies <- my_babies[my_babies$wt != 999,]
my_babies <- my_babies[my_babies$gestation != 999,]
my_babies <- my_babies[my_babies$parity != 99,]
my_babies <- my_babies[my_babies$race != 99,]
my_babies <- my_babies[my_babies$age != 99,]
my_babies <- my_babies[my_babies$ed != 9,]
my_babies <- my_babies[my_babies$ht != 99,]
my_babies <- my_babies[my_babies$wt1 != 999,]
my_babies <- my_babies[my_babies$drace != 99,]
my_babies <- my_babies[my_babies$dage != 99,]
my_babies <- my_babies[my_babies$ded != 9,]
my_babies <- my_babies[my_babies$dwt != 999,]
my_babies <- my_babies[my_babies$dht != 99,]
my_babies <- my_babies[my_babies$inc != 98,]
my_babies <- my_babies[my_babies$inc != 99,]
my_babies <- my_babies[my_babies$smoke != 9,]
my_babies <- my_babies[my_babies$time != 98,]
my_babies <- my_babies[my_babies$time != 99,]
my_babies <- my_babies[my_babies$number != 98,]
my_babies <- my_babies[my_babies$number != 99,]

4. 회귀식 추정
전처리된 결과를 바탕으로 회귀 모형을 만들면 다음과 같은 결과를 얻을 수 있다.
before <- my_babies
summary(before)
이 결과에서 주목할 몇 가지 항목만 짚어보자. (Intercept)는 다중 회귀식에서 y 절편을 나타낸다. 그리고 맨 우측의 Pr(>|t|)는 각 독립변수들의 p-value를 나타낸다. 일반적으로 이 p-value가 0.05보다 작을 때 통계적으로 유의하다고 정의한다. 우측의 *표시는 통계적으로 유의한 정도를 나타내며, 개수가 많을수록 더욱 유의하다는 의미이다. 그리고 하단의 Multiple R-squared와 Adjusted R-squared는 회귀 모형의 타당성을 검토할 때 사용되는 값이다. 그리고 가장 밑에 있는 p-value는 전체 회귀 모형의 p-value를 나타낸다. 이 값도 역시 0.05보다 작을 때 통계적으로 유의하다고 정의한다. 관찰 결과 2.2e-16보다 작은 값이 나타나므로, 이미 충분히 유의하게 babies 데이터셋을 설명한다고 판단할 수 있다. 하지만, 통계적으로 유의하다고 판단할 수 없는 독립변수들(dht, dwt )이 다수 포함되어 있다.

다중 회귀 모형의 경우 독립변수가 여러개 존재하지만, 이들 중 모두가 종속변수에 유의한 영향을 주는 것은 아닐 수도 있다. 이때 독립변수들 중에서 통계적으로 유의한 변수들을 선별하는 것을 다중 회귀식의 추정이라고 한다.
추정 방법에는 대표적으로 Enter, Stepwise, Elimination, Backward, Forward가 있다.
이 중에서 Backward 방법을 채택한다. Backward란 모든 독립변수를 포함한 상태에서 기여도가 적은(p-value가 큰) 변수부터 하나씩 빼기 시작하여 모델에 남아있는 변수들의 p-value가 0.05 이하가 될 때까지 삭제하는 방법이다. 주의할 점은, 매번 독립변수를 하나 제거할 때마다 나머지 독립변수에 대한 다중 회귀 분석을 다시 진행하여 p-value를 계산해야 한다. 다시 말해서, 모든 독립변수를 포함한 초기 회귀 모형에서 각 독립변수의 p-value들을 정렬하여 하나씩 제거하면 안된다는 것이다. 어떤 독립변수가 제거될 경우 나머지 독립변수에 영향을 미치기 때문이다.

이미 초기 회귀 모형의 p-value가 0.05 이하이기 때문에, 유의한 독립변수만 남을 때까지 Backward 방법을 적용하도록 한다.
temp <- lm(wt ~ date + gestation + parity + race + age + ed + ht + wt1 + drace + dage + ded + dwt + marital + inc + smoke + time + number, my_babies) # remove dht
summary(temp)
temp <- lm(wt ~ date + gestation + parity + race + age + ed + ht + wt1 + drace + dage + ded + dwt + marital + inc + smoke + number, my_babies) # remove time
summary(temp)
temp <- lm(wt ~ date + gestation + parity + race + ed + ht + wt1 + drace + dage + ded + dwt + marital + inc + smoke + number, my_babies) # remove age
summary(temp)
temp <- lm(wt ~ date + gestation + parity + race + ed + ht + wt1 + drace + ded + dwt + marital + inc + smoke + number, my_babies) # remove dage
summary(temp)
temp <- lm(wt ~ date + gestation + parity + race + ed + ht + drace + ded + dwt + marital + inc + smoke + number, my_babies) # remove wt1
summary(temp)
temp <- lm(wt ~ date + gestation + parity + race + ed + ht + drace + ded + dwt + marital + smoke + number, my_babies) # remove inc
summary(temp)
temp <- lm(wt ~ date + gestation + parity + race + ed + ht + drace + ded + dwt + smoke + number, my_babies) # remove marital
summary(temp)
temp <- lm(wt ~ date + gestation + parity + race + ed + ht + ded + dwt + smoke + number, my_babies) # remove drace
summary(temp)
temp <- lm(wt ~ date + gestation + parity + race + ht + ded + dwt + smoke + number, my_babies) # remove ed
summary(temp)
temp <- lm(wt ~ date + gestation + parity + race + ht + dwt + smoke + number, my_babies) # remove ded
summary(temp)
temp <- lm(wt ~ gestation + parity + race + ht + dwt + smoke + number, my_babies) # remove date
summary(temp)
이 과정을 진행해보면, dht, time, age, dage, wt1, inc, marital, drace, ed, ded, date 순으로 독립변수가 제거된다. 위의 코드를 전부 실행할 필요없이 최하단의 다중 회귀 분석만 진행하면 된다.
after <- lm(wt ~ gestation + parity + race + ht + dwt + smoke + number, my_babies)
summary(after)

결과를 보면, 통계적으로 유의한 독립변수들로만 구성되어 있는 것, 그리고 독립변수의 수는 줄어들었지만 전체 회귀 모형의 p-value가 초기 회귀 모형과 동일하게 나타난다는 것을 확인할 수 있다.

분산 분석에 해당하는 anova 함수를 통해 Backward 방법을 적용한 회귀 모형과 초기 회귀 모형을 비교하면 다음과 같은 결과가 나온다.
anova(after, before)
이처럼 F-test의 결과로 p-value 0.6489로 다소 큰 값이 나왔으므로, Backward 방법을 통해 통계적으로 유의하지 않은 독립변수들을 제거한 것이 타당하다고 해석할 수 있다. 따라서 Backward 방법을 적용한 'after' 회귀 모형을 채택한다.

5. 모형적합도
채택한 회귀 모형(after)의 타당성을 검토하려면 결정계수(R-squared)를 확인하면 된다.
이 결정계수는 상관계수의 제곱으로, 회귀식이 데이터를 얼마나 잘 설명하고 있는지를 나타내는 계수이다. 일반적으로 이 값이 0.65보다 클 경우 회귀식이 데이터를 잘 설명한다고 판단한다. 이 0.65가 절대적인 수치는 아니다. 연구자의 주관에 따라 달라질 수 있다.
다중 회귀 분석에서는 대부분 수정된 결정계수(Adjusted R-squared)를 사용한다. 이는 독립변수의 수와 데이터의 수를 고려한 결정계수이며, 독립변수의 수가 증가할수록 값이 커지는 성질이 있다.
채택한 회귀 모형의 경우 수정된 결정계수가 0.261로 관찰된다. 초기 회귀 모형(before)의 수정된 결정계수가 0.2582임을 감안할 때, 독립변수의 수가 영향이 있었음을 예상해볼 수 있다. 결론적으로 채택된 회귀 모형은 반응변수의 약 26% 정도를 설명한다고 볼 수 있다. 범주형 데이터를 수치 데이터로 처리했기 때문에 설명력이 저하되었음을 의심해볼 수 있다. 이 26%라는 설명력은 기준이 되는 65%에 비해 낮은 수치이다. 하지만 이는 다수의 독립변수가 포함되었음을 감안할 때 결코 무시할만 한 수준은 아니다.

6. References
https://cran.r-project.org/web/packages/UsingR/UsingR.pdf
http://rstudio-pubs-static.s3.amazonaws.com/14197_79619e2b222041f28b6857e45c9cba5d.html
https://ko.wikipedia.org/wiki/%EC%84%A0%ED%98%95_%ED%9A%8C%EA%B7%80
http://blog.naver.com/PostView.nhn?blogId=y4769&logNo=220390306491
http://rstudio-pubs-static.s3.amazonaws.com/189354_277dfb3a83a34a2abaae855b90fcf269.html
http://rfriend.tistory.com/131
http://ordo.tistory.com/21

댓글 3개:

  1. 블로그 관리자가 댓글을 삭제했습니다.

    답글삭제
  2. 블로그 관리자가 댓글을 삭제했습니다.

    답글삭제
  3. 블로그 관리자가 댓글을 삭제했습니다.

    답글삭제