[Python] 데이터 사이언스 스쿨 - 4.1 회귀분석 예제

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.1 회귀분석 예제

4.1.1 보스턴 집값 예측

sklearn 패키지의 datasets 서브패키지는 회귀분석을 공부하기 위한 예제를 제공한다.

그 중 load_boston() 명령으로 받을 수 있는 보스턴 주택 가격 데이터는 다음과 같은 데이터이다.

보스턴의 506개 타운(town)의 13개 독립변수값로부터 해당 타운의 주택가격 중앙값을 예측하는 문제다.

사용할 수 있는 특징 데이터는 다음과 같다.

변수 설명
CRIM 범죄율
INDUS 비소매상업지역 면적 비율
NOX 일산화질소 농도
RM 주택당 방 수
LSTAT 인구 중 하위 계층 비율
B 인구 중 흑인 비율
PTRATIO 학생/교사 비율
ZN 25,000 평방피트를 초과 거주지역 비율
CHAS 찰스강의 경계에 위치한 경우는 1, 아니면 0
AGE 1940년 이전에 건축된 주택의 비율
RAD 방사형 고속도로까지의 거리
DIS 직업센터의 거리
TAX 재산세율
MEDV 보스턴 506개 타운의 1978년 주택 가격 중앙값 (단위 1,000 달러)

종속변수는 MEDV로 사실 원래 변수명이 따로 없이 저장되어 있는데 밑에 실습에서 MEDV로 지정할 것이다.

Boston 데이터 불러오기

from sklearn.datasets import load_boston

temp = load_boston()
dir(temp)
['DESCR', 'data', 'feature_names', 'filename', 'target']

load_boston() 명령으로 받는 데이터 집합은 Bunch 라는 클래스 객체로 생성된다.

이 클래스 객체는 다음과 같은 속성을 가진다.

  • data: 독립변수 ndarray 배열

  • target: 종속변수 ndarray 배열

  • feature_names: 독립변수 이름 리스트

  • target_names: (옵션) 종속변수 이름 리스트

  • DESCR: (옵션) 자료에 대한 설명 문자열

x_data = pd.DataFrame(temp.data, columns = temp.feature_names)
y_data = pd.DataFrame(temp.target, columns = ["MEDV"])

boston = pd.concat([x_data, y_data], axis = 1)
boston.head()
CRIM ZN INDUS CHAS NOX RM AGE DIS RAD TAX PTRATIO B LSTAT MEDV
0 0.00632 18.0 2.31 0.0 0.538 6.575 65.2 4.0900 1.0 296.0 15.3 396.90 4.98 24.0
1 0.02731 0.0 7.07 0.0 0.469 6.421 78.9 4.9671 2.0 242.0 17.8 396.90 9.14 21.6
2 0.02729 0.0 7.07 0.0 0.469 7.185 61.1 4.9671 2.0 242.0 17.8 392.83 4.03 34.7
3 0.03237 0.0 2.18 0.0 0.458 6.998 45.8 6.0622 3.0 222.0 18.7 394.63 2.94 33.4
4 0.06905 0.0 2.18 0.0 0.458 7.147 54.2 6.0622 3.0 222.0 18.7 396.90 5.33 36.2
  • load_boston()의 여러 속성을 이용해서 boston 데이터 프레임을 생성하였다.

  • 종속 변수는 MEDV로 이름을 지정하였다.

일부 변수 시각화

sns.pairplot(boston[["MEDV", "RM", "AGE"]])
plt.suptitle("Boston Pair Plot, 일부 독립변수와 종속변수 시각화", y=1.03)
plt.show()

png

  • 방 개수(RM)가 증가할 수록 집값(MEDV)은 증가하는 경향이 보인다.

  • 노후화 정도(AGE)와 집값은 관계(MEDV)가 없어 보인다.

4.1.2 당뇨병 진행도 예측

scikit-learn 패키지가 제공하는 당뇨병 진행도 예측용 데이터는 442명의 당뇨병 환자를 대상으로한 검사 결과를 나타내는 데이터이다.

변수 설명
age 나이
sex 성별
bmi BMI(Body mass index)지수
bp 평균혈압
s1~s6 6종류의 혈액검사수치
종속변수 1년 뒤 측정한 당뇨병의 진행률

