[Python] 데이터 사이언스 스쿨 - 4.3 스케일링

Updated:

데이터 사이언스 스쿨 자료를 토대로 공부한 내용입니다.

실습과정에서 필요에 따라 내용의 누락 및 추가, 수정사항이 있습니다.


기본 세팅

import numpy as np
import pandas as pd

import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns

import warnings
%matplotlib inline
%config InlineBackend.figure_format = 'retina'

mpl.rc('font', family='NanumGothic') # 폰트 설정
mpl.rc('axes', unicode_minus=False) # 유니코드에서 음수 부호 설정

# 차트 스타일 설정
sns.set(font="NanumGothic", rc={"axes.unicode_minus":False}, style='darkgrid')
plt.rc("figure", figsize=(10,8))

warnings.filterwarnings("ignore")

4.3 스케일링

4.3.1 회귀분석과 조건수

조건수

행렬의 조건수(conditional number)는 가장 큰 고유치와 가장 작은 고유치의 비율을 뜻한다.

회귀분석에서는 공분산행렬 $X^{T}X$의 가장 큰 고유치와 가장 작은 고유치의 비율이 된다.

조건수가 클때의 문제점

import scipy as sp

A = sp.linalg.hilbert(4)
A
array([[1.        , 0.5       , 0.33333333, 0.25      ],
       [0.5       , 0.33333333, 0.25      , 0.2       ],
       [0.33333333, 0.25      , 0.2       , 0.16666667],
       [0.25      , 0.2       , 0.16666667, 0.14285714]])
  • 위 행렬은 4차 힐버트 행렬로 조건수가 매우 큰 행렬이다.
np.linalg.cond(A)
15513.738738929038
  • 조건수가 약 15,514로 매우 크다.
b = np.ones((4,1))
b
array([[1.],
       [1.],
       [1.],
       [1.]])
  • 이번엔 모든 값이 1인 4 x 1 행렬을 생성하였다.

  • 그냥 벡터로 만들어도 상관없다.

sp.linalg.solve(A, b)
array([[  -4.],
       [  60.],
       [-180.],
       [ 140.]])
  • 위 코드는 $Ax = b$인 연립방적식에서 $x$의 해를 찾아주는 코드이다.

  • 결과를 보면 값이 잘 나왔음을 확인 할 수 있다.

sp.linalg.solve(A + 0.0001 * np.eye(4), b)
array([[ -0.58897672],
       [ 21.1225671 ],
       [-85.75912499],
       [ 78.45650825]])
  • 이번엔 $A$ 행렬에 0.0001에 오차를 추가해서 $x$의 해를 찾아보았다.

  • 아주 작은 오차가 생겼는데 해의 값이 많이 달라졌다.

  • 이처럼 조건수가 크면 작은 오차에도 값이 크게 달라진다.

  • 회귀분석의 경우 $X^{T}X$의 조건수가 커지면 예측값 역시 오차가 커질 수 밖에 없다.

회귀분석에서 조건수가 커지는 경우

  1. 변수들의 단위 차이로 인해 숫자의 스케일이 크게 달라지는 경우. 이 경우에는 스케일링(scaling)으로 해결한다.

  2. 다중 공선성 즉, 상관관계가 큰 독립 변수들이 있는 경우, 이 경우에는 변수 선택이나 PCA를 사용한 차원 축소 등으로 해결한다.

Boston 데이터 회귀분석

from sklearn.datasets import load_boston
import statsmodels.api as sm

boston = load_boston()

dfX = pd.DataFrame(boston.data, columns=boston.feature_names)
dfy = pd.DataFrame(boston.target, columns=["MEDV"])
df = pd.concat([dfX, dfy], axis=1)

model1 = sm.OLS.from_formula("MEDV ~ " + "+".join(boston.feature_names), data=df)
result1 = model1.fit()
print(result1.summary())
                            OLS Regression Results                            
