통계학에서 가장 먼저 배우는 통계 모델은 회귀분석이다. 회귀분석에도 종류가 여러가지 있지만 그 중에서 단순회귀분석을 가장 먼저 배운다. 구조는 단순하지만 구조는 단순하지만 개념이 동일하기 때문에 배우기에 좋다. 파이썬에서 회귀분석을 하는 방법은 여러가지가 있다. 오늘은 그 중에서 머신러닝에 많이 사용되는 패키지, 사이킷런(scikit-learn)을 이용해서 회귀분석 하는 방법에 대해서 알아보도록 하겠다.

 

 

파이썬 회귀분석

 


단순회귀분석은 하나의 변수와 다른 변수 사이의 선형관계를 보여주는 모델이다. 인터넷에 검색해보면, 단순회귀분석에 대한 자세한 내용이 많이 있다. 몇 가지 중요한 부분만 짚고 넘어가도록 하겠다. 단순회귀분석은 아래와 같은 통계 모형을 만들고, x에 따른 예측값을 구한다.

 

단순 회귀식

 

 

1. 통계학에서 하는 방법을 먼저 알아보자.

실제 y값과 예측값의 차이를 잔차라고 하는데, 이 잔차가 최소가 되는 모형을 찾아야 한다. 잔차가 최소가 되는 모형은 RSS(residual sum of squares, 잔차제곱합)가 최소로 되는 값을 찾는 것이다. 통계학에서는 이를 최소제곱추정법(least squares method)라고 하고, 이를 통해 추정되는 값을 최소제곱추정량(least squares estimator)라고 한다. 잔차제곱합을 편미분하면 얻을 수 있다고 한다.

 

잔차 제곱합

 

 

2. 머신러닝에서 하는 방법은 이렇다.

머신러닝에서는 Gradient descent(경사하강법)을 이용한다. 이는 미분의 개념을 최적화 문제에 적용한 것으로 local minimum(또는 maximum)을 찾는 방법이다. Gradient는 경사, descent는 하강이라는 뜻이다. 경사를 따라 하강하면서 가장 최소의 값을 주는 파라미터를 찾는 것이다.

 

절차는 이렇다. 가장 최적의 모형 파라미터를 찾기 위해 Cost Function을 정의한다. 위의 경우에는 잔차제곱합을을 Cost Function으로 정의했다고 가정하자. 특정 지점(임의의 파라미터)에서 경사(기울기)를 구한다. 이 때 미분을 사용한다. 기울기가 양이라면, 현재 지점(현재 파라미터값)보다 음의 방향으로 움직인다. (경사를 따라 내려간다고 이해하면 되겠다.)


이 때 기울기(그레디언트 값)에 learning rate를 곱해준다. learning rate가 크면 학습속도가 빠르지만 이동범위가 넓어 값이 최소로 수렴하지 않을 수 있고, 너무 작으면 이동범위가 너무 좁아 계속 학습을 시켜도 최소값에 가지 못할 수 있다.


시작 지점에 따라 경사를 따라 내려온 위치가 다를 수도 있다. 이 때 Convex Function이라는 개념이 나온다. Convex Function은 Cost Function이 밥그릇을 뒤집어 놓은 모양으로 나오는 경우를 말한다고 한다. 이 때는 어디에서 시작해도 밥그룻의 제일 아랫부분에 도달하게 된다. 그래서 Cost Function이 Convex Function인 것을 확인하면, local minization에 도달하게 될 것이라는 문제는 걱정하지 않아도 된다.

 

 

3. 파이썬 회귀분석 하기

사설이 길었지만 이제 사이킷런 패키지로 단순회귀분석을 해 보도록 하자. 9월 아파트 매매가와 전세가를 결합한 데이터셋을 만들어보았다. 데이터가 필요하면 아래 링크에서 다운받으면 되겠다.


- 19년 9월 아파트 매매가&전세가 데이터 다운 받기

apt_tot.pkl
0.44MB

 

import pickle
import pandas as pd
 
df = pd.read_pickle("./apt_tot.pkl")

 

seaborn패키지를 이용해서 산점도를 그려보았다.

import seaborn as sns
 
sns.relplot(x="bo_price", y="price", data=df)

 

산점도

 

 

아웃라이어를 제거하기 위해, (평균) ± 3 * (표준편차)를 벗어나는 값들을 제거하였다. 다시 산점도를 그려보니 아웃라이어가 제거된 듯 하다.

 

def del_outlier(x):
    from_out = x.mean() - 3 * x.std()
    to_out = x.mean() + 3 * x.std()
    
    x = x[(x>from_out) & (x<to_out)]
    
    return x
 
df["price"] = del_outlier(df["price"])
df["bo_price"] = del_outlier(df["bo_price"])
 
sns.relplot(x="bo_price", y="price", data=df)

 

아웃라이어 제거 후 산점도

 

 

null값인 데이터가 있어 제거해 주었다.

 

df = df[(df["price"].isnull() == False) & (df["bo_price"].isnull() == False)]

 


실제 학습을 시키는 코드는 3줄이면 가능하다.

 

from sklearn.linear_model import LinearRegression
 
model = LinearRegression()
model.fit(df[["bo_price"]], df[["price"]])

 

 

r square와 모형 파라미터(베타0, 베타1)의 값도 출력이 가능하다. intercept_가 베타0, coef_가 베타1이다. 하지만, 통계학에서 다루는 다른 통계량들은 산출이 불가능했다. 이를 위해서는 statsmodel패키지를 이용해야 한다.

 

r_sq = model.score(df[["bo_price"]], df[["price"]])

print(r_sq)
print(model.intercept_)
print(model.coef_)

 


예측치를 구하고, 그래프를 그려보았다.

 

df["predict_price"] = model.predict(df[["bo_price"]])

sns.relplot(x= "bo_price", y = "price", data = df)
sns.lineplot(x= "bo_price", y = "predict_price", color="r", data = df)

 

 

회귀식

 

 

오늘은 이렇게 파이선 사이킷런(sklearn) 패키지를 이용해서 단순회귀분석을 하는 방법에 대해서 알아보았다. 회귀분석을 적용하는 방법은 어렵지 않지만, 여러가지 통계량들을 산출할 수 없다는 점이 조금 아쉬웠다. 통계학에서 다루는 수치들을 얻고 싶다면, statsmodel패키지를 이용하는 것이 좋을 듯 하다.

  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기