비례오즈모델의 비례성 가정 검증 방법 소개 및 파이썬 예제
비례 오즈 모델을 이용한 순위 로지스틱 회귀 모델 탐구 비례 오즈 모델은 McCullagh (1980)에 의해 처음 도입되었으며, 이진 로지스틱 회귀를 순위형 종속 변수가 있는 상황으로 확장하였습니다. 이 모델은 독립 관찰, 로그-오즈의 선형성, 예측 변수 간 다중 공선성 부재, 그리고 비례 오즈 가정 등 여러 가정을 기반으로 합니다. 비례 오즈 가정은 순위형 종속 변수의 모든 임계값에서 회귀 계수들이 일정하다는 것을 의미합니다. 이 가정이 성립하는지 확인하는 것은 모델의 유효성과 해석 가능성에 매우 중요합니다. 이 논문에서는 Brant (1990)이 제안한 두 가지 방법을 중심으로 비례 오즈 가정을 평가하는 방법을 다룹니다. 또한 Python을 사용하여 실제 데이터에 이러한 기법을 적용하는 방법을 설명합니다. 이 글은 데이터 과학, 머신 러닝, 통계학 배경을 가진 독자들을 대상으로 하며, 순위 로지스틱 회귀 모델의 적합성을 평가하는 방법을 이해하는 데 도움이 됩니다. 1. 비례 오즈 모델 소개 우리는 N개의 독립 관찰을 가정하며, 각 관찰은 p개의 설명 변수 ( X_i = (X_{i1}, X_{i2}, \ldots, X_{ip}) )와 1부터 K까지 순서대로 범주화된 종속 변수 ( Y )로 표현됩니다. 비례 오즈 모델은 종속 변수 ( Y )의 누적 분포 확률을 설명 변수 ( X_i )의 함수로 모델링합니다. 이는 다음과 같이 정의됩니다: [ \text{logit}(\gamma_j) = \log\left(\frac{\gamma_j}{1 - \gamma_j}\right) = \theta_j - \beta^T X_i \quad \text{for } j = 1, 2, \ldots, K-1 ] 여기서 ( \theta_j )는 각 카테고리 j에 대한 절편이며, ( \theta_1 < \theta_2 < \cdots < \theta_{K-1} )를 만족해야 합니다. ( \beta )는 모든 카테고리에서 동일한 회귀 계수 벡터입니다. 비례 오즈 모델은 연속적인 잠재 변수 ( Y^* )의 존재를 가정하여 유도될 수 있습니다. 이 잠재 변수는 다음과 같은 선형 회귀 모델을 따릅니다: [ Y^* = \beta^T X_i + \epsilon ] 여기서 ( \epsilon )는 일반적으로 표준 로지스틱 분포를 따르는 오차항입니다. 잠재 변수 ( Y^* )는 임계값 ( \theta_j )들로 구분되어 관찰 가능한 순위형 변수 ( Y )를 생성합니다. 2. 비례 오즈 가정 평가: 우도 비율 검정 Brant (1990)은 비례 오즈 가정을 평가하기 위해 우도 비율 검정을 제안했습니다. 이 접근 방법은 회귀 계수가 카테고리에 따라 변할 수 있게 허용하는 덜 제약된 모델을 먼저 적합시킵니다. 이 모델은 다음과 같이 표현됩니다: [ \text{logit}(\gamma_j) = \theta_j - \beta_j^T X_i \quad \text{for } j = 1, \ldots, K-1 ] 여기서 ( \beta_j )는 각 카테고리 j에 대한 회귀 계수 벡터입니다. 비례 오즈 가정이 성립하지 않는다는 뜻입니다. 그런 다음, 우도 비율 검정을 사용하여 제약 모델과 비제약 모델을 비교합니다. 우도 비율 통계량은 다음과 같이 정의됩니다: [ \lambda = -2 \log \left( \frac{L(\hat{\theta}_0)}{L(\hat{\theta})} \right) ] 여기서 ( L(\hat{\theta}) )는 전체 모델의 최대 우도 추정치이고, ( L(\hat{\theta}_0) )는 비례 오즈 가정이 성립하는 제약 모델의 최대 우도 추정치입니다. 이 통계량은 카이제곱 분포를 따르며, 자유도는 전체 모델과 제약 모델의 매개변수 수의 차이인 ( (K-1) \times (p+1) - (K-1) - p = (K-2) \times p )입니다. 3. 비례 오즈 가정 평가: 개별 적합 접근 Mahalanobis 거리를 이해하는 것이 중요합니다. 이 거리는 동일한 분포를 공유하는 다변량 공간에서 두 벡터가 얼마나 다른지를 측정합니다. [ D_M(x, y) = \sqrt{(x - y)^T \Sigma^{-1} (x - y)} ] 이 거리는 카이제곱 분포를 따르며, 이를 통해 비례 오즈 가정을 평가할 수 있습니다. 비례 오즈 가정을 평가하기 위해, 각 임계값 ( j = 1, 2, \ldots, K-1 )에 대해 개별 이진 로지스틱 회귀 모델을 적합시키고, 추정된 회귀 계수들 사이의 차이를 검정합니다. 이는 다음과 같은 가설을 검정하는 것과 같습니다: [ H_0 : \beta_1 = \beta_2 = \cdots = \beta_{K-1} ] 각 이진 모델에서 추정된 회귀 계수 벡터 ( \hat{\beta}j )를 사용하여, 전역 벡터 ( \hat{\beta} = (\hat{\beta}_1^T, \hat{\beta}_2^T, \ldots, \hat{\beta}{K-1}^T)^T )를 구성합니다. 이 벡터는 점근적으로 정규 분포를 따르며, 그 분산-공분산 행렬 ( \Sigma(\hat{\beta}) )를 결정해야 합니다. Brant은 이 분산-공분산 행렬의 명시적인 추정치를 제공하며, 이는 각 이진 모델의 최대 우도 추정치 ( \hat{\beta}_j )를 기반으로 합니다. 이를 통해, 비례 오즈 가정을 검정하기 위한 Wald 통계량 ( X^2 )를 계산할 수 있습니다: [ X^2 = (\mathbf{D} \hat{\beta})^T \left[ \mathbf{D} \Sigma(\hat{\beta}) \mathbf{D}^T \right]^{-1} (\mathbf{D} \hat{\beta}) ] 이 통계량은 ( (K-2) \times p ) 자유도를 가진 카이제곱 분포를 따릅니다. 4. 예제: 두 비례 오즈 검정 방법의 Python 구현 이 예제는 "와인 품질" 데이터셋을 사용합니다. 이 데이터셋은 1,599개의 관찰과 12개의 변수를 포함하며, 목표 변수 "품질"은 3에서 8까지 순위형입니다. 충분한 관찰 수를 확보하기 위해, 3과 4 카테고리를 하나의 카테고리 (라벨 4)로, 7과 8 카테고리를 하나의 카테고리 (라벨 7)로 결합하여, 응답 변수가 네 개의 수준을 가지도록 조정하였습니다. 설명 변수의 이상치는 IQR 방법을 사용하여 처리하였고, "휘발성 산성도", "자유 황화수소", "총 황화수소" 세 가지 예측 변수를 선택하여 표준화하였습니다. 표 1: 개별 이진 로지스틱 회귀 모델의 적합된 계수 표 2: 비례 오즈 모델의 적합된 계수 표 1과 표 2에서 "휘발성 산성도" 계수의 차이가 특히 눈에 띕니다. 예를 들어, 첫 번째와 두 번째 이진 모델 사이의 "휘발성 산성도" 계수 차이는 -0.280이고, 두 번째와 세 번째 모델 사이의 차이는 0.361입니다. 이러한 차이는 비례 오즈 가정이 성립하지 않을 가능성을 시사합니다. 우도 비율 검정을 수행한 결과, 검정 통계량 ( LR = 53.207 )와 p-값 ( 1.066 \times 10^{-9} )가 얻어졌습니다. 이 결과는 5% 유의 수준에서 비례 오즈 가정이 위반되었음을 나타냅니다. 또한 Wald 검정 통계량 ( X^2 = 41.880 )와 p-값 ( 1.232 \times 10^{-7} )를 계산하여, 이 역시 5% 유의 수준에서 비례 오즈 가정이 위반되었음을 확인하였습니다. 결론 이 논문은 비례 오즈 가정을 평가하는 방법을 설명하고, Brant (1990)의 논문을 통해 더 깊게 이해하도록 독자를 권장합니다. Brant의 연구는 비례 오즈 가정 평가를 넘어서, 모델의 전반적인 적합성을 평가하는 방법을 제공합니다. 예를 들어, 잠재 변수 ( Y^* )가 로지스틱 분포를 따르는지 또는 다른 링크 함수가 더 적절한지를 검정하는 방법을 제시합니다. 이 글에서는 비례 오즈 가정의 전반적인 평가에 집중하였지만, Brant은 특정 계수가 위반의 원인인지를 세밀하게 분석하는 방법도 다루고 있으므로, 논문을 전체적으로 읽는 것을 강력히 권장합니다. 이미지 및 참고 문헌 본 논문의 모든 이미지와 시각화는 Python (pandas, matplotlib, seaborn, plotly) 및 Excel을 사용하여 작성되었습니다. 참고 문헌은 다음과 같습니다: Brant, Rollin. 1990. "Assessing Proportionality in the Proportional Odds Model for Ordinal Logistic Regression." Biometrics, 1171–78. McCullagh, Peter. 1980. "Regression Models for Ordinal Data." Journal of the Royal Statistical Society: Series B (Methodological) 42 (2): 109–27. Wasserman, L. (2013). All of Statistics: A Concise Course in Statistical Inference. Springer Science & Business Media. Cortez, P., Cerdeira, A., Almeida, F., Matos, T., & Reis, J. (2009). Wine Quality [Dataset]. UCI Machine Learning Repository. https://doi.org/10.24432/C56S3T. 데이터 및 라이선스 본 논문에서 사용된 데이터셋은 Creative Commons Attribution 4.0 International (CC BY 4.0) 라이선스 하에 공개되었습니다. 이 라이선스는 사용, 배포, 수정이 허용되며, 상업적 용도에서도 사용 가능합니다. 단, 적절한 출처 표시가 필요합니다. 코드 예시 데이터 불러오기 및 관찰 수 확인: ```python import pandas as pd data = pd.read_csv("winequality-red.csv", sep=";") data.head() 품질 변수 재분류 data['quality'].value_counts(normalize=False).sort_index() data['quality'] = data['quality'].replace({3: 4, 8: 7}) data['quality'].value_counts(normalize=False).sort_index() print("관찰 수:", data.shape[0]) ``` 이상치 처리: ```python def remove_outliers_iqr(df, column): Q1 = df[column].quantile(0.25) Q3 = df[column].quantile(0.75) IQR = Q3 - Q1 lower_bound = Q1 - 1.5 * IQR upper_bound = Q3 + 1.5 * IQR return df[(df[column] >= lower_bound) & (df[column] <= upper_bound)] for col in data.columns: if col != 'quality': data = remove_outliers_iqr(data, col) ``` 각 품질 그룹별 변수의 박스플롯 생성: ```python var_names_without_quality = [col for col in data.columns if col != 'quality'] import matplotlib.pyplot as plt import seaborn as sns plt.figure(figsize=(15, 10)) for i, var in enumerate(var_names_without_quality): plt.subplot(3, 4, i + 1) sns.boxplot(x='quality', y=var, data=data) plt.title(f'{var}의 품질별 박스플롯') plt.xlabel('품질') plt.ylabel(var) plt.tight_layout() plt.show() ``` 비례 오즈 가정 검정을 위한 순위 회귀 모델 구현: ```python from statsmodels.miscmodels.ordinal_model import OrderedModel from sklearn.preprocessing import StandardScaler explanatory_vars = ['volatile acidity', 'free sulfur dioxide', 'total sulfur dioxide'] data[explanatory_vars] = StandardScaler().fit_transform(data[explanatory_vars]) def fit_ordered_logistic_regression(data, response_var, explanatory_vars): model = OrderedModel( data[response_var], data[explanatory_vars], distr='logit' ) result = model.fit(method='bfgs', disp=False) return result response_var = 'quality' result = fit_ordered_logistic_regression(data, response_var, explanatory_vars) print(result.summary()) log_reduced = result.llf print(f"제약 모델의 로그 우도: {log_reduced}") ``` 전체 다항 로지스틱 모델 계산: ```python import statsmodels.api as sm data_sm = sm.add_constant(data[explanatory_vars]) model_full = sm.MNLogit(data[response_var], data_sm) result_full = model_full.fit(method='bfgs', disp=False) print(result_full.summary()) log_full = result_full.llf print(f"전체 모델의 로그 우도: {log_full}") LR_statistic = 2 * (log_full - log_reduced) print(f"우도 비율 통계량: {LR_statistic}") df1 = (len(thresholds) - 1) * len(explanatory_vars) df2 = result_full.df_model - OrderedModel( data[response_var], data[explanatory_vars], distr='logit' ).fit().df_model print(f"자유도: {df1}") print(f"전체 모델의 자유도: {df2}") from scipy.stats import chi2 p_value = chi2.sf(LR_statistic, df1) print(f"p-값: {p_value}") if p_value < 0.05: print("귀무 가설을 기각: 비례 오즈 가정이 위반됨.") else: print("귀무 가설을 기각하지 않음: 비례 오즈 가정이 성립함.") ``` Wald 통계량 ( X^2 ) 계산: ```python def wald_statistic(D, betaStar, varBeta): Db = D @ betaStar V = D @ varBeta @ D.T inv_V = np.linalg.inv(V) X2 = float(Db.T @ inv_V @ Db) return X2 K_1 = len(binary_models) p = len(explanatory_vars) D = construct_D(K_1, p) X2 = wald_statistic(D, betaStar, varBeta) ddl = (K_1 - 1) * p pval = 1 - chi2.cdf(X2, ddl) print(f"Wald 통계량 X² = {X2:.4f}") print(f"자유도 = {ddl}") print(f"p-값 = {pval:.4g}") ``` 업계 전문가의 평가 비례 오즈 모델은 순위형 자료를 분석하는 데 널리 사용되는 강력한 도구입니다. 그러나 비례 오즈 가정이 성립하지 않는 경우, 모델의 해석성이 크게 저하될 수 있습니다. Brant (1990)의 방법은 모델의 적합성을 체계적으로 평가하는 데 유용하며, Python을 사용하여 실제 데이터에 적용할 수 있습니다. 본 연구는 비례 오즈 가정의 검정뿐만 아니라, 모델의 전반적인 적합성을 평가하는 다양한 방법을 제시하여, 데이터 분석가들에게 실질적인 도움을 줍니다.