본문 바로가기

R/R을 이용한 데이터 처리&분석 실무

로지스틱 회귀 모델

반응형

로지스틱 회귀 모델(Logistic Regression)은 데이터 X의 분류가 Y일 확률을 p, N일 확률을 1-p라 할 때 다음과 같은 선형 모델을 가정한다.

 

log(p / (1-p)) = β_(0) + β_(1)

 

이 식에 대한 가장 단순한 설명은 다음과 같다.

 

β_(0) + β_(1)X는 (-∞, ∞) 값을 가질 수 있다. 그러나 우리가 예측하고자 하는 p는 분류가 Y일 확률이므로 (0, 1) 값을 가진다. 따라서 이 둘을 맞춰줄 필요가 있다. 이를 위한 첫 번째 단계는 p를 예측하는 것이 아니라 비(오즈odds)를 예측하도록 하는 것이다.

 

p / (1-p) = β_(0) + β_(1)X  (식 10-1)

 

이 식에서 좌변의 값은 (0, ∞) 값만 가질 수 있다. 반면 우변은 (-∞, ∞)를 가진다. 좌변이 (-∞, ∞) 값을 갖게 하기 위해 log 함수를 취한다. 그 결과 얻어진 log(p / (1-p))를 로짓 함수(logit function)라고 하고, 이를 이용한 결과는 식 9-1이 된다. 선형 모델에 대한 본격적인 설명은 참고자료를 보기 바란다.

 

로지스틱 회귀 모델은 glm( )함수를 사용해 수행한다.

 

-glm : 일반화 선형 모델을 생성한다.

glm(
  formula,  # 모델 포뮬러
  data,     # 포뮬러를 적용할 데이터
  family,   # 오차 분포와 링크(link) 함수. 로지스틱 회귀 모델의 경우 "binomial"을 지정한다.
)

 

-predict.glm : 일반화 선형 모델을 사용한 예측을 수행한다.

predict.glm(
  object,   # glm 객체
  newdata,  # 예측을 수행할 대상 데이터
  # 예측 결과의 유형을 지정한다. 기본값은 "link"다.
  # - link: 선형 독립 변수들의 연산 결과의 크기로 값을 반환한다. 이 값은 로지스틱 회귀 모델의
  # 경우 로그 오즈 log(p / (1-p))다.
  # - response: 반응 변수(response variable)의 크기로 값을 반환하며 로지스틱 회귀 모델의 경우
  # p가 이에 해당한다.
  # - terms: 행렬에 모델 포뮬러의 각 변수에 대한 적합된 값을 선형 예측 변수의 크기로 반환한다.
  type=c("link", "response", "terms")
)

 

 

아이리스 데이터로부터 로지스틱 회귀 모델을 작성해보자. 예측값이 두 분류여야 하므로 virginica, versicolor라는 두 분류만 남긴다.

> d <- subset(iris, Species == "virginica" | Species == "versicolor")
> str(d)
'data.frame':	100 obs. of  6 variables:
 $ Sepal.Length: num  7 6.4 6.9 5.5 6.5 5.7 6.3 4.9 6.6 5.2 ...
 $ Sepal.Width : num  3.2 3.2 3.1 2.3 2.8 2.8 3.3 2.4 2.9 2.7 ...
 $ Petal.Length: num  4.7 4.5 4.9 4 4.6 4.5 4.7 3.3 4.6 3.9 ...
 $ Petal.Width : num  1.4 1.5 1.5 1.3 1.5 1.3 1.6 1 1.3 1.4 ...
 $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Species2    : int  1 2 1 2 1 2 1 2 1 2 ...

 

위 결과에서 보듯이 subset( )을 적용하고 나면 데이터는 virginica, versicolor만 남도록 잘 걸러지지만 Species는 여전히 3개 레벨을 가질 수 있는 팩터다. 따라서 Species 컬럼에 새로 범주 레벨이 정해지도록 다시 한 번 factor( ) 함수를 거치게 한다.

> d$Species <- factor(d$Species)
> str(d)
'data.frame':	100 obs. of  6 variables:
 $ Sepal.Length: num  7 6.4 6.9 5.5 6.5 5.7 6.3 4.9 6.6 5.2 ...
 $ Sepal.Width : num  3.2 3.2 3.1 2.3 2.8 2.8 3.3 2.4 2.9 2.7 ...
 $ Petal.Length: num  4.7 4.5 4.9 4 4.6 4.5 4.7 3.3 4.6 3.9 ...
 $ Petal.Width : num  1.4 1.5 1.5 1.3 1.5 1.3 1.6 1 1.3 1.4 ...
 $ Species     : Factor w/ 2 levels "versicolor","virginica": 1 1 1 1 1 1 1 1 1 1 ...
 $ Species2    : int  1 2 1 2 1 2 1 2 1 2 ...

 

그 결과 Species가 2개의 레벨로 잘 정리되었다. 모델은 glm( ) 함수에 family=“binomial”을 지정해 선형 회귀 모델에서 한 것처럼 만든다.

> (m <- glm(Species ~ ., data=d, family="binomial"))

