이번 내용은 미적분을 기반으로 이루어져 있기 때문에, 이해가 잘 안된다면 다음을 참고하도록 하자.
https://taichi1.tistory.com/34
[Python] 경사하강법 구현
[In] # 경사하강법 구하기 %matplotlib inline import matplotlib.pyplot as plt import numpy as np def my_func(x): # 최솟값을 구하는 함수 return x**2 - 2*x def grad_func(x): # 도함수 return 2*x - 2 lr = 0.1 # 학습계수 x = 4.0 # 초깃
taichi1.tistory.com
이 외에도 정규분포 등등 이해가 안가는 부분은 전에 있는 페이지들을 참고하면 전부 이해 가능하다.
데이터 설정
[In]
# 데이터 설정
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
X = np.linspace(-np.pi, np.pi, 50) # 입력 데이터
T = np.sin(X) # 노이즈 추가 전 데이터
plt.plot(X, T)
T += 0.4 * np.random.randn(len(X)) # 정규분포를 따르는 노이즈(= 가우시안 노이즈) 추가
plt.scatter(X, T)
plt.show()
X /= np.pi # 수렴하기 쉽게 X를 -1에서 1 사이로 지정
[Out]
위의 데이터는 sin() 함수를 베이스로 하고 어느 정도 랜덤으로 흩어져 있다.
다항식 회귀의 구현
[In]
# 다항식 회귀의 구현
n = 0.01 # 학습계수(Learning Rate)
# ---- 다항식 ----
def polynomial(x, params):
poly = 0
for i in range(len(params)):
poly += params[i] * x ** i
return poly
# ---- 각 파라미터의 그래디언트 ----
def grad_params(X, T, params):
grad_ps = np.zeros(len(params))
for i in range(len(params)):
for j in range(len(X)):
grad_ps[i] += (polynomial(X[j], params) - T[j]) * X[j] ** i
return grad_ps
# ---- 학습 ----
# degree : 다항식 차수, epoch : 학습시키는 횟수
def fit(X, T, degree, epoch):
# ---- 파라미터의 초깃값을 설정 ----
params = np.random.randn(degree + 1)
for i in range(len(params)):
params[i] *= 2 ** i # 고차일 수록 파라미터 크게 설정
# ---- 파라미터의 갱신 ----
for i in range(epoch):
params -= n * grad_params(X, T, params)
return params
# ---- 결과 표시 ----
degrees = [1, 3, 6] # 다항식의 차수
for degree in degrees:
print("--- " + str(degree) + "차 다항식 ----")
params = fit(X, T, degree, 1000) # 천번 반복
Y = polynomial(X, params)
plt.scatter(X, T) # 정답 label 표시
plt.plot(X, Y, linestyle = 'dashed') # 학습 결과 표시
plt.show()
[Out]
--- 1차 다항식 ----
--- 3차 다항식 ----
--- 6차 다항식 ----
위 결과를 보게 되면, 1차 다항식일 때는 파라미터 수가 적어 Underfitting이 일어난 것을 알 수 있다. 반대로 6차 다항식일 때는 데이터 수에 비해 파라미터가 너무 복잡해 Overfitting이 일어난 것을 알 수 있다.
따라서 가장 실제 데이터의 경향과 비슷한 모델은 3차 다항식인 것을 알 수가 있다.