IT/Machine Learning

회귀모델 성능지표 결정계수란? (feat. 기준값, 음수, 조정된 결정계수)

엘티엘 2021. 3. 3. 12:30

결정계수란?

  • 회귀모델이 주어진 자료에 얼마나 적합한지를 평가하는 지표
  • y의 변동량대비 모델 예측값의 변동량을 의미함
  • 0~1의 값을 가지며, 상관관계가 높을수록 1에 가까워짐
  • r2=0.3인 경우 약 30% 정도의 설명력을 가진다 라고 해석할 수 있음
  • sklearn의 r2_score의 경우 데이터가 arbitrarily할 경우 음수가 나올수 있음
  • 음수가 나올경우 모두 일괄 평균으로 예측하는 것보다 모델의 성능이 떨어진다는 의미
  • 결정계수는 독립변수가 많아질 수록 값이 커지기때문에, 독립변수가 2개 이상일 경우 조정된 결정계수를 사용해야 함

 

결정계수 수식

아래 결정계수 수식이다.

  • SSR > SST 보다 클 경우 음수가 나올수가 있음
  • 이는 모델의 예측값이 평균값으로 예측하는것보다 정확하지 않을때 발생함

결정계수

 

아래는 조정된 결정계수 수식이다.

  • 기존의 결정계수에 n(데이터 개수), k(변수 개수)가 추가됨
  • k(변수 개수)값이 커질수록 전체적인 값이 작아짐. 따라서 변수가 많아질수록 값이 커지는 기존 결정계수의 단점을 보완함
  • n(데이터 개수)가 커질수록 k의 영향도(?)가 작아짐. 따라서 데이터가 많다면 변수가 많아도 기존 결정계수값이 유사하게 유지됨

조정된 결정계수

 

일반적인 결정계수 기준

  • 일반적으로 Bio는 0.95, 공학은 0.7, 사회과학은 0.3 정도를 기준으로 한다고 함.
  • Cohen이라는 학자는 아래와 같이 효과크기에 따른 결정계수의 기준을 제시함
  • 보통 사회과학에서는 이중 medium의 기준인 0.13 정도를 기준으로 함

sklearn r2_score로 결정계수 확인하기

아래는 sklearn 의 보스턴 집값예측 데이터와 LinearRegression을 활용해 결정계수 및 조정된 결정계수를 계산했다.

처음은 단순 LinearRegression을 했고(Feature 13개), 두번째는 PolynomialFreature를 활용해서 Feature를 105개로 늘려서 LinearRegression을 적용했다.

from sklearn.datasets import load_boston
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import PolynomialFeatures
from sklearn.metrics import r2_score, mean_squared_error
import pandas as pd


def adj_r2(r2, n, p):
    return 1 - (1-r2)*(n-1)/(n-p-1)


data = load_boston()

################ 단순 LinearRegression ################
df = pd.DataFrame(data['data'], columns=data['feature_names'])

train_x, test_x, train_y, test_y = train_test_split(df, data['target'], test_size=0.3)

lr = LinearRegression()
lr.fit(train_x, train_y)

r2 = r2_score(lr.predict(test_x), test_y)

print("df.shape", df.shape, "r2_score", r2, "adj_r2_score", adj_r2(r2, test_x.shape[0], test_x.shape[1]))



################ PolynimialFeature 활용 ################
df = pd.DataFrame(data['data'], columns=data['feature_names'])
df2 = PolynomialFeatures().fit_transform(df)

train_x, test_x, train_y, test_y = train_test_split(df2, data['target'], test_size=0.3)

lr = LinearRegression()
lr.fit(train_x, train_y)

r2 = r2_score(lr.predict(test_x), test_y)

print("df.shape", df2.shape, "r2_score", r2, "adj_r2_score", adj_r2(r2, test_x.shape[0], test_x.shape[1]))

아래는 출력 결과다. 첫번째 결과를 살펴보면, adj_r2의 값이 0.43 정도이다.

  • 첫번째: df.shape (506, 13) r2_score 0.4824869009493715 adj_r2_score 0.433735666980834
  • 두번째: df.shape (506, 105) r2_score 0.8265107679574099 adj_r2_score 0.4305027382949759

사회과학(집값) 문제이므로, 일반적인 기준(0.3)에 적용해보면 유의미하다고 볼 수도 있겠다.

다만, 주의해서 볼 점은 두번째 모델의 결정계수(r2)가 첫번째 모델의 값보다 월등히 높지만(0.48 vs 0.82), 조정된 결정계수(adj_r2)는 거의 차이가 없다는 점이다. 이처럼 성능(조정된 결정계수)에 큰 차이가 없다면, 오히려 첫번째 모델을 사용하는게 나은 선택이 될 수도 있다.

예를 들어 설명력이 중요한 상황이라면 첫번째 모델이 더 나을수 있고, 정확도가 중요하다면 두번째 모델이 더 나을수 있다.

반응형