1. Intro

 

지난번의 단순선형회귀에 이어 이번엔 다중선형회귀를 알아보자. 말이 어려워서 그런데 그냥 변수가 여러개면 다중선형회귀다. 마치 요렇게 생긴 데이터처럼 말이다! (킹 카운티 주택 데이터다.. 아주아주 익숙한 예제데이터) 

 

우리는 주택 가격을 예측하고 싶고 예측을 계산하기 위한 변수로 방 개수나 방 사이즈 등을 알 수 있다. 

 

 

이런 경우 변수가 다양하기 때문에 이런 회귀식을 쓸 수 있을것이다 

 

 

파이썬에서 사용할 코드는 아주 간단하다. 지난번과 똑같이 타깃과 피쳐를 정해주고, 모델 선언 후 학습, 파라미터들을 찍어보면 절편과 기울기를 쉽게 알 수 있다

 

predictors = ['SqFtTotLiving', 'SqFtLot', 'Bathrooms', 
              'Bedrooms', 'BldgGrade']
outcome = 'AdjSalePrice'

house_lm = LinearRegression()
house_lm.fit(house[predictors], house[outcome])

print(f'Intercept: {house_lm.intercept_:.3f}')
print('Coefficients:')
for name, coef in zip(predictors, house_lm.coef_):
    print(f' {name}: {coef}')

변수별로 계수가 나온다 

Intercept: -521871.368
Coefficients:
 SqFtTotLiving: 228.83060360240793
 SqFtLot: -0.06046682065307607
 Bathrooms: -19442.840398321066
 Bedrooms: -47769.95518521438
 BldgGrade: 106106.96307898081

 

단순선형회귀와 마찬가지로 계수를 가지고 타깃과 피쳐들간의 관계를 해석하면 된다.  예를 들어 변수 중 SqFtotLiving (제곱피트, 주택 사이즈) 가 1 오르면 주택 가격은 299달러 증가한다 정도로 말이다 ! 

 

 

 

2. 평가지표 & 모델해석 

 

 

만들어진 선형모델이 얼마나 예측을 잘 하는지 평가할 때는 평가 지표를 쓴다. RMSE 와 r2 score 가 예제에 있었는데 다른 지표들보단 이게 제일 통상적으로 쓰이는듯하다 

 

fitted = house_lm.predict(house[predictors])
RMSE = np.sqrt(mean_squared_error(house[outcome], fitted))
r2 = r2_score(house[outcome], fitted)
print(f'RMSE: {RMSE:.0f}')
print(f'r2: {r2:.4f}')
RMSE: 261220
r2: 0.5406

 

모델 summary 를 찍어보면 모델 내부의 좀 더 심층적인 상관관계를 알 수 있다. DA 적 관점에서 변수의 설명력을 보여줄 수 있는 부분은 여기가 아닐까 예측해본다

 

model = sm.OLS(house[outcome], house[predictors].assign(const=1))
results = model.fit()
print(results.summary())

이런식으로 summary 가 나오는데 ! 여기서부터가 굉장히 중요하다!

왜냐...

 

다들 들어는 봤을 것이다 데이터 공부하면 한 번쯤 들어보는 오컴의 면도날 

 

 

단순한 모델을 만들려면? 

어떤 변수가 높은 설명력을 가지는지 알아야 하니까 말이다 

summary 는 변수별로 모델 내에서 어떤 영향을 끼쳤는지 다각도로 분석해준다 

 

 

  OLS Regression Results                            
==============================================================================
Dep. Variable:           AdjSalePrice   R-squared:                       0.541
Model:                            OLS   Adj. R-squared:                  0.540
Method:                 Least Squares   F-statistic:                     5338.
Date:                Mon, 26 Sep 2022   Prob (F-statistic):               0.00
Time:                        01:31:23   Log-Likelihood:            -3.1517e+05
No. Observations:               22687   AIC:                         6.304e+05
Df Residuals:                   22681   BIC:                         6.304e+05
Df Model:                           5                                         
Covariance Type:            nonrobust                                         

                   coef    std err          t      P>|t|      [0.025      0.975]
---------------------------------------------------------------------------------
SqFtTotLiving   228.8306      3.899     58.694      0.000     221.189     236.472
SqFtLot          -0.0605      0.061     -0.988      0.323      -0.180       0.059
Bathrooms     -1.944e+04   3625.388     -5.363      0.000   -2.65e+04   -1.23e+04
Bedrooms      -4.777e+04   2489.732    -19.187      0.000   -5.27e+04   -4.29e+04
BldgGrade      1.061e+05   2396.445     44.277      0.000    1.01e+05    1.11e+05
const         -5.219e+05   1.57e+04    -33.342      0.000   -5.53e+05   -4.91e+05
==============================================================================
Omnibus:                    29676.557   Durbin-Watson:                   1.247
Prob(Omnibus):                  0.000   Jarque-Bera (JB):         19390738.346
Skew:                           6.889   Prob(JB):                         0.00
Kurtosis:                     145.559   Cond. No.                     2.86e+05
...
Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 2.86e+05. This might indicate that there are
strong multicollinearity or other numerical problems.

 

* 분산: 차이값의 제곱의 평균 

 

* R-squared: 결정계수, 데이터들이 예측값으로부터 얼마나 떨어져있는지를 계산해서 분산을.. 어떻게 잘 계산하던데 공식은 다른데 검색해보자. 값이 크면 예측이 정확하다는거다. 왜냐면 독립변수가 종속변수를 그만큼 더 잘 설명한다는거라서! 다른 지표들은 작을수록 좋은건데 얜 클수록 (1에 가까울수록) 좋다.

 

