knitr::opts_chunk$set( collapse = TRUE, comment = "#>" )
library(dmtr) library(dplyr)
이분 로지스틱 회귀모형은 종속변수가 2가지 범주를 취하는 경우에 사용된다.
$N$개의 객체로 이루어진 학습데이터 ${(\mathbf{x}i, y_i)}{i = 1, \cdots, N}$를 아래와 같이 정의하자.
$\mathbf{x}_i$ 관측값을 이용하여 $y_i$의 기대값 $P_i$을 추정하는 모형을 아래와 같이 로지스틱 함수로 정의하자.
\begin{eqnarray} P_i &=& P(y_i = 1 \,|\, \mathbf{x}_i)\ &=& E[y_i | \mathbf{x}_i]\ &=& \frac{\exp(\beta_0 + \boldsymbol\beta^\top \mathbf{x}_i)}{1 + \exp(\beta_0 + \boldsymbol\beta^\top \mathbf{x}_i)} (#eq:logistic-function) \end{eqnarray}
여기에서 $\boldsymbol\beta \in \mathbb{R}^{p}$는 $\mathbf{x}_i$와 동일한 차원의 벡터이다 ($\boldsymbol\beta = [\beta_1 \, \beta_2 \, \cdots \, \beta_p]^\top$).
식 \@ref(eq:logistic-function)는 모든 $\mathbf{x}_i$값에 대해 0에서 1 사이의 값을 갖게 되므로 각 범주에 속할 확률을 추정하는 데 적합한 반면, 변수 $\mathbf{x}$ 및 계수들에 대해 선형이 아니므로 추정이 어렵다. 그러나 아래와 같이 로짓(logit) 변환을 통해 선형회귀식으로 변환할 수 있다.
\begin{eqnarray} logit(P_i) &=& \ln \left[ \frac{P_i}{1 - P_i} \right]\ &=& \ln(\exp(\beta_0 + \boldsymbol\beta^\top \mathbf{x}_i))\ &=& \beta_0 + \boldsymbol\beta^\top \mathbf{x}_i (#eq:logit-transform) \end{eqnarray}
식 \@ref(eq:logit-transform)에서 확률 $P_i$는 직접적으로 관측되는 것이 아니고 0 또는 1을 갖는 $y_i$가 관측되므로, $P_i$를 일종의 잠재변수(latent variable)로 해석할 수 있다.
\begin{equation} y_i = \begin{cases} 1 & \text{ if } \beta_0 + \boldsymbol\beta^\top \mathbf{x}_i + \varepsilon_i > 0 \ 0 & \text{ otherwise } \end{cases} (#eq:binary-logistic-latent-interpret) \end{equation}
식 \@ref(eq:binary-logistic-latent-interpret)에서 $\varepsilon_i$는 표준로지스틱분포(standard logistic distribution)을 따른다.
data(student, package = "dmtr")
knitr::kable( student, align = c('r', 'r', 'r', 'r', 'r'), caption = '우수/보통 학생에 대한 설문조사 결과' )
로지스틱 모형에서 회귀계수의 추정을 위해서 주로 최우추정법(maximum likelihood estimation)이 사용된다. $N$개의 객체로 이루어진 학습데이터에 대해 우도함수는 다음과 같다.
\begin{equation} L = \prod_{i = 1}^{N} P_i^{y_i} (1 - P_i)^{1 - y_i} \end{equation}
그리고 우도함수에 자연로그를 취하면 아래와 같이 전개된다.
\begin{eqnarray} \log L &=& \sum_{i = 1}^{N} y_i \log P_i + \sum_{i = 1}^{N} (1 - y_i) \log (1 - P_i)\ &=& \sum_{i = 1}^{N} y_i \log \frac{P_i}{1 - P_i} + \sum_{i = 1}^{N} \log (1 - P_i)\ &=& \sum_{i = 1}^{N} y_i (\beta_0 + \boldsymbol\beta^\top \mathbf{x}i) - \sum{i = 1}^{N} \log (1 + \exp (\beta_0 + \boldsymbol\beta^\top \mathbf{x}i) )\ &=& \sum{i = 1}^{N} y_i \left(\beta_0 + \sum_{j = 1}^{p} \beta_j x_{ij} \right) - \sum_{i = 1}^{N} \log \left(1 + \exp\left(\beta_0 + \sum_{j = 1}^{p} \beta_j x_{ij}\right)\right) (#eq:binary-logistic-reg-loglik) \end{eqnarray}
식 \@ref(eq:binary-logistic-reg-loglik)을 각 회귀계수 $\beta_0, \beta_1, \cdots, \beta_p$에 대해 편미분하여 최적해를 얻는다. 이를 위해 주로 뉴턴-랩슨 알고리즘(Newton-Raphson algorithm)이나 quasi-Newton 알고리즘이 사용된다 [@jun2012datamining].
회귀계수를 추정하는 함수를 fit_binary_logistic_regression()
으로 구현하였다.
fit <- fit_binary_logistic_regression(student, y, c(x1, x2, x3), .reflevel = "보통") print(fit)
위 추정계수와 헤시안 행렬(Hessian matrix)를 이용하여 아래와 같이 결과를 요약할 수 있다.
fit_summary_df <- tibble( term = names(fit$betas), estimate = fit$betas, std_error = sqrt((diag(solve(-fit$hessian)))), statistic = estimate / std_error, p_value = pnorm(if_else(statistic < 0, statistic, - statistic)) * 2, odds_ratio = if_else(term == "(Intercept)", NA_real_, exp(estimate)) )
knitr::kable( fit_summary_df, booktabs = TRUE, digits = 2L, caption = "우수/보통 학생 설문조사 데이터에 대한 Logistic Regression 결과" )
위 추정된 계수를 이용하여 사후확률을 계산하는 함수 회귀계수를 추정하는 함수를 posterior_binary_logistic_regression()
로 구현하였다.
posterior_df <- posterior_binary_logistic_regression( fit$betas, .new_data = student, c(x1, x2, x3), .reflevel = "보통", .poslevel = "우수" ) prediction_df <- bind_cols(student, posterior_df)
knitr::kable( prediction_df, booktabs = TRUE, align = rep('r', ncol(prediction_df)), digits = 2L, caption = "우수/보통 학생 설문조사 데이터에 대한 범주 추정" )
종속변수가 셋 이상의 범주를 갖고 있으나 자연스러운 순서가 없는 경우, 기준범주 로짓모형이 널리 사용된다.
$N$개의 객체로 이루어진 학습데이터 ${(\mathbf{x}i, y_i)}{i = 1, \cdots, N}$를 아래와 같이 정의하자.
각 객체 $i$가 각 범주에 해당할 확률을 $\pi_{ij}$라 하자.
\begin{equation} \pi_{ij} = P(y_i = j \, | \, \mathbf{x}_i), \, j = 1, \cdots, J \end{equation}
이 때, 모든 $i$에 대하여
\begin{equation} \sum_{j = 1}^{J} \pi_{ij} = 1 \end{equation}
이 성립한다. 여기에서 범주 1을 기준 범주(reference category 혹은 baseline category)로 간주하여 범주별로 다음과 같은 회귀모형을 정의한다 (교재 [@jun2012datamining]에는 범주 $J$를 기준 범주로 간주).
\begin{equation} \log \left( \frac{\pi_{ij}}{\pi_{i1}} \right) = \beta_{0,j} + \boldsymbol\beta_{j}^\top \mathbf{x}_i, \, j = 2, \cdots, J \end{equation}
이를 $\pi_{ij}$에 대해 풀면, 아래와 같은 해가 얻어진다 [@czepiel2002maximum].
\begin{equation} \begin{split} \pi_{ij} &= \frac{\exp \left( \beta_{0,j} + \boldsymbol\beta_{j}^\top \mathbf{x}i \right)}{1 + \sum{j = 2}^{J} \exp \left( \beta_{0,j} + \boldsymbol\beta_{j}^\top \mathbf{x}i \right)}, \, j = 2, \cdots, J\ \pi{i1} &= \frac{1}{1 + \sum_{j = 2}^{J} \exp \left( \beta_{0,j} + \boldsymbol\beta_{j}^\top \mathbf{x}_i \right)} \end{split} (#eq:multi-nominal-prob-sol) \end{equation}
data(defecttype, package = "dmtr")
knitr::kable(defecttype, booktabs = TRUE, align = c('r', 'r', 'r', 'r'), caption = '공정변수-불량 종류 데이터')
위 모수 추정을 위해 최우추정법을 사용해보자. 우선, 종속변수를 변환한 지시변수를 아래와 같이 정의한다.
\begin{equation} v_{ij} = \begin{cases} 1 & \text{ if } y_i = j\ 0 & \text{ otherwise } \end{cases} \end{equation}
이를 이용해 우도 함수를
\begin{eqnarray} L &=& \prod_{i = 1}^{n} \prod_{j = 1}^{J} \left( \pi_{ij} \right)^{v_{ij}} \ &=& \prod_{i = 1}^{n} \pi_{i1}^{1 - \sum_{j = 2}^{J} v_{ij}} \prod_{j = 2}^{J} \left( \pi_{ij} \right)^{v_{ij}}\ &=& \prod_{i = 1}^{n} \frac{\pi_{i1}}{\pi_{i1}^{\sum_{j = 2}^{J} v_{ij}}} \prod_{j = 2}^{J} \left( \pi_{ij} \right)^{v_{ij}}\ &=& \prod_{i = 1}^{n} \frac{\pi_{i1}}{\prod_{j = 2}^{J} \pi_{i1}^{v_{ij}}} \prod_{j = 2}^{J} \left( \pi_{ij} \right)^{v_{ij}}\ &=& \prod_{i = 1}^{n} \pi_{i1} \prod_{j = 2}^{J} \left( \frac{\pi_{ij}}{\pi_{i1}} \right)^{v_{ij}} \end{eqnarray}
와 같이 표현할 수 있으며, 여기에 식 \@ref(eq:multi-nominal-prob-sol)을 이용하면 아래와 같이 정리할 수 있다.
\begin{eqnarray} L &=& \prod_{i = 1}^{n} \frac{1}{1 + \sum_{j = 2}^{J} \exp \left( \beta_{0,j} + \boldsymbol\beta_{j}^\top \mathbf{x}i \right)} \prod{j = 2}^{J} \left( \exp \left( \beta_{0,j} + \boldsymbol\beta_{j}^\top \mathbf{x}i \right) \right)^{v{ij}}\ &=& \prod_{i = 1}^{n} \left( 1 + \sum_{j = 2}^{J} \exp \left( \beta_{0,j} + \boldsymbol\beta_{j}^\top \mathbf{x}i \right) \right)^{-1} \prod{j = 2}^{J} \left( \exp \left( \beta_{0,j} + \boldsymbol\beta_{j}^\top \mathbf{x}i \right) \right)^{v{ij}} \end{eqnarray}
이에 따라 로그 우도함수는 다음과 같이 정의된다.
\begin{equation} \log L = \sum_{i = 1}^{n} \left( - \log \left( 1 + \sum_{j = 2}^{J} \exp \left( \beta_{0,j} + \boldsymbol\beta_{j}^\top \mathbf{x}i \right) \right) + \sum{j = 2}^{J} v_{ij} \left( \beta_{0,j} + \boldsymbol\beta_{j}^\top \mathbf{x}_i \right) \right) (#eq:multi-nominal-logit-loglik) \end{equation}
식 \@ref(eq:multi-nominal-logit-loglik)을 각 계수에 대해 미분하면 아래와 같이 정리된다.
\begin{equation} \begin{split} \frac{\partial \log L}{\partial \beta_{0,j}} &= \sum_{i = 1}^{n} v_{ij} - \frac{\exp \left( \beta_{0,j} + \boldsymbol\beta_{j}^\top \mathbf{x}i \right)}{1 + \sum{j = 2}^{J} \exp \left( \beta_{0,j} + \boldsymbol\beta_{j}^\top \mathbf{x}i \right)}\ \frac{\partial \log L}{\partial \beta{k,j}} &= \sum_{i = 1}^{n} v_{ij} x_{ik} - \frac{x_{ik} \exp \left( \beta_{0,j} + \boldsymbol\beta_{j}^\top \mathbf{x}i \right)}{1 + \sum{j = 2}^{J} \exp \left( \beta_{0,j} + \boldsymbol\beta_{j}^\top \mathbf{x}_i \right)}, \, k = 1, \cdots, p \end{split} (#eq:multi-nominal-logit-loglik-diff) \end{equation}
따라서, 명목 로지스틱 회귀분석은 식 \@ref(eq:multi-nominal-logit-loglik-diff)이 표현하는 $(J - 1) \times (p + 1)$개의 미분식을 모두 0으로 만드는 계수값을 찾는 문제가 된다. 이에 대한 closed form solution은 존재하지 않으므로, 각종 알고리즘을 이용하여 해를 찾아야 한다. Newton-Raphson method에 의해 해를 찾는 방법은 @czepiel2002maximum 에 보다 자세하게 설명되어 있다.
Table \@ref(tab:nominal-logistic-reg-train-data-print)의 학습데이터에 대해 명목 로지스틱 회귀모형을 학습하여 범주를 추정한 결과는 아래와 같다.
회귀계수를 추정하는 함수를 fit_multinom_logistic_regression()
으로 구현하였다.
fit <- fit_multinom_logistic_regression(defecttype, y, c(x1, x2), .reflevel = 3L, .control = list(fnscale = -1, reltol = 1e-10, maxit = 100000)) print(fit)
종속변수가 3개 이상의 범주를 가지며, 각 범주 간에 서열이 있는 경우에 대한 로지스틱 회귀모형을 소개한다.
data(telconnection, package = "dmtr")
knitr::kable(telconnection, booktabs = TRUE, align = c('r', 'r', 'r'), label = c('잡음(N)', '손실(L)', '만족도(y)'), caption = '성능변수에 따른 통신 만족도')
객체 $i$가 범주 $j$ 이하에 속할 누적확률을 $\kappa_{ij}$라 하자.
\begin{equation} \kappa_{ij} = P(y_i \leq j \, | \, \mathbf{x}_i), \, j = 1, \cdots, J \end{equation}
누적 로짓모형은 범주 누적확률의 로짓변환에 대한 선형 회귀모형이다.
\begin{equation} \log \left( \frac{\kappa_{ij}}{1 - \kappa_{ij}} \right) = \beta_{0,j} + \boldsymbol\beta^\top \mathbf{x}_i, \, j = 1, \cdots, J - 1 (#eq:cumulative-logit) \end{equation}
식 \@ref(eq:cumulative-logit)은 독립변수에 대한 계수 $\boldsymbol\beta$가 모든 범주에 대해 동일하며 절편(intercept) $\beta_{0,j}$만 범주에 따라 다른 비례 승산 모형(proportional odds model)이다. 즉, 범주에 관계없이 각 독립변수가 한 단위 증가할 때마다 로그 승산비는 동일하게 증가한다.
모형의 추정은 \@ref(nominal-logistic-regression)절과 유사하게 다항분포를 사용한 최우추정법을 사용할 수 있다. 각 객체 $i$가 범주 $j$에 속할 확률은 아래와 같다.
\begin{equation} \begin{split} \pi_{ij} &= \kappa_{ij} - \kappa_{i,j-1}\ &= \frac{\exp (\beta_{0,j} + \boldsymbol\beta^\top \mathbf{x}i)}{1 + \exp (\beta{0,j} + \boldsymbol\beta^\top \mathbf{x}i)} - \frac{\exp (\beta{0,j-1} + \boldsymbol\beta^\top \mathbf{x}i)}{1 + \exp (\beta{0,j-1} + \boldsymbol\beta^\top \mathbf{x}i)}, \, j = 2, \cdots, J - 1\ & \ \pi{i1} &= \kappa_{i1}\ &= \frac{\exp (\beta_{0,1} + \boldsymbol\beta^\top \mathbf{x}i)}{1 + \exp (\beta{0,1} + \boldsymbol\beta^\top \mathbf{x}i)}\ & \ \pi{iJ} &= 1 - \kappa_{i,J-1}\ &= 1 - \frac{\exp (\beta_{0,J-1} + \boldsymbol\beta^\top \mathbf{x}i)}{1 + \exp (\beta{0,J-1} + \boldsymbol\beta^\top \mathbf{x}_i)} \end{split} (#eq:cumulative-logit-prob) \end{equation}
로그 우도함수는
\begin{equation} \sum_{i = 1}^{n} \sum_{j = 1}^{J} y_i \log \pi_{ij} \end{equation}
이며, 이에 위에서 정리한 $\pi_{ij}$식을 대입하여 전개할 수 있다. 이 로그 우도함수는 concave 함수이므로[@pratt1981concavity], 각 계수에 대해 편미분하여 0이 되도록 하는 값을 구하는 방식으로 회귀모형을 추정할 수 있다.
회귀계수를 추정하는 함수를 fit_ordinal_logistic_regression()
으로 구현하였다.
fit <- fit_ordinal_logistic_regression( telconnection, y, c(N, L) ) print(fit)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.