Diabetes 데이터 불러오기

from sklearn.datasets import load_diabetes

temp = load_diabetes()
diabetes = pd.DataFrame(temp.data, columns=temp.feature_names)
diabetes["target"] = temp.target
diabetes.tail()
age sex bmi bp s1 s2 s3 s4 s5 s6 target
437 0.041708 0.050680 0.019662 0.059744 -0.005697 -0.002566 -0.028674 -0.002592 0.031193 0.007207 178.0
438 -0.005515 0.050680 -0.015906 -0.067642 0.049341 0.079165 -0.028674 0.034309 -0.018118 0.044485 104.0
439 0.041708 0.050680 -0.015906 0.017282 -0.037344 -0.013840 -0.024993 -0.011080 -0.046879 0.015491 132.0
440 -0.045472 -0.044642 0.039062 0.001215 0.016318 0.015283 -0.028674 0.026560 0.044528 -0.025930 220.0
441 -0.045472 -0.044642 -0.073030 -0.081414 0.083740 0.027809 0.173816 -0.039493 -0.004220 0.003064 57.0

일부 변수 시각화

sns.pairplot(diabetes[["target", "bmi", "bp", "s1"]])
plt.suptitle("Diabetes Pair Plot, 일부 독립변수와 종속변수 시각화", y=1.03)
plt.show()

png

  • 독립변수 BMI지수와 평균혈압은 종속변수인 당뇨병 진행도와 양의 상관관계를 가지는 것을 볼 수 있다.

  • 독립변수 BMI지수와 평균혈압도 서로 양의 상관관계를 가져 다중공선성이 보인다.

4.1.3 연습문제

sklearn.datasets 패키지의 fetch_california_housing 명령은 캘리포니아 주택가격을 예측하기위한 데이터다.

이 데이터의 독립변수를 조사하고 어떤 데이터들이 주택가격과 상관관계가 있는지를 조사한다.

또한 서로 강한 상관관계를 가지는 독립변수도 알아보자.

California 데이터 불러오기

from sklearn.datasets import fetch_california_housing

temp = fetch_california_housing()

california = pd.DataFrame(temp.data, columns=temp.feature_names)
california["MedHouseVal"] = temp.target
california.tail()
MedInc HouseAge AveRooms AveBedrms Population AveOccup Latitude Longitude MedHouseVal
20635 1.5603 25.0 5.045455 1.133333 845.0 2.560606 39.48 -121.09 0.781
20636 2.5568 18.0 6.114035 1.315789 356.0 3.122807 39.49 -121.21 0.771
20637 1.7000 17.0 5.205543 1.120092 1007.0 2.325635 39.43 -121.22 0.923
20638 1.8672 18.0 5.329513 1.171920 741.0 2.123209 39.43 -121.32 0.847
20639 2.3886 16.0 5.254717 1.162264 1387.0 2.616981 39.37 -121.24 0.894

상관관계 확인

corr_M = california.corr()
mask = np.array(corr_M)
mask[np.tril_indices_from(mask)] = False

plt.figure(figsize= (10,8))

sns.heatmap(corr_M, 
            cmap = sns.light_palette("red", as_cmap=True),
            annot = True, 
            mask = mask)

plt.show()

png

  • 종속변수 MedHouseVal와 상관관계가 높은 독립변수는 MedInc이다.

  • 독립변수간에는 AveRooms와 AveBedrms, Latitude와 Longitude가 서로 강한 상관관계를 가지고 있다.

일부 변수 시각화

sns.pairplot(california[["MedHouseVal", "MedInc", "AveRooms", "AveBedrms", "Latitude", "Longitude"]])
plt.suptitle("California Pair Plot, 일부 독립변수와 종속변수 시각화", y=1.03)
plt.show()

png

  • 상관계수로 확인 하였듯이 변수간 선형관계가 보인다.

  • Latitude와 Longitude는 비선형 형태에 가까워 보인다.

4.1.4 가상 데이터 예측

가상 데이터 만들기

datasets 서브패키지에는 가상 회귀 분석 예제를 만들 수 있는 make_regression() 함수가 있다.

