Writer: Harim Kang
해당 포스팅은 머신러닝에서 사용되는 Regression, 회귀를 공부하면서 직접 코드를 작성해본 실습 위주의 내용입니다. 선형 회귀의 경우에는 Numpy, Tensorflow2.0, sklearn 라이브러리를 사용하여 세가지 방법으로 구현해보았고, 다항 회귀는 Tensorflow2.0, sklearn 라이브러리를 사용하여 두가지 방법을 사용해보았습니다.
회귀는 기본적인 데이터 분석 방법입니다. 짧게 정의하자면, 가격이나 확률처럼 연속된 실숫값을 정확히 예측하는 것을 목적으로 가진 방법입니다.
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
x = 2 * np.random.rand(100, 1)
y = 4 + 3 * x + np.random.randn(100, 1)
plt.plot(x, y, 'bo')
plt.show()
x값은 0부터 2까지의 랜덤한 값을 선언하였고, y=3x+4 경향에 가깝도록 y=3x+4+randn 값을 선언하였습니다.
x_mean = sum(x) / len(x)
y_mean = sum(y) / len(y)
a = sum([(x_ - x_mean) * (y_ - y_mean) for x_, y_ in list(zip(x, y))])
a /= sum([(x_ - x_mean) ** 2 for x_ in x])
b = y_mean - a * x_mean
print('a:', a, 'b:', b)
x_pred = np.arange(min(x), max(x), 0.01)
y_pred = a * x_pred + b
plt.plot(x_pred, y_pred, 'r-')
plt.plot(x,y,'bo')
plt.show()
위에서 설명한 최소제곱법의 공식을 이용하여 코드를 작성하였습니다. x_pred는 x값들을 numpy배열로 바꾼것이고, y_pred는 최소제곱법을 사용하여 계산한 a와 b를 사용하여 계산한 값입니다.
a가 3에 가깝고, y절편인 b가 4에 가깝게 계산되었습니다.
import random
w = tf.Variable(random.random())
b = tf.Variable(random.random())
우선 가중치와 편향을 랜덤 값으로 초기화를 하였습니다.
def residue():
y_pred = w * x + b
re= tf.reduce_mean((y - y_pred) ** 2)
return re
잔차(residue)를 구하는 함수입니다. 예측 값과 실제 데이터 값의 차이를 제곱한 값의 합을 구하여 이것의 평균을 re로 return합니다.
optimizer = tf.optimizers.Adam(lr=0.07)
for i in range(1000):
optimizer.minimize(residue, var_list=[w,b])
if i % 100 == 99:
print(i, 'w:', w.numpy(), 'b:', b.numpy(), 'loss:', residue().numpy())
손실을 최소화하는 최적화 함수(optimizer)입니다. 해당 함수는 복잡한 미분 계산 및 가중치 업데이트를 자동으로 진행해주는 함수입니다. 해당 포스팅에서는 Adam 최적화 함수를 선정하였습니다. SGD와 함께 많이 쓰이는 함수로서, 좋은 성능을 보여줍니다. lr(learning rate)는 보통 0.1에서 0.0001 사이 값을 사용하는 데, 0.07을 사용하겠습니다.
optimizer.minimize(residue, var_list)는 var_list로 받은 변수 리스트를 residue함수가 최소가 되도록 1000번 학습하는 것입니다. 값의 변화를 확인하기 위해서, 100번에 한번씩 출력해보았습니다.
위의 결과를 토대로 그래프를 그려보면 아래와 같습니다.
x_pred = np.arange(min(x), max(x), 0.01)
y_pred = w * x_pred + b
plt.plot(x_pred, y_pred, 'r-')
plt.plot(x, y, 'bo')
plt.show()
numpy로 계산한 a,b와 텐서플로우로 계산한 w,b가 완전히 일치하진 않지만, 아주 유사함을 확인할 수 있습니다.
from sklearn.linear_model import LinearRegression
lin_reg = LinearRegression()
lin_reg.fit(x, y)
print(lin_reg.intercept_, lin_reg.coef_)
sklearn 라이브러리는 LinearRegression을 위한 자체적인 모델을 제공합니다. fit함수를 통해서 데이터를 입력시켜주면됩니다.
numpy 계산과 일치하게, tensorflow 계산과는 유사하게 결과가 나왔습니다. 이를 그래프로 나타내보면 아래와 같습니다.
x_pred = np.array([[0], [2]])
y_pred = lin_reg.predict(x_pred)
plt.plot(x, y, 'bo')
plt.plot(x_pred, y_pred, 'r-')
plt.show()
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
x = 2 * np.random.rand(100, 1)
y = 6 * (x ** 2) + 3 * x + 4 + np.random.randn(100, 1)
plt.plot(x, y, 'bo')
plt.show()
이번엔 이차함수인 y=6x^2+3*x+4 경향이 나타나도록 랜덤값들을 데이터로 만들어보았습니다.
import random
w = tf.Variable(random.random())
b = tf.Variable(random.random())
c = tf.Variable(random.random())
def residue():
y_pred = w * x**2 + b * x + c
loss = tf.reduce_mean((y - y_pred) ** 2)
return loss
optimizer = tf.optimizers.Adam(lr=0.07)
for i in range(1000):
optimizer.minimize(residue, var_list=[w,b,c])
if i % 100 == 99:
print(i, 'w:', w.numpy(), 'b:', b.numpy(), 'c:', c.numpy(), 'loss:', residue().numpy())
선형 회귀와 유사합니다. 달라진 점은 c라는 변수의 추가와 y식의 변화입니다.
학습이 좀 더 진행된다면 더 낮은 손실과 정확한 값들을 찾을 수 있습니다.
x_pred = np.arange(min(x), max(x), 0.01)
y_pred = w * x_pred * x_pred + b * x_pred + c
plt.plot(x_pred, y_pred, 'r-')
plt.plot(x, y, 'bo')
plt.show()
sklearn에서는 LinearRegression은 제공합니다. 해당 클래스와 다항 회귀를 위해서 기존 데이터를 다항 회귀에 적합한 데이터로 바꾸어주는 PolynomialFeatures 클래스를 이용하여 다항 회귀 모델을 추정할 수 있습니다.
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
poly_features = PolynomialFeatures(degree = 2, include_bias=True)
x_poly = poly_features.fit_transform(x)
lin_reg = LinearRegression()
lin_reg.fit(x_poly, y)
x_new = np.linspace(0, 2, 100).reshape(100,1)
x_new_poly = poly_features.transform(x_new)
y_predict = lin_reg.predict(x_new_poly)
plt.plot(x_new, y_predict, "r-")
plt.plot(x, y, "bo")
plt.show()
식의 차수를 늘리고, 변수를 늘리면, 3차 이상의 다항 함수들의 회귀도 가능합니다. 이것은 데이터의 형태를 파악한 후에, 적절한 차수를 선택하면 좋을 것 같습니다.
딥러닝 네트워크를 이용한 회귀(Regression)은 아래의 포스트에서 확인할 수 있습니다.
2020/02/12 - [IT/Deep Learning] - 딥러닝 (4) - 회귀(Regression) 네트워크 만들기
위의 실습 내용들은 아래의 깃허브 링크를 통해서 확인 하실 수 있습니다.
https://github.com/harimkang/tensorflow2_deeplearning/blob/master/regression_1.ipynb
최소제곱법: https://ko.wikipedia.org/wiki/최소제곱법
머신러닝 (6) - Fine Tuning Model (2) | 2020.02.12 |
---|---|
머신러닝 (5) - Cross Validation(교차검증) (9) | 2020.01.28 |
머신러닝 (4) - ML 모델 생성과 훈련, 예측, 평가 (2) | 2020.01.28 |
머신러닝 (3) - 데이터 전처리 (0) | 2020.01.22 |
머신러닝 (2) - ML프로젝트를 위한 데이터 선택 및 준비 (0) | 2020.01.21 |