Posts 선형회귀(Linear Regression)와 Cost Function
Post
Cancel

선형회귀(Linear Regression)와 Cost Function

1. 기본 개념 잡기

1.1 주택 가격 예측

  • 주택의 넓이과 가격이라는 데이터가 있고, 주택가격을 예측한다고 했을때, 머신러닝 모델은 어떻게 만들수 있을까?
  • 일단 학습데이터 각각에 정답(주택가격)이 있으므로 지도학습이고, 주택가격이 연속된 값이고, 이를 예측하는 것이므로 회귀 문제이다

1.2 선형회귀(Linear Regression)

  • 입력변수(특징) x가 1개인 경우 선형회귀문제는 주어진 학습데이터와 가장 잘 맞는 가설(Hypothesis) 함수 h를 찾는 문제가 됨

1.3 모델을 구성하는 파라미터를 찾는 방법

  • 주어진 학습 데이터 x에 대해 정답 y와 예측값 y^의 차이가 최소가 되게 파라미터의 값을 결정 한다.

1.4 직선상에 있지 않은 3개의 점을 직선으로 표현하기

  • 3개의 점들과 가장 가깝게 선을 그으면 됨
  • 점들과 선의 거리가 제일 가까운위치 (오차가 제일 적은 위치)라는 뜻

2. Cost Function


2.1 Cost Function이란

  • 생성한 모델과 실제 데이터간의 차이
  • Cost Function이 작아야, 모델의 성능은 높다
  • 위의 예제에서 해당 선이 모델이라고 하였을때 각 3점과의 에러가 가장 작은 선을 찾아야함

2.2 Cost Function 계산

1
2
3
import numpy as np

np.poly1d([2, -1]) ** 2 + np.poly1d([3, -5]) ** 2 + np.poly1d([5, -6]) ** 2
1
poly1d([ 38, -94,  62]) <br>

2.3 최소값 구하기

1
2
3
import scipy as sp
import sympy as sym
th = sym.Symbol('th')

1
2
diff_th = sym.diff(38 * th ** 2 - 94 * th + 62 ,th)
diff_th

1
sym.solve(diff_th)
1
[47/38]


3. Cost Function Graph


3.1 Cost Function - 데이터와 모델이 완전히 일치하면 th = 1

1
2
3
4
plt.figure(figsize=(12, 8))
plt.scatter([1, 2, 3], [1, 2, 3], marker = 'o', s = 100, c = 'r')
plt.plot(np.linspace(0, 3), np.linspace(0, 3))
plt.show()


3.2 Cost Function - 데이터와 모델이 반만 일치하면 th = 0.5

1
2
3
4
5
6
plt.figure(figsize=(12, 8))
plt.scatter([1, 2, 3], [1, 2, 3], marker = 'o', s = 100, c = 'r')
plt.plot(np.linspace(0, 3), np.linspace(0, 1.5))
plt.xlim(0,4)
plt.ylim(0,4)
plt.show()


3.3 Cost Function - 데이터와 모델이 완전히 안맞을때 th = 0

1
2
3
4
5
6
plt.figure(figsize=(12, 8))
plt.scatter([1, 2, 3], [1, 2, 3], marker = 'o', s = 100, c = 'r')
plt.plot(np.linspace(0, 3), np.linspace(0, 0), color='r')
plt.xlim(0, 4)
plt.ylim(-0.1, 4)
plt.show()


3.4 cost function에 따른 th의 모양

1
2
3
4
plt.figure(figsize=(12, 8))
plt.plot([0, 0.5, 1, 1.5, 2], [3, 1, 0, 1, 3], 'o')
plt.plot([0, 0.5, 1, 1.5, 2], [3, 1, 0, 1, 3])
plt.show()


3.5 실제 데이터는 다르다

  • 하지만 실제 데이터는 1차원 데이터가 아닌, 특성들이 많은 다차원 데이터임
  • 결국 실제 데이터는 너무 복잡해서 손으로 풀수가 없습니다.

4. 경사하강법(Gradient Descent)


4.1 경사하강법이란?

  • 손쉽게 최소값 찾는 방법
  • 랜덤하게 임의의 점을 선택해서 미분(or 편미분)값을 계산해서 업데이트 하여 오른쪽이나, 왼쪽으로 하강하여, 최소점을 찾는 방법

4.1 학습률(Learning Rate)

  • 얼마만큼 theta를 갱신할것인지를 설정하는 값
  • 학습률이 작다면
    • 최소값을 찾으러가는 간격이 작게됨
    • 여러번 갱신해야 함
    • 대신 최소값에 잘 도달할수 있음
  • 학습률이 높다면
    • 최소값을 찾으러가는 간격이 크게됨
    • 만약 최소값을 찾았다면 갱신횟수는 상대적으로 적을수 있으나, 수렴하지 않고 진동할 수도 있음

5. 다변수 데이터에 대한 회귀 (Multivariate Linear Regression)


5.1 여러개의 특성

  • Multivariate Linear Regression 문제로 일반화 할수 있음
  • 회귀문제에서 대부분은 다변수 데이터 일것임

6. 실습) 보스턴 집값으로 예측해 보는 다변수 회귀 문제


6.1 데이터 불러오기

1
2
3
from sklearn.datasets import load_boston

boston = load_boston()


6.2 컬럼 확인 (사실상 왜있는지도 모르는겠는 컬럼이 있기는함..)

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

6.3 Dataframe 만들기