해당 함수에 대한 설명은 다음과 같다.

X, Y, B  = make_regression(
    n_samples, n_features, bias, noise, random_state, coef=True, n_informative, effective_rank, tail_strength)
옵션 입력 자료형 설명
n_samples 정수(디폴트 100) 표본 데이터의 갯수 n
n_features 정수(디폴트 100) 독립변수의 수 p
bias 실수(디폴트 0) Y 절편
noise 실수(디폴트 0) 오차항의 표준편차 $\epsilon$의 표준편차
random_state 정수(디폴트 None) 난수 발생용 시드값
coef 불리언(디폴트 False) True면 회귀 계수 출력
n_informative 정수(디폴트 10) 독립변수 중 종속변수와 상관 관계가 있는 독립변수의 수
effective_rank 정수 또는 None(디폴트 None) 독립변수 중 서로 독립인 독립변수의 수. 만약 None이면 모두 독립
tail_strength 0~1사이의 실수(디폴트 0.5) effective_rank가 None이 아닌 경우 독립변수간의 상관관계를 결정하는 변수. 0.5면 독립변수간의 상관관계가 없다.

출력은 다음과 같다.

  • X: (n_samples, n_features) 형상의 2차원 배열로 독립변수의 표본 데이터 행렬 $X$, n x p

  • Y: (n_samples) 형상의 1차원 배열로 종속변수의 표본 데이터 벡터 $Y$, n x 1

  • B: (n_features) 형상의 1차원 배열로 선형 모형의 계수 벡터 $\beta$, p x 1

    혹은 (n_features, n_targets) 형상의 2차원 배열 (옵션)
    
    입력 인수 coef가 True 인 경우에만 출력됨 - 절편 제외
    
from sklearn.datasets import make_regression

X, Y, B = make_regression(
    n_samples=200, n_features=1, bias=2, noise=10, coef=True, random_state=1017
)
x = np.linspace(-3, 3, 100)
y0 = B * x + 2

plt.figure(figsize= (10,8))

# 회귀식 - 오차항 고려없이 계수로 생성, 모수 beta를 이미 알고 있음
plt.plot(x, y0, "r-")

# 산점도
plt.scatter(X, Y)

plt.xlabel("x")
plt.ylabel("y")
plt.title("make_regression 예제")

plt.show()

png

  • make_regression() 으로 만든 가상 데이터 산점도이다.

  • 독립변수는 1개, 절편은 2, 오차항의 표준편차는 10으로 설정하였다.

  • 오차항 고려 없이 만든 직선을 기준으로 데이터가 잘 퍼져있다.

def make_regression2(n_informative, effective_rank, tail_strength, i):
    X, Y, B = make_regression(
        n_samples=300, n_features=2, noise=10, coef=True, random_state=0,
        n_informative = n_informative, effective_rank= effective_rank, tail_strength = tail_strength
    )
    
    axs[i].scatter(X[:, 0], X[:, 1], c=Y, s=100, cmap=mpl.cm.bone)

    axs[i].set_xlabel("x1")
    axs[i].set_ylabel("x2")

fig, axs = plt.subplots(1,3, figsize= (15,6))

make_regression2(2,None,0.5, 0)
make_regression2(1,None,0.5, 1)
make_regression2(2,1,0, 2)
    
plt.axis("equal")

axs[0].set_title("독립변수: 서로 독립, 종속변수와 모두 상관 관계")
axs[1].set_title("독립변수: 서로 독립, 종속변수와 하나만 상관 관계")
axs[2].set_title("독립변수가 독립이 아닌 경우")

plt.show()

png

  • 종속변수 값은 점의 명암으로 표시하였으며 밝을수록 종속변수 값이 큰 것이고 점의 어두울수록 작은 값이다.

  • 첫 번째 산점도에선 x1, x2 모두 증가할수록 종속변수 값이 커지는 것을 알 수 있다.

  • 두 번째 산점도에선 x2가 증가할수록 종속변수 값이 증가하지만 x1에 따라선 큰 차이가 없다.

  • 세 번쨰 산점도에선 x1, x2가 상관관계를 가지는 것을 확인 할 수 있다.

Leave a comment