다중선형회귀(Multiple Linear Regression) – 파이썬 코드 예제

이전에 선형회귀에 대한 개념을 소개한 바 있다. X의 값에 따라 Y값이 어떻게 달라질지 예측하는, 기울기와 절편만 있는 단순한 1차 방정식 y = m*X + b로 설명했는데, 이건 그냥 단순선형회귀라고 부른다. (만약 선형회귀의 개념이 생소하다면 반드시 알고 넘어가야 하니, 아래 글을 참고하자.)

참고 글: 선형회귀(Linear Regression) 쉽게 이해하기

아무튼 우리가 사는 세상은 단순선형회귀로 설명할 수 있을만큼 그렇게 단순하지 않다. 고려해야 하는 변수 X가 하나가 아니라는 의미다.

예를 들어 주택 임대료를 예측한다고 했을 때, 주택의 면적만 고려해서 예측하면 단순회귀가 되겠지만 지어진지 얼마나 오래 되었는지, 지하철 역과 거리가 얼마나 가까운지 등 다양한 요소의 영향을 받는다. 결국 주택 임대료 y를 예측하려면 여러 개의 변수 x를 포함해야 하는 거다. 이를 다중선형회귀(Multiple Linear Regression)라고 하며, 방정식으로 나타내면 아래와 같다.

식으로 보면 쉽지만 변수가 많기 때문에 시각화를 해놓으면 인간의 인지 능력으로는 이해할 수 없어진다. x 변수를 두 개만 넣고 시각화 해도 이런 식으로 나오는데…

그러니 기계의 힘을 빌리자.

이제부터 파이썬으로 다중선형회귀 분석하는 방법을 코드 예제와 함께 살펴보자.


데이터 불러오기

pandas를 통해 일단 csv로 저장된 예제 데이터를 불러와봤다. 예제 데이터는 뉴욕 맨해튼의 주택 임대료와 관련한 테이블이다.

import pandas as pd

df = pd.read_csv("manhattan.csv")
df.head()

맨 왼쪽에 “rent”라는 항목이 있는데, 이게 주택의 임대료다. 이걸 예측하는 게 우리의 목표다. 그 외의 항목들은 침실이 몇개 있는지, 지하철 역에서 몇 분 거리에 있는지, 엘리베이터가 있는지 등 주택에 대한 다양한 정보다. 아래와 같이 총 14개의 정보가 있다.

['bedrooms', 'bathrooms', 'size_sqft', 'min_to_subway', 'floor', 'building_age_yrs', 'no_fee', 'has_roofdeck', 'has_washer_dryer', 'has_doorman', 'has_elevator', 'has_dishwasher', 'has_patio', 'has_gym']

데이터 세트 분리하기 (Training & Test)

가지고 있는 데이터를 모두 사용해서 다중선형회귀 모델을 만들 수도 있지만, 우리는 실제로 생성한 모델이 잘 예측하는지 테스트를 해보기 위해 학습(train) 데이터와 시험(test) 데이터를 분리해보자. (모든 데이터에 주택 임대료 “rent” 정답이 있으니, 시험 데이터를 예측 모델에 넣어서 실제 정답을 잘 맞추는지 보기 위함이다.)

데이터 세트 분리는 sklearn에서 train_test_split을 통해 손쉽게 할 수 있다.

아래와 같이 8:2 정도의 비율로 나눠보자.

from sklearn.model_selection import train_test_split

x = df[['bedrooms', 'bathrooms', 'size_sqft', 'min_to_subway', 'floor', 'building_age_yrs', 'no_fee', 'has_roofdeck', 'has_washer_dryer', 'has_doorman', 'has_elevator', 'has_dishwasher', 'has_patio', 'has_gym']]

y = df[['rent']]

x_train, x_test, y_train, y_test = train_test_split(x, y, train_size=0.8, test_size=0.2)

다 된 거다.


모델 생성하기

이제 모델을 생성하자. 당연히 학습 데이터를 가지고 모델을 생성한다.

방법은 단순선형회귀와 똑같다.

from sklearn.linear_model import LinearRegression

mlr = LinearRegression()
mlr.fit(x_train, y_train) 

끝난 거다.

이제 만약 내가 주택에 대한 14개 항목값 넣어주면 주택 임대료를 예측해준다.

my_apartment = [[1, 1, 620, 16, 1, 98, 1, 0, 1, 0, 0, 1, 1, 0]]
my_predict = mlr.predict(my_apartment)
[[2393.58059075]]

이제 x 시험 데이터 x_test를 넣어 예측한 y 값들을 y_predict라고 저장해보자. 추후에 시험 데이터에 있는 실제 정답, 즉 y_test와 비교해보기 위함이다.

y_predict = mlr.predict(x_test)

matplotlib의 시각화를 통해 간단히 확인하고 넘어가보자.

