본문 바로가기

머신러닝

[파이썬] Perceptron Gradient Descent

728x90

1. Cost function

 

신경망에서의 학습은 최적의 weight와 bias값을 찾아가는 과정입니다.

Cost function(비용함수)은 최적화된 가중치와 편향을 찾기 위한 기준이 되는 지표 함수입니다.

 

현재까지 진행된 학습의 상태를 지표로 나타내며, cost function을 가장 작은 값으로 만들어주는 것을 목표로 합니다.

 

Cost function의 값은 신경망이 추정한 y 값(prediction)과 현재 입력 데이터에 대응되는

실제 target 값 사이의 오차를 나타냅니다.

 

일반적으로 Mean Squared Error(평균 제곱 오차)와 Cross Entropy Error(교차 엔트로피 오차)를 

가장 많이 사용합니다.

 

Classfication에서는 Cross Entropy Error를 주로 사용하며 Regression은 MSE를 자주 사용합니다.

 

MSE는 다음과 같은 식을 가집니다.

$$E=\dfrac{1}{n}\sum _{k}\left( y_{k}-t_{k}\right) ^{2}$$

 

Entropy는 불확실성의 정도이며, entropy가 높다는 것은 정보가 많음을 의미합니다.

Cross Entropy는 서로 다른 사건의 확률 분포를 곱해 Entropy를 구합니다.

즉, 두 확률 분포의 차이를 확인할 수 있습니다. ( Cross Entropy가 작을 수록 두 분포가 유사 )

 

Cross Entropy는 다음과 같은 식을 가집니다.

$$E=-\dfrac{1}{n}\sum _{k}t_{k}\log y_{k}$$

 

2. Learning Rate

 

Gradient Descent는 현 위치의 기울기를 구하고, 

w = w- 기울기(slope) 식을 통해 위치를 이동시킵니다.

이 과정을 기울기가 0이 될 때까지 반복합니다.

 

기울기의 크기를 그대로 update의 정도에 반영할 경우, 일반적으로 가중치 update의 정도가 커집니다.

때문에 0을 찾지 못하고 그래프의 위쪽으로 이동하게 됩니다.

 

위 문제를 개선하기 위해서는 현 위치의 기울기를 구하고,

위치를 이동시킬 땐 w = w-(n * 기울기) 식을 사용해 기울기가 0이 될 때까지 반복합니다.

 

여기서 n은 Learning rate(학습률)입니다.

 

Gradient descent가 최적값에 도달 위해서는 learning rate가 

작지도 크지도 않은 적절한 값으로 설정되어야 합니다.

 

너무 클 경우 최적값 좌측의 하강 곡선, 우측의 상승 곡선 사이를 좌우로

반복적으로 이동하며, 최적값에 도달하지 못하고 발산할 수 있습니다.

 

너무 작을 경우, 최적값에 수렴하는 단계가 증가하므로 설정된 횟수 내에서

최적값에 도달하지 못할 수 있습니다.

 

최적의 Learning Rate값은 주로 0.01 ~ 0.1사이의 값입니다.

 

728x90

 

3. Perceptron Gradient Descent

 

Perceptron에서 Gradinet Descent는 cost function을 w로 미분하며

최적의 w를 찾는 과정입니다.

 

w = w - 기울기이며 이는 w - dCost/dw입니다.

Cost function을 미분하기 위해선 체인룰을 사용합니다.

체인룰을 사용하면 다음과 같은 식이 됩니다.

$$\dfrac{dJ}{dw}=\dfrac{dJ}{dy^{\left( k\right) }}\cdot \dfrac{dy^{\left( k\right) }}{da^{\left( k\right) }}.\dfrac{da^{\left( k\right) }}{dw_{i}}$$

 

위 식에서 J를 y로 미분한 식은 Cost function으로 미분하면 다음과 같은 식을 가집니다.

$$\dfrac{dJ}{dy^{\left( k\right) }}=\dfrac{1}{n}\sum _{k}\left( y^{\left( k\right) }-t^{\left( k\right) }\right)$$

 

위 식에서 y를 a로 미분한 식은 Activation function으로 미분하면 다음과 같은 식을 가집니다.

$$\dfrac{dy^{\left( k\right) }}{da^{\left( k\right) }}=h'\left( a^{\left( k\right) }\right)$$

 

위 식에서 a를 w로 미분한 식은 Weighted sum으로 미분하면 다음과 같은 식을 가집니다.

$$\dfrac{dx^{\left( k\right) }}{dw_{1}}=x_{1}^{\left( k\right) }$$

 

출처: COSS 빅데이터

 

