* 모든 코드는 제 깃허브 (cdjs1432/DeepLearningBasic: Deep Learning from scratch)에서 확인할 수 있습니다.

import numpy as np
import ComputeGrad
data = np.array([[1, 2, 3], [4, 6, 8]])  # y=2x+2 --> w=2, b=2
train_x = data[0]
train_y = data[1]

w = 1
b = 1

learning_rate = 0.1

epoch = 10000
w, b = ComputeGrad.GradientDescent(train_x, train_y, b, w, learning_rate, epoch)
print(w)
print(b)

 

 

 

 

일단 가장 먼저 할 것은, 간단한 Linear Regression 및 Gradient Descent의 구현입니다.

어차피 설명할 부분이 적으니, 코드로 바로 들어가도록 하겠습니다.

 

 

data = np.array([[1, 2, 3], [4, 6, 8]])  # y=2x+2 --> w=2, b=2
train_x = data[0]
train_y = data[1]

w = 1
b = 1

learning_rate = 0.1
epoch = 10000

우선 처음 시작은 이렇게 간단한 데이터로 하겠습니다.

이정도로 간단한 데이터라면 분명 Gradient Descent를 통해 w=2, b=2라는 정답을 찾아낼 수 있을 겁니다.

위 코드를 통해 train_x에는 [1, 2, 3]이, train_y에는 [4, 6, 8]이 들어가게 됩니다.

또, w값과 b값은 초기 값을 1로 설정하고, learning rate와 epoch까지 설정했습니다.

 

 

 

def GradientDescent(x, y, b, w, learning_rate=0.01, epoch=10000):
    if type(w) != np.ndarray:
        w = float(w)
        w = np.reshape(w, (1, 1))
    if x.size == x.shape[0]:
        x = x.reshape(x.shape[0], 1)
    if y.size == y.shape[0]:
        y = y.reshape(y.shape[0], 1)
    for epochs in range(epoch):
        pred = x.dot(w) + b  # y = w1x1 + w2x2 + ... + wmxm + b
        """
        err = 1/m * ((Wx1 + b - y1)^2 + (Wx2 + b - y2)^2 + ... + (Wxm + b - ym)^2)
        to minimize err --> differentiate w and b
        dw = 2/m * ((Wx1 + b - y1) * x1 + (Wx2 + b - y2) * x2 + ... + (Wxm + b - ym) * xm) 
        db = 2/m * ((Wx1 + b - y1) * 1 + (Wx2 + b - y2) * 1 + ... + (Wxm + b - ym))  
        """
        dw = ((pred - y) * x).mean(0)
        db = (pred - y).mean()
        dw = dw.reshape(dw.shape[0], 1)
        w -= dw * learning_rate
        b -= db * learning_rate


        if epochs % 1000 == 0:
            err = np.mean(np.square(pred - y))  # err = 1/m * (w1x1 + w2x2 + ... + wmxm + b - y)^2
            print("error : ", err)
    return w, b

다음은 Gradient Descent 부분 코드입니다.

 

    if type(w) != np.ndarray:
        w = float(w)
        w = np.reshape(w, (1, 1))
    if x.size == x.shape[0]:
        x = x.reshape(x.shape[0], 1)
    if y.size == y.shape[0]:
        y = y.reshape(y.shape[0], 1)

원래 Multi Variable Linear Regression을 먼저 만들 생각이었기에, w와 x의 값을 행렬곱에 적합한 형태로 바꾸어 주어야 합니다.

 

    for epochs in range(epoch):
        pred = x.dot(w) + b  # y = w1x1 + w2x2 + ... + wmxm + b
        """
        err = 1/m * ((Wx1 + b - y1)^2 + (Wx2 + b - y2)^2 + ... + (Wxm + b - ym)^2)
        to minimize err --> differentiate w and b
        dw = 2/m * ((Wx1 + b - y1) * x1 + (Wx2 + b - y2) * x2 + ... + (Wxm + b - ym) * xm) 
        db = 2/m * ((Wx1 + b - y1) * 1 + (Wx2 + b - y2) * 1 + ... + (Wxm + b - ym))  
        """
        dw = ((pred - y) * x).mean(0)
        db = (pred - y).mean()
        dw = dw.reshape(dw.shape[0], 1)
        w -= dw * learning_rate
        b -= db * learning_rate


        if epochs % 1000 == 0:
            err = np.mean(np.square(pred - y))  # err = 1/m * (w1x1 + w2x2 + ... + wmxm + b - y)^2
            print("error : ", err)
    return w, b

 

다음은 훈련 과정입니다.

 

우선, Linear Regression에서의 예측값을 pred, loss값을 err로 설정해 두었습니다.

 

계산 과정은 주석으로 달아놨지만, 조금 더 자세히 써보도록 하겠습니다.

 

 

우선 err값은 1/m * ((Wx1 + b - y1)^2 + (Wx2 + b - y2)^2 + ... + (Wxm + b - ym)^2)으로 설정해 두었습니다.

하지만 지금은 multi variable gradient descent가 아니므로, w와 x는 값을 각 한개씩을 가지게 됩니다.

따라서 err값은 $ err = 1/m * (wx + b - y)^2 $ 로 설정이 됩니다.

 

이제 이 err 값을 w와 b에 대하여 미분해 보면,

$$ \frac{\partial{err}}{{\partial{w}}} = 2/m * (wx + b - y) * x$$

$$ \frac{\partial{err}}{{\partial{b}}} = 2/m * (wx + b - y)$$

가 됩니다.

 

따라서, 이를 코드로 구현하면, 

        dw = ((pred - y) * x).mean(0)

        db = (pred - y).mean()

가 됩니다.

(2를 곱하지 않은 이유는, 딱히 중요한 이유가 있는게 아니라 코드에 2 곱하는 코드 있으면 더러워 보여서 그런겁니다.)

 

 

 

 

그리고, 아까 위에서 잠깐 언급했듯, 위 코드는 Multi Variable일때도 작동합니다.

import numpy as np
import ComputeGrad
train_x = np.random.uniform(-5, 5, (100, 10))
ans_w = np.random.uniform(-5, 5, (10, 1))
ans_b = 3
train_y = train_x.dot(ans_w) + ans_b
w = np.random.uniform(-5, 5, (10, 1))
b = np.random.uniform(-5, 5, (1, 1))

w, b = ComputeGrad.GradientDescent(train_x, train_y, 3, w)

print(ans_w)
print(w)

print(ans_b)
print(b)

 

위의 코드가 바로 그 Multi Variable일 경우의 코드입니다.

 

train_x와 ans_w, ans_b를 각각 만들어 주어 ans_w * train_x + b의 값으로 y를 만들어 주었고,

w와 b의 초기값을 랜덤으로 설정해 두며 Gradient Descent를 작동시켰습니다.

 

마지막의 결과값을 보면 ans_w와 w, ans_b와 b가 서로 비슷해져 있는 모습을 볼 수 있습니다.

 

 

+ Recent posts