x축은 실제 임대료, y축은 예측한 임대료다. 만약 정답을 맞춘다면 정확히 선으로 일치되어 나올 거다.

import matplotlib.pyplot as plt

plt.scatter(y_test, y_predict, alpha=0.4)
plt.xlabel("Actual Rent")
plt.ylabel("Predicted Rent")
plt.title("MULTIPLE LINEAR REGRESSION")
plt.show()

임대료가 낮은 항목들은 꽤 가깝게 맞추는데, 높은 임대료에서는 오차가 좀 있는 걸 알 수 있다. 그래도 어쨌든 얼추 잘 나오는 것 같다.


회귀계수와 상수 확인하기

위에서도 언급했지만 다중회귀는 아래와 같은 방정식으로 표현할 수 있다.

단순선형회귀는 우리가 직접 그릴 수 있는 1차 방정식 y = m*x + b으로 설명이 되기 때문에 m을 기울기, b를 절편이라고 불렀다.

그런데 다중회귀에서는 변수가 많기 때문에 조금 표현을 달리해야겠다. 일단 모든 변수 x마다 각각의 m이 있다. 그러니 이것들을 회귀계수라고 부르자. 그리고 b는 그냥 상수라고 부르자.

아무튼 다중회귀에서도 단순회귀와 똑같이 이 값들을 확인할 수 있다. 모델 뒤에 .coef_ , .intercept_라고 써주면 끝이다.

print(mlr.coef_)
[[-302.73009383 1199.3859951 4.79976742 -24.28993151 24.19824177
-7.58272473 -140.90664773 48.85017415 191.4257324 -151.11453388
89.408889 -57.89714551 -19.31948556 -38.92369828]]

위 모델에서 총 14개의 변수를 사용했기 때문에 회귀계수도 당연히 14개가 존재한다.

그런데 이렇게 보면 대체 어떤 변수가 중요한 건지 감이 안 온다.


상관 살펴보기

그럴 땐 matplotlib에서 scatter 플롯을 그려서 변수들과 주택 임대료의 상관을 살펴보자

# 주택의 면적 'size_sqft'과 가격 'rent'
plt.scatter(df[['size_sqft']], df[['rent']], alpha=0.4)
plt.show()
# 주택이 얼마나 오래 전에 지어졌는지 'building_age_yrs'와 가격 'rent'
plt.scatter(df[['building_age_yrs']], df[['rent']], alpha=0.4)
plt.show()

일단 이 두 개의 그림만 봐도 주택 면적은 상관이 있는데 얼마나 오래된 건물인지는 딱히 상관이 나타나지 않는 걸 알 수 있다.


모델의 정확도(Accuracy) 평가하기

위에서 데이터 세트를 나눠놨기 때문에 학습 시킨 모델을 테스트 할 수 있다.

다중선형회귀 모델의 정확도를 평가할 때는 잔차 분석(Analysis)을 하면 된다. 잔차는 실제 값 y와 예측된 값 ŷ의 차 e를 말한다. 방정식으로 표현하면 이렇게.

sklearnlinear_model.LinearRegression를 사용해서 모델을 생성하면 .score()라는 메서드를 사용할 수 있는데 라고 하는 결정계수(coefficient of determination)를 돌려준다. 결정계수 은 이렇게 표현할 수 있다.

이게 뭐냐… 개념적으로만 일단 이해해보자.

일단 분자에 있는 u는 잔차의 제곱의 평균 RSS(residual sum of square)직선이 미처 Y에 대해 설명하지 못한 변화량을 의미한다.

((y - y_predict) ** 2).sum()

분모에 있는 vTSS(total sum of squares), y값의 총 변화량으로 이해하면 된다.

((y - y.mean()) ** 2).sum()

결국 결정계수 R²는 전체에서 직선이 미처 설명하지 못한 부분의 비율을 뺀 거다.

아무튼 어려우면 다 잊고 그냥…….

결정계수 R²가 클수록 실제값과 예측값이 유사함을 의미하며, 데이터를 잘 설명한다고 이해하자.

그러니 모델이 얼마나 정확한지 평가할 때도 이 결정계수 가 기준이 될 수 있는 거다.

예를 들어, 주택 사이즈(“size_sqft”)와 침실 개수(“bedrooms”)를 기준으로 임대료를 예측하는 모델의 R²이 0.72인 경우 그 2개의 변수들이 함께 임대료 변동의 72%를 설명한다는 뜻이다.

여기에 다른 x 변수, 주택이 얼마나 오래 전에 지어졌는지(“building_age_yrs”)를 모델에 추가하면 새로운 R²가 0.95로 증가했다고 하자. 그럼 주택 사이즈(“size_sqft”), 침실 개수(“bedrooms”), 얼마나 오래 전에 지어졌는지(“building_age_yrs”) 이 3개의 변수가 함께 임대료 변동의 95%를 설명한다는 거다.