1
2
3
4
5
6
7
import pandas as pd

[i for i in boston.feature_names]
boston_pd = pd.DataFrame(boston.data, columns=boston.feature_names)
boston_pd['PRICE'] = boston.target

boston_pd.head()
CRIMZNINDUSCHASNOXRMAGEDISRADTAXPTRATIOBLSTATPRICE
00.0063218.02.310.00.5386.57565.24.09001.0296.015.3396.904.9824.0
10.027310.07.070.00.4696.42178.94.96712.0242.017.8396.909.1421.6
20.027290.07.070.00.4697.18561.14.96712.0242.017.8392.834.0334.7
30.032370.02.180.00.4586.99845.86.06223.0222.018.7394.632.9433.4
40.069050.02.180.00.4587.14754.26.06223.0222.018.7396.905.3336.2


6.4 Price에 대한 Histogram

1
2
3
4
5
6
7
8
# import plotly.express as px

# fig = px.histogram(boston_pd, x= 'PRICE')
# fig.show()

plt.figure(figsize=(12, 8))
plt.hist(data = boston_pd, x = 'PRICE')
plt.show()


6.5 각 특성별 상관계수 확인

1
2
3
4
5
6
7
import matplotlib.pyplot as plt
import seaborn as sns

corr_mat = boston_pd.corr().round(1)
sns.set(rc={'figure.figsize': (10, 8)})
sns.heatmap(data=corr_mat, annot = True, cmap = 'bwr')
plt.show()

  • Price의 rm과 lstat가 상관관계가 높음
  • 방의 갯수가 많으면 집이 상대적으로 넓을것이고, 그렇다면 집값이 비싸고, 하위 계층의 비율이 높으면 잘 못사는 지역으로 집값이 싼것으로 생각이 듬


6.6 RM과 LSTAT의 PRICE와이 관계를 더 자세히

1
2
3
4
5
6
sns.set_style('darkgrid')
sns.set(rc={'figure.figsize': (12, 6)})
fig, ax = plt.subplots(ncols=2)
sns.regplot(x = 'RM', y = 'PRICE', data = boston_pd, ax = ax[0])
sns.regplot(x = 'LSTAT', y = 'PRICE', data = boston_pd, ax = ax[1])
plt.show()

  • 저소득층 인구가 낮을수록, 방의 갯수가 많을 수록 집값이 높아지는것 처럼 보임

6.7 데이터 분리

1
2
3
4
5
6
7
from sklearn.model_selection import train_test_split

X = boston_pd.drop('PRICE', axis=1)
y = boston_pd['PRICE']

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=13)


6.8 LinearRegression

1
2
3
4
from sklearn.linear_model import LinearRegression

reg = LinearRegression()
reg.fit(X_train, y_train)
1
LinearRegression() - 회귀 문제로 풀기로했으니, LinearRegression으로 학습 <br>

6.9 모델 평가 RMSE로 해보기

1
2
3
4
5
6
7
8
9
10
import numpy as np
from sklearn.metrics import mean_squared_error

pred_tr = reg.predict(X_train)
pred_test = reg.predict(X_test)
rmse_tr = (np.sqrt(mean_squared_error(y_train, pred_tr)))
rmse_test = (np.sqrt(mean_squared_error(y_test, pred_test)))

print('RMSE of Train Data :', rmse_tr)
print('RMSE of Test Data :', rmse_test)
1
2
RMSE of Train Data : 4.642806069019824
RMSE of Test Data : 4.931352584146711

6.10 성능확인

1
2
3
4
5
6
plt.scatter(y_test, pred_test)
plt.xlabel('Actual House Price ($1000)')
plt.ylabel('Predicted Prices')
plt.title('Real vs Predicted')
plt.plot([0, 48], [0, 48], 'r')
plt.show()


6.11 LSTAT를 제외하고 다시 해보기

1
2
3
4
5
6
7
8
9
10
from sklearn.model_selection import train_test_split

X = boston_pd.drop(['PRICE', 'LSTAT'], axis=1)
y = boston_pd['PRICE']

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=13)

reg = LinearRegression()
reg.fit(X_train, y_train)
1
LinearRegression() <br>

6.12 성능은 나빠짐

1
2
3
4
5
6
7
8
9
10
import numpy as np
from sklearn.metrics import mean_squared_error

pred_tr = reg.predict(X_train)
pred_test = reg.predict(X_test)
rmse_tr = (np.sqrt(mean_squared_error(y_train, pred_tr)))
rmse_test = (np.sqrt(mean_squared_error(y_test, pred_test)))

print('RMSE of Train Data :', rmse_tr)
print('RMSE of Test Data :', rmse_test)
1
2
RMSE of Train Data : 5.165137874244864
RMSE of Test Data : 5.295595032597162
  • 당연히 상관관계가 높은 특성을 뺐으니..
  • 하지만 RMSE가 5.1, 5.2가 나오는게 얼마나 좋은것인지 판단이 안섬

6.13 그래프로 보기

1
2
3
4
5
6
plt.scatter(y_test, pred_test)
plt.xlabel('Actual House Price ($1000)')
plt.ylabel('Predicted Prices')
plt.title('Real vs Predicted')
plt.plot([0, 48], [0, 48], 'r')
plt.show()

  • 어떤 특성을 넣고 뺴고 하는 고민은 항상 있을듯 싶다.
This post is licensed under CC BY 4.0 by the author.