* Adj. R-squared: 조정된 결정계수: 변수가 많을수록 상관계수가 좀 올라감. 요걸 잘 조정해준 애

 

* F-Static : 값이 크면 데이터로 선형이 잘 안 그려진다는 뜻이다. 계수 중 하나라도 0이 아닌게 있다면 유의미한 모델이라는 뜻

 

*Prob(f-static): 귀무가설의 정확도를 알려줌

 

* log-likelihood: 우도, likelihood 에 로그를 씌워 만든건데 그 과정은 잘 모르겠구,, "데이터 샘플의 예측값이 어느정도 가능성을 가지냐" 를 나타내주는 값이랜다. 이걸로 aic, bic score 를 계산함 

 

* AIC & BIC: 모델이 복잡해질 수록 페널티를 주는 애들임. 그러니 작을수록 좋음. 다른 지표가 다 좋고 이 스코어들까지 좋다면 모델이 단순한 모델 (최소한의 변수로 복잡도를 잘 낮춘 모델) 이라는 뜻이다. 후자가 좀 더 강력하게 이걸 구분해내는 지표! 

 

*참고자료 

https://aliencoder.tistory.com/24

 

*std error: standard deviation 의 추정치임. 낮을수록 해당 변수의 설명력이 강한것임 

 

*P>|t|: 제일 중요함! 요걸 이용해 p-value 를 계산하는데, 두번째 변수의 저 값이 0.37이라는건 37프로 확률로 저 변수와 타깃은 상관관계가 없다는 뜻이다

 

 

 

자 그럼 이런 지표들로 어떻게 "설명력이 높은 변수들만 적절히 남긴" 그리고 복잡도가 낮아져 "AIC score 가 낮은" 모델을 고를 수 있을까? R 은 이걸 자동으로 해주는 패키지가 있는거같은데 사이킷런에는 없다 ! ㅎㅎ 그래서 함수로 구현한걸 보겠다

 

 

y = house[outcome]

def train_model(variables): #주어진 변수 내에서 적합 모델만 반환
    if len(variables) == 0:
        return None
    model = LinearRegression()
    model.fit(X[variables], y)
    return model

def score_model(model, variables): #모델과 변수 세트 사이의 AIC score 를 반환
    if len(variables) == 0:
        return AIC_score(y, [y.mean()] * len(y), model, df=1)
    return AIC_score(y, model.predict(X[variables]), model)

#모델 결정 패키지
best_model, best_variables = stepwise_selection(X.columns, train_model, score_model, 
                                                verbose=True)

print()
print(f'Intercept: {best_model.intercept_:.3f}')
print('Coefficients:')
for name, coef in zip(best_variables, best_model.coef_):
    print(f' {name}: {coef}')

이렇게 돌리면 모델 복잡도를 기준으로 다음과 같은 순위의 결과를 반환한다. 

Variables: SqFtTotLiving, SqFtLot, Bathrooms, Bedrooms, BldgGrade, NbrLivingUnits, SqFtFinBasement, YrBuilt, YrRenovated, NewConstruction, PropertyType_Single Family, PropertyType_Townhouse
Start: score=647988.32, constant
Step: score=633013.35, add SqFtTotLiving
Step: score=630793.74, add BldgGrade
Step: score=628230.29, add YrBuilt
Step: score=627784.16, add Bedrooms
Step: score=627602.21, add Bathrooms
Step: score=627525.65, add PropertyType_Townhouse
Step: score=627525.08, add SqFtFinBasement
Step: score=627524.98, add PropertyType_Single Family
Step: score=627524.98, unchanged None

Intercept: 6178645.017
Coefficients:
 SqFtTotLiving: 199.2775530420169
 BldgGrade: 137159.56022619663
 YrBuilt: -3565.424939249451
 Bedrooms: -51947.38367361402
 Bathrooms: 42396.16452772084
 PropertyType_Townhouse: 84479.16203300131
 SqFtFinBasement: 7.046974967551216
 PropertyType_Single Family: 22912.055187017668

 

 

이렇게 모델에 변수를 하나씩 더해가면서 기여도가 통계적으로 더이상 유의미하지 않을때 멈추는 방법을 전진선택이라고 한다. 반대로 하나씩 빼는 후진제거 방법도 있고, 아니면 설명력이 작은 변수에 대해 계수를 줄이는 벌점회귀방식 (라소가 대표적인 예시) 도 있다

 

 

 

3, 가중회귀 

 

최소제곱법은 그런데 이상치에 민감할 수 밖에 없다. (그리고 실제로 많은 데이터들은 그렇다) 그래서 특잇값에 패널티를 부과하거나 없애거나, 혹은 설명력이 더 좋거나 믿을만한 변수에 가중치를 부과하는 방법이 가중회귀다.

 

조금 더 어렵게 말하자면, 등분산성이 충족되지 않을 때 (서로 다른 두개 이상의 집단을 비교하고자 할때, 기본적으로 해당 집단들이 만족해야되는 조건 중 한가지로 분산이 같음을 의미) 가중치가 포함된 가중회귀를 쓴다

 

파이썬 상에서 구현할때는 

 

sample_weight 파라미터만 달아주면 된다. 

 

house_wt.fit(house[predictors], house[outcome], sample_weight=house.Weight)
728x90
반응형
허니비 honeybee