당연히 최선의 R²는 1이겠지만 그건 말이 안 되고, 일반적으로 0.7 정도면 양호한 것으로 간주한다.

위 예제에서 14개의 변수를 넣고 생성한 모델의 결정계수를 확인해보자.

print(mlr.score(x_train, y_train))
0.7725460559817883

꽤 높다.

주택 임대료의 77%를 저 14개의 항목으로 설명할 수 있다는 의미다.

일단 선형회귀분석은 여기까지…!

나도 파이썬 더 잘하고 싶다.

추천 글

“다중선형회귀(Multiple Linear Regression) – 파이썬 코드 예제”의 21개의 댓글

    1. scatterplot 그리는 소스코드는 본문에 다 있으니 바로 참고하실 수 있을 것 같고요.

      만약 처음에 나오는 3D 그래프를 그리실 거면
      matplotlib 공식문서와 함께 아래와 같은 글 참고하시면 될 거 같습니다.
      https://www.aiproblog.com/index.php/forums/topic/multiple-linear-regression-with-python-numpy-matplotlib-plot-in-3d/
      https://aegis4048.github.io/mutiple_linear_regression_and_visualization_in_python

      구글링 조금만 해보셔도 많이 나올 거예요.

    1. 저도 비전공자로 제가 공부한 걸 남긴 건데 도움이 되셨다니 기쁘네요.
      혹시 읽어보시다가 제가 잘못 적은 게 있다면 알려주세요. 감사합니다. 🙂

  1. 머신러닝좌가되고싶다

    초보자의 시선에서 이해하기 쉽게 설명해주셔서 감사합니다. 많은 도움이 되었네요!!!

  2. 꾸밈 없이 살기

    안녕하세요. 회귀 분석 공부 중에 찾았는데 정리가 너무 잘 되어있어서 잘 읽히고 좋네요. 블로그 글 써주셔서 감사합니다. 덕분에 공부하기 좋네요. 다른 블로그 카테고리도 너무 좋아요 🙂 응원합니다! 좋은 하루 보내세요.

  3. 그냥 가려다가 댓글 좋아하신다길래 너무 감사해서 댓글 달고 갑니다!
    다른 script 계속 검색해서 해봤는데 잘 안되어서 고생 좀 했었거든요. 그런데 여기서 보고 따라했는데 잘 해결되었어요!
    정말 정말 감사합니다!!!

    그런데 저 말고도 이 스크랩을 복사해서 하시는 분들 중 안되시는 분들을 위해 한가지 말씀드리자면
    중간에 “y_predicted = mlr.predict(x_test)” 이 부분의 y_predicted 를 y_predict 로 바꾸셔야 할 것 같아요!
    바로 아래 스크랩에는 y_predict로 써있어서 복사해서 쓰시는 분들은 아마 오류가 날 것 같아요!
    저도 계속 오류가 나서 뭐지 하고 꼼꼼히 읽어보다가 발견했어요!!

    무튼 저도 비전공자로써 거의 매일 맨땅에 헤딩하면서 하고 있는데
    여기 블로그 보고 많이 배워갑니다. 감사의 마음으로 광고 하나 클릭하고 갑니다.

    1. 오타 발견해주셨네요. 감사합니다.
      덕분에 본문에도 수정 반영했습니다!

      그리고 광고 클릭까지………
      덕분에 0.3달러 정도 벌었네요. 감사합니다. 하핫 🙂

  4. 안녕하세요
    정말 큰 도움이 되는거 같습니다^^
    혹시 사용하셨던 맨해튼 주택가격 예제 파일은 어디서 구할수있을까요?
    그대로 따라해보려고 하는데
    이왕이면 사용하셨던 파일 그대로 해보고 싶어서요

  5. 현업에 뛰어들면서 여러사이트를 찾아보았는데 여기만큼 사용자관점에서 설명해주신 블로그는 못봤습니다.
    너무 도움이 많이되었습니다.

    저뿐만 아니라 다른분들에게 도움이 될수있도록 github이나 블로그에 전체소스코드가 공유되면 더더욱 좋을꺼같아요
    안되면 아쉬울뿐입니다.. ㅎㅎ

  6. 해외에서 박사 수료중입니다만, 정말 좋은 퀄리티의 블로그인것 같습니다.
    올해 여름부터 봤는데 많은 사람들이 좋아해주시네요.
    감사합니다.

    1. 저도 어려운 내용은 잘 몰라서
      공부하고 이해한 수준에서 최대한 쉽게 기억하려고 남겨놓은 건데
      이 분야에 입문하시는 분들께 도움이 되는 것 같기도 하더라고요.

      기분 좋은 댓글 제가 더 감사합니다. 🙂

댓글 남기기