Call:  glm(formula = Species ~ ., family = "binomial", data = d)

Coefficients:
 (Intercept)  Sepal.Length   Sepal.Width  Petal.Length   Petal.Width  
    -42.0508       -2.4929       -6.6524        9.3069       18.2460  
    Species2  
      0.1178  

Degrees of Freedom: 99 Total (i.e. Null);  94 Residual
Null Deviance:	    138.6 
Residual Deviance: 11.89 	AIC: 23.89

 

모델이 적합된 값은 fitted( )를 사용해 알 수 있다.

> fitted(m)[c(1:5, 51:55)]
          51           52           53           54           55 
1.137650e-05 5.504927e-05 1.131091e-03 5.122874e-05 1.382259e-03 
         101          102          103          104          105 
1.000000e+00 9.996284e-01 9.999988e-01 9.997111e-01 9.999999e-01 

 

로지스틱 회귀 모델은 0 또는 1로 값을 예측하는 모델이다. 위 결과를 보면 virginica에 해당하는 1:5행은 0, versicolor에 해당하는 51:55행은 1로 잘 예측된 것을 알 수 있다.

 

예측값이 0.5 이하인 경우 virginica, 0.5보다 큰 경우 versicolor라고 하고, 이를 실제 데이터와 비교해보자. 아래 코드에서 as.numeric( )은 팩터를 숫자를 저장한 벡터로 변환한다. R에서 팩터의 레벨은 1, 2, 3, …처럼 1부터 값이 부여되기 시작한다. 따라서 as.numeric( )으로 팩터를 변환한 뒤 1을 빼주어야 로지스틱 회귀 분석의 결과에 맞게 0 또는 1의 값을 갖게 된다.

> f <- fitted(m)
> as.numeric(d$Species)
  [1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 [35] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
 [69] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
> ifelse(f> .5, 1, 0)==as.numeric(d$Species) -1
   51    52    53    54    55    56    57    58    59    60    61    62 
 TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE 
   63    64    65    66    67    68    69    70    71    72    73    74 
 TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE 
   75    76    77    78    79    80    81    82    83    84    85    86 
 TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE 
   87    88    89    90    91    92    93    94    95    96    97    98 
 TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE 
   99   100   101   102   103   104   105   106   107   108   109   110 
 TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE 
  111   112   113   114   115   116   117   118   119   120   121   122 
 TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE 
  123   124   125   126   127   128   129   130   131   132   133   134 
 TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE 
  135   136   137   138   139   140   141   142   143   144   145   146 
 TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE 
  147   148   149   150 
 TRUE  TRUE  TRUE  TRUE 

 

예측된 분류와 실제 분류가 일치한 경우 TRUE, 일치하지 않은 경우 FALSE가 표시되었다. 눈으로 확인하기에 불편한 점이 있으므로 위 결과의 TRUE 개수를 코드를 사용해 세어보자.

> is_correct <- (ifelse(f > .5, 1, 0) == as.numeric(d$Species) - 1)
> sum(is_correct)
[1] 98
> sum(is_correct) / NROW(is_correct)
[1] 0.98

 

sum( ) 함수는 TRUE를 1, FALSE를 0으로 취급하므로 sum( )은 전체에서 TRUE의 개수를 반환한다. NROW( )는 데이터의 전체 개수를 반환한다. 따라서 sum(is_correct) / NROW(is_correct)는 정확한 분류의 비율이 되며 이 경우에는 98%였다.

 

새로운 데이터에 대한 예측은 predict( ) 함수를 사용한다. 이 예에서는 설명의 편의를 위해 미리 테스트할 데이터를 제외시켜놓지 않았기 때문에 모델을 만들 때 사용한 데이터를 재사용한 예를 보인다. 그러나 실제 모델을 만들 때는 9장에서 설명한 것처럼 훈련 데이터와 테스트 데이터가 분리되어 있도록 하는 것이 올바른 방법이다.

 

type을 response로 지정하고 예측을 수행하면 0 ~ 1 사이의 확률을 구해준다.

> predict(m, newdata=d[c(1, 10, 55),], type="response")
          51           60          105 
1.137650e-05 1.848877e-05 9.999999e-01 

 

predict( )는 일반 함수Generic Function므로 주어진 인자에 따라 다른 메서드를 호출한다. predict( ) 함수가 호출하는 메서드의 목록은 methods(“predict”)로 볼 수 있으며, glm의 경우 predict.glm( )이 자동으로 호출된다.

 

로지스틱 회귀 모델에는 이외에도 8장의 선형 회귀에서 살펴본 다양한 함수가 적용 가능하니 확인해보기 바란다.

 

 

 

R을 이용한 데이터 처리&분석 실무 中

반응형

'R > R을 이용한 데이터 처리&분석 실무' 카테고리의 다른 글

의사 결정 나무  (0) 2020.02.12
다항 로지스틱 회귀 분석  (0) 2020.02.12
모델 평가 방법 - 2  (0) 2020.02.11
모델 평가 방법  (0) 2020.02.11
전처리-2  (0) 2020.02.10