이제 파이썬으로 Perceptron Gradient Descent를 구현하겠습니다.

 

import numpy as np
import matplotlib.pyplot as plt

# index 0 ~ n_class-1(49)인 데이터에 2를 더해 평균을 (2,2)로 이동시킴
# index n_class ~ n-1(99)인 데이터에 -2를 더해 평균을 (-2,2)로 이동시킴
# index 0~n_class까지는 0이고, n_class ~ n-1까지는 1인 t 생성

n = 100 # 샘플
n_class = 50 # class에 속한 데이터의 수

x = np.random.randn(n,2) # 평균이 0이고 분산과 표준편차가 1인 임의의 데이터로 구성된 입력 shape의 ndarry 랜덤 생성
x[n_class:,:] +=2 # 0부터 49까지 +2 
x[:n_class,:] -=2 # 50부터 99까지 -2
t = np.zeros((n,1)) # 0이 100개인 (100,1) ndarry생성
t[n_class:]=1 # index 50~99까지 1로 변경 (t는 target 값)

 

input node의 수가 2개이고 데이터 샘플의 수가 100개, class의 수가 2개,

각 class에 속한 데이터의 수가 50개인 perceptron을 구현합니다.

 

이때 class 0 은 평균이 2,2이고 표준편차가 1인 정규분포이며,

class 1은 평균이 -2,-2이고 표준편차가 1인 정규분포입니다.

 

다음 평균이 0,0이고 표준편차가 1인 n(100)개의 X를 생성합니다.

random.randn은 표준정규분포의 랜덤 값을 생성합니다.

 

만든 샘플을 시각화 해봅시다.

 

plt.scatter(x[:n_class,0],x[:n_class,1]) # label(t) = 0
plt.scatter(x[n_class:,0],x[n_class:,1]) # label (t) = 1
# 산점도의 가로축은 x1 세로축은 x2임

 

위 샘플을 perceptron을 통해 분류합니다.

먼저 activation, cost function을 함수로 생성합니다.

def sigmoid(a):
    return 1/(1+np.exp(-a))
    
def mse(y,t): 
    return 0.5 * np.mean((y-t)**2)  # prediction과 target 차를 제곱한 후, 결과의 평균값 반환

 

activation function은 sigmoid, cost function은 mse로 하겠습니다.

 

w = np.random.randn(2,1) # 랜덤한 (2,1) w 값 생성
b = np.random.randn(1,) # 랜덤한 스칼라 b 값 생성
print(w,'\n',w.shape,'\n',b)

 

랜덤한 2,1의 w와 랜덤한 스칼라 b 값을 생성합니다.

w가 2,1인 이유는 input node가 2개이고 output node가 1개이기 때문입니다.

 

다음 예측 함수를 생성합니다.

def prediction(x,w,b):
    a = x.dot(w)+b
    return sigmoid(a)

예측한 값 a가 sigmoid를 거칩니다.

 

다음 학습 전 예측 값을 시각화 하겠습니다.

plt.plot(t,linewidth=10,alpha=0.3) # target
plt.plot(prediction(x,w,b)) # prediction
plt.legend(['target','prediction'])

 

target 값과 prediction 값의 차이가 큰 모습을 확인할 수 있습니다.

 

# perceptron GD

eta = 0.1 
iter = 200 
cost_iter = np.zeros(iter) 

y = prediction(x,w,b)

for i in np.arange(iter):
    w = w - eta * np.mean((y-t)*y*(1-y)*x,axis=0).reshape(w.shape) # 최적의 w 찾는 식 (w1 = w1-학습률*aj/aw1)
    b = b - eta * np.mean((y-t)*y*(1-y),axis=0) # 최적의 b 찾는 식
    y = prediction(x,w,b) # 예측값
    
    cost_iter[i] = mse(y,t)
    
print(w)
print(b)

 

eta는 learning rate이며, iter는 학습 횟수, cost_iter는 예측값을 저장하는 변수입니다.

 

a = np.dot(x,w)+b
y = sigmoid(a)

mse(y,t)

최적의 w와 b를 학습을 통해 찾아 mse 값을 출력합니다.

잘 학습 된 모습을 볼 수 있습니다.

 

마지막으로 시각화를 합니다.

X = np.arange(100)
plt.plot(t,linewidth=10,alpha=0.3)
plt.plot(y)
plt.legend(['target','prediction'])

 

plt.plot(mse_iter)

 

비교적 정확하게 분류하고, 학습 횟수에 따라 mse가 낮아지는 모습을 확인할 수 있습니다.

728x90
반응형