==============================================================================
Dep. Variable:                   MEDV   R-squared:                       0.741
Model:                            OLS   Adj. R-squared:                  0.734
Method:                 Least Squares   F-statistic:                     108.1
Date:                Fri, 11 Jun 2021   Prob (F-statistic):          6.72e-135
Time:                        19:05:29   Log-Likelihood:                -1498.8
No. Observations:                 506   AIC:                             3026.
Df Residuals:                     492   BIC:                             3085.
Df Model:                          13                                         
Covariance Type:            nonrobust                                         
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
Intercept     36.4595      5.103      7.144      0.000      26.432      46.487
CRIM          -0.1080      0.033     -3.287      0.001      -0.173      -0.043
ZN             0.0464      0.014      3.382      0.001       0.019       0.073
INDUS          0.0206      0.061      0.334      0.738      -0.100       0.141
CHAS           2.6867      0.862      3.118      0.002       0.994       4.380
NOX          -17.7666      3.820     -4.651      0.000     -25.272     -10.262
RM             3.8099      0.418      9.116      0.000       2.989       4.631
AGE            0.0007      0.013      0.052      0.958      -0.025       0.027
DIS           -1.4756      0.199     -7.398      0.000      -1.867      -1.084
RAD            0.3060      0.066      4.613      0.000       0.176       0.436
TAX           -0.0123      0.004     -3.280      0.001      -0.020      -0.005
PTRATIO       -0.9527      0.131     -7.283      0.000      -1.210      -0.696
B              0.0093      0.003      3.467      0.001       0.004       0.015
LSTAT         -0.5248      0.051    -10.347      0.000      -0.624      -0.425
==============================================================================
Omnibus:                      178.041   Durbin-Watson:                   1.078
Prob(Omnibus):                  0.000   Jarque-Bera (JB):              783.126
Skew:                           1.521   Prob(JB):                    8.84e-171
Kurtosis:                       8.281   Cond. No.                     1.51e+04
==============================================================================

Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 1.51e+04. This might indicate that there are
strong multicollinearity or other numerical problems.
  • Boston 데이터 회귀분석 결과 Notes[2]를 해석하면 다음과 같다.

    조건수(conditiona number)가 15,100으로 너무 큽니다.

    강한 다중공선성(multicollinearity)이나 다른 수치적 문제가 있을 수 있습니다.

"+".join(boston.feature_names)
'CRIM+ZN+INDUS+CHAS+NOX+RM+AGE+DIS+RAD+TAX+PTRATIO+B+LSTAT'
  • 참고로 OLS.from_formula()에 직접 수식을 지정하므로 변수들을 편하게 넣기 위해 위와 같은 방법을 사용한다.
dfX.std()
CRIM         8.601545
ZN          23.322453
INDUS        6.860353
CHAS         0.253994
NOX          0.115878
RM           0.702617
AGE         28.148861
DIS          2.105710
RAD          8.707259
TAX        168.537116
PTRATIO      2.164946
B           91.294864
LSTAT        7.141062
dtype: float64
  • Boston 데이터의 독립변수의 경우 단위가 0.1 수준부터 100 수준까지 혼재되어 있다.
feature_names = list(boston.feature_names)
feature_names.remove("CHAS") 
feature_names = [f"scale({name})" for name in feature_names] + ["CHAS"]

model3 = sm.OLS.from_formula("MEDV ~ " + "+".join(feature_names), data=df)
result3 = model3.fit()

print(result3.summary())
                            OLS Regression Results                            
==============================================================================
Dep. Variable:                   MEDV   R-squared:                       0.741
Model:                            OLS   Adj. R-squared:                  0.734
Method:                 Least Squares   F-statistic:                     108.1
Date:                Fri, 11 Jun 2021   Prob (F-statistic):          6.72e-135
Time:                        19:05:29   Log-Likelihood:                -1498.8
No. Observations:                 506   AIC:                             3026.
Df Residuals:                     492   BIC:                             3085.
Df Model:                          13                                         
Covariance Type:            nonrobust                                         
==================================================================================
                     coef    std err          t      P>|t|      [0.025      0.975]
----------------------------------------------------------------------------------
Intercept         22.3470      0.219    101.943      0.000      21.916      22.778
scale(CRIM)       -0.9281      0.282     -3.287      0.001      -1.483      -0.373
scale(ZN)          1.0816      0.320      3.382      0.001       0.453       1.710
scale(INDUS)       0.1409      0.421      0.334      0.738      -0.687       0.969
scale(NOX)        -2.0567      0.442     -4.651      0.000      -2.926      -1.188
scale(RM)          2.6742      0.293      9.116      0.000       2.098       3.251
scale(AGE)         0.0195      0.371      0.052      0.958      -0.710       0.749
scale(DIS)        -3.1040      0.420     -7.398      0.000      -3.928      -2.280
scale(RAD)         2.6622      0.577      4.613      0.000       1.528       3.796
scale(TAX)        -2.0768      0.633     -3.280      0.001      -3.321      -0.833
scale(PTRATIO)    -2.0606      0.283     -7.283      0.000      -2.617      -1.505
scale(B)           0.8493      0.245      3.467      0.001       0.368       1.331
scale(LSTAT)      -3.7436      0.362    -10.347      0.000      -4.454      -3.033
CHAS               2.6867      0.862      3.118      0.002       0.994       4.380
==============================================================================
Omnibus:                      178.041   Durbin-Watson:                   1.078
Prob(Omnibus):                  0.000   Jarque-Bera (JB):              783.126
Skew:                           1.521   Prob(JB):                    8.84e-171
Kurtosis:                       8.281   Cond. No.                         10.6
==============================================================================

Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
  • CHAS는 카테고리 변수이므로 스케일링에서 제외한다.

  • 스케일링 하였을 때 조건수가 10.6으로 줄어든 것을 확인 할 수 있다.

Leave a comment