[Python]단순선형회귀분석 실습 - 데이터 불러오기부터 회귀계수까지

2020. 6. 10. 16:31ML in Python/Python

실습에 사용될 데이터 : 보스턴 주택 데이터

Target Data

-1978 보스턴 주택 가격
-506개 타운의 주택 가격 중앙값 (단위 1,000 달러)

Feature Data

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

Boston_house.csv
0.03MB

 

 


 

import pandas as pd                                                  # Dataframe 활용 라이브러리
import numpy as np                                                   # 행렬 활용 라이브러리
import statsmodels.api as sm                                         # 통계기법 활용 라이브러리

# 데이터 불러오기
boston = pd.read_csv("./Boston_house.csv")
boston.head()

 

boston.head() - df.head()는 Data의 상위 5개 행을 보여준다.

# Target 제외한 데이터만 뽑기
boston_data = boston.drop(["Target"],axis=1)  

# Data 통계 뽑아보기
boston_data.describe()

boston_data.describe() - df.describe()는 기초 통계 정보를 제공한다.

# crim 변수로 단순 선형 회귀분석 진행

target = boston[['Target']]
crim = boston[['CRIM']]
rm = boston[['RM']]
lstat = boston[['LSTAT']]

# 여기서 boston data에 존재하는 column을 지정할 때, 대괄호 두 개를 사용한 것(df[["colname"]])은
# 데이터 프레임의 개별 컬럼데이터를 Series 형태가 아닌 DataFrame형태로 추출하고자 함
# df["colname"] - Series Type / df[["colname"]] - DataFrame Type
# target ~ crim 선형회귀분석

# crim DataFrame에 선형회귀분석을 위한 b0항 (상수항)을 더해준다.
crim1 = sm.add_constant(crim, has_constant = "add") 
crim1 

crim1 DataFrame

 

# sm OLS 적합
model1 = sm.OLS(target, crim1)
fitted_model1 = model1.fit()

# summary 함수통해 결과출력
fitted_model1.summary()

# OLS를 통해 출력된 summary에는 Warning이 있다. 이는 잔차항(에러항)이 정규분포/등분산을 가정한 결과이다. 
# 즉, 그렇기에 잘못된 결과가 도출될 수도 있다.
# 실제 데이터를 활용할 때는 데이터셋을 확인하는 작업을 통해 모델을 달리하거나,
# 전처리를 통해 데이터를 가공해 줄 필요가 있다.

fitted_model1.summary() - sm.OLS(target, feature).fit().summary()는 OLS결과를 출력한다.

 위를 보면 R-squeared 가 0.151로 모델의 설명력이 낮다는 것을 확인 할 수 있다. 이는 더 높은 영향력을 찾을 변수를 추가하거나 다른 변수를 선택할 필요가 있다고 판단된다.   

# 회귀 계수 출력
fitted_model1.params     

fitted_model1.params 

 

# 방법1 - Y_hat = beta0 + beta1*X 계산하기
pred0 = np.dot(crim1, fitted_model1.params)

# 방법2 - predict함수를 통해 Y_hat 구하기
pred1 = fitted_model1.predict(crim1)

# numpy를 사용하여 직접구한 Y_hat과 predict함수를 통해 구한 Y_hat은 차이가 없다
pred0 - pred1                                        # 모든 predict 행 오차 = 0

pred0 - pred1, 두 예측이 동일하다는 것을 확인할 수 있다.

# 적합시킨 직선 시각화

import matplotlib.pyplot as plt                     # 파이썬 시각화 라이브러리 
 
plt.yticks(fontname = "Arial")                      
plt.scatter(crim,target,label="data")               # 실제 데이터 분포를 알아보기 위한산점도 표기 방법이다. 
                                                    # 점의 label은 "data"로 정해주었다.
plt.plot(crim,pred1,label = "result")               # 회귀선 표기를 위한 선형 그래프이다
                                                    # label은 "result"로 정해주었다.
plt.legend()                                        # plt.legend()함수는 범주를 plot에 그리는 함수이다.
plt.show()

시각화1 - 산점도 및 회귀선 표시

# 실제값과 예측(단순 선형회귀)값 비교

plt.scatter(target, pred1)
plt.xlabel("real_value")
plt.ylabel("pred_value")
plt.show()

# 아래 그래프를 보면 단순 선형회귀가 개별 변수들을 예측하는 것에는 한계가 있음을 보인다.
# 만약 완전하게 예측을 진행한다면, Y축 값과 X축 값은 항상 같은 결과가 나와야한다.
# 즉, Y = X 그래프이어야 한다. 

# 선형 회귀분석은 사실 현실 데이터에서 추세를 알고자 하는 용도로 쓸 순 있겠지만
#, 실제로 이 회귀분석을 통해 값을 예측하고 적용하기에는 한계가 있다.

시각화2 - 실제값과 예측값

## residual 시각화

fitted_model1.resid.plot()                
# model.resid는 각 항의 예측값과 실제값의 오차를 Series형태로 출력해주는 함수이다. 

plt.xlabel("residual_number")
plt.show()

시각화3 - 잔차 시각화

 

 위의 실습에서는 "CRIM" 변수 한 가지만 이용해서 단순 선형회귀분석을 진행하였다. 하지만, 이는 다른 변수에도 똑같은 방법으로 적용된다. 다음 차례는 다중 회귀분석을 같은 데이터로 진행해보겠다.