IT/AI\ML

[python] 결정계수 R2와 자유도 조정 결정 계수 R*2

개발자 두더지 2021. 11. 28. 23:29
728x90

 다중회귀 분석의 결과 지표 중 하나는 "결정계수"이다. 1에 가까울수록 좋은 결과가된다. 그러나, 결정계수만으로는 결과를 잘못 이해할 가능성이 있기 때문에, 결정계수에 대해 잘 이해해둬야할 필요가 있다.

 먼저 결정계수에 대해 가볍게 살펴보고 가자. 결정계수는 회귀 분석에 의해 도출된 목적 변수의 예측 값이, 실제 목적 변수의 값과 어느정도 일지하는가를 표시하는 지표이다. 회귀분석에는 y=ax+b이라는 식으로 표시할 수 있는 단일 회귀 분석과 설명변수가 여러 개 있는 다중 회귀 분석이 있다. 

(이번 포스팅에서는 결정계수 계산식에 대해서는 다루지 않고, 자유도 조정 결정 계수에 대한 것을 주로 다룰 것이다)

 

단일 회귀분석에 있어서 결정계수


 단일 회귀 분석에서는  y=ax+b의 형식으로 목적 변수(y)의 값을 요측하지만, 어디까지나 "예측값"이므로, 실제의 목적 변수의 값과 완전히 일치하지 않는다. 그러므로, 무엇을 설명변수(x)으로 할 것인지가에 따라 "예측이 거의 맞는" 경우와 "별로 맞지 않는" 경우가 있다.

 위 그림의 왼쪽이 "예측이 거의 맞는" 상태이고, 오른쪽이 "거의 맞지 않는" 상태라는 것을 알 수 있다. 이러한 두 가지 경우를 비교하기 위해서는 "예측이 어느정도 맞고 있는가"를 객관적으로 표시하는 지표가 결정지표이다. 결정계수는 0부터 1사이의 범위 값으로, 앞서 말했듯이 1에 가까울수록 좋은 결과가 된다. 이 숫자는 밀접히는 "회귀분석한 결과가 목적변수의 분산을 어느정도 설명하고 있는가"에 의해 정의되고 있다.

 

 

다중 회귀분석에 있어서 결정계수


 계속해서 다중회귀 분석이다. 설명 변수가 2개인 경우는 아래의 경우와 같다.

 2차원이었던 단일 회귀분석과 달리 3차원의 공간에 점이 허공에 뜬 상태가 되지만, 기본적인 결정계수와는 동일하다. 이 경우세도 "(이 그림의 경우는) x와 z로부터 구해진 y의 예측값이 실제의 y과 어느정도 일치하고 있는가"를 표시하고 있는 것이 결정계수이다. 아까의 2차원의 회귀 분석의 경우와 동일하게 오차가 적으면 적을수록 좋은 결과가 된다.

 

 

"결정계수"와 "자유도 조정 결정계수"


 여기까지 회귀분석 및 다중회귀분석에 의한 결정계수에 대해 설명했다. 일반적인 통계 소프트웨어를 사용하여 회귀 분석을 실행한 경우에는 결정계수와 함께 "자유도 조정 결정계수"가 표시되는 경우가 많다고 생각되므로 이 두 가지의 차이에 대해서 간단히 설명하도록 하겠다. "한국 국민 전체에서 랜덤으로 1000명을 골라 앙케이트를 한다"고 생각해보자.

 이 앙케이트의 결과에 대해서도 회귀분석을 하여, 여기서 얻어진 회귀 계수를 바탕으로 결정계수를 냈다. 그러나, 여기서 구해진 회귀계수는 어디까지나 "우연히 선택된 1000명"에 대한 가장 예측이 맞도록 요구된 것이다. 한국 국민 전체를 대상으로 "우연히 선택된 1000명"에 최적화된 결과를 적용하면 일반적으로 예측이 나쁘게 된다.

 이러한 문제에 대해서 대처하기 위한 것이 "자유도 조정 결정계수"이다. 값의 수정으로는 샘플 수와 설명 변수의 갯수를 구해진 "자유도"이라는 숫자를 사용한다.

 즉 한마디로 얘기하자면, 결정계수는 절대적인 지표가 될 수 없다. 

 

 

자유도 조정 결정계수


 자유도 조정 결정 계수는 아래의 식으로 표현할 수 있다.

 여기서 n은 데이터 점의 갯수, p는 설명 변수의 갯수이다. 설명 변수를 늘리면 필연적으로 결정계수가 증가되므로, 이 영향을 조정한 지표이다.

 

 

python 코드로 자유도 조정 결정계수 구현하기


 이번 검증에 사용할 데이터는 scikit-learn의 datasets 중에 보스턴 주택 데이터(설명변수 13개)이다. 아래와 같이 설명 데이터세트와 목적 변수 데이터 세트를 작성하였다.

import pandas as pd
from sklearn.datasets import load_boston
X = pd.DataFrame(load_boston().data, columns=load_boston().feature_names)
y = pd.DataFrame(load_boston().target, columns=['target'])

 python으로 자유도 결정 계수를 구할 수 있는 방법이 크게 두 가지가 있다. 하나는 sklearn.linear_model 이고 다른 하나는 statsmodels.api이다.

 

sklearn.linear_model 을 이용한 방법

먼저 선형 회귀 모델을 작성하여 결정 계수를 구한다.

from sklearn.linear_model import LinearRegression
model = LinearRegression()
model.fit(X, y)
model.score(X, y)
#---> 0.7406426641094094

 sklearn.metrics의 r2_score을 사용하는 것이 보다 빠르게 결정 계수를 구할 수 있다. 

from sklearn.metrics import r2_score
y_pred = model.predict(X)
r2_score(y, y_pred)
#---> 0.7406426641094094

 자유도 조정 결정계수에 대해서는 식을 바탕으로 정의하면 다음과 같다.

# 자유도 조정 결정계수를 계산하는 함수를 정의한다.
def adj_r2_score(y_true, y_pred, p=X.shape[1]):
    return 1-(1-r2_score(y_true, y_pred)) * (len(y_true)-1) / (len(y_true) - p - 1)

adj_r2_score(y, y_pred)
#---> 0.7337897263724629

 

statsmodels.api를 사용한 방법

statsmodels.api를 사용하면 간단히 결정계수와 자유도 조정 결정계수를 구할 수 있다.

import statsmodels.api as sm
# 상수항의 추가
X1 = sm.add_constant(X)
m = sm.OLS(y, X1)
result = m.fit()
# 결정계수의 표시
print(result.rsquared)
#---> 0.7406426641094095
# 자유도 조정 결정계수의 표시
print(result.rsquared_adj)
#---> 0.733789726372463

 LinearRegression에서는 기본적으로 상수항인 어떤 회귀 모델이 작성되지만, statsmodels에서는 기본적으로 상수항이 아닌 회귀 모델이 작성된다. 따라서 모델 작성 전에 상수항을 추가해줘야한다.


참고자료

https://xica.net/adva/column/about-coefficient-of-determination/

https://qiita.com/bianca26neve/items/4ddcf5ca12652b652f04

 

728x90