학습이란 어떤 데이터로부터 규칙을 찾는것이라고 할 수 있다. 간단한 예시를 보자

x = [1, 2, 3, 4, 5]
y = [13, 23, 33, 43, 53]

x, y의 데이터가 있다. 사람이라면 x와 y사이의 규칙을 쉽게 찾을 수 있다. x에 10을 곱해서 3을 더하거나, x에 9를 곱해서 4를 더하거나 등등.. 하지만 기계는 규칙을 찾을 수 없다. 그럼 기계는 어떻게 x와 y의 규칙을 찾을까? 바로 학습을 시켜야 한다. 사람도 어려서부터 학습을 하듯이 기계도 학습이란것을 할 수 있다.

$y = wx + b$라는 식이 있다고 가정하자. 사람은 $w$에 10, $b$에 3이 들어간다는 것을 너무나도 잘 안다. 기계는 어떻게 $w$와 $b$의 값을 알아낼 수 있을까? $w$와 $b$를 딥러닝에서 가중치(weight)편향(bias) 이라고 부른다. w와 b는 처음 랜덤한 값으로 초기화된다.

지금부터는 다 예시이므로 ‘아~대충 이렇게 동작하는구나’ 라는 것만 알아두자

x = 2
y = 23
w = 0.5
b = 0.1

x, y에 2, 23로, w와 b에 각각 0.5, 0.1로 초기화 하였다. $y = wx + b$ 그럼 이 식에 $w$와 $b$를 넣고 계산해보자. $y = 0.5*2 + 0.1$ 이므로 1.1이 나온다. 하지만 $y$는 23이 나와야 정상이다. 그러므로 $w$, $b$의 값은 틀렸다고 할 수 있다. 자 그럼 틀리긴 틀렸는데, 이 값이 얼마나 틀렸는지 알아야 기계입장에서 $w$, $b$를 수정할 것 아닌가?
여기서 손실함수라는 것이 등장한다. 손실함수란 쉽게 말해서 정답과 계산한 값의 차이가 얼마나 있는지 알수있게 해주는 함수이다.
가장 흔한 MSE손실함수를 사용해보자. 예측한 값(계산한 값)과 실제 $y$값을 넣으면 된다.
계산한 값이 1.1이고 실제 $y$값은 23이다.

import tensorflow as tf
def MSE(y_pred, y):
  return tf.reduce_mean(tf.square(y_pred - y))

print(MSE(1.1, 23).numpy())
479.61

479.61 이라는 값이 나왔다. 자 이제 임의로 w, b를 수정해보자.
w를 5라고 하고, b를 1이라고 했을때, $y = wx + b$ 식을 계산해보자.
$y = 5*2 + 1$ 이므로 11이라는 값이 나온다. 이 값을 손실함수에 넣어서 손실값을 계산해보자.

print(MSE(11, 23).numpy())
144

144라는 값이 나왔다. 아까 나왔던 값보다 줄어든 것을 알 수 있다. 그렇다면 계산한 값과 실제 값이 동일할 때 손실값은 어떻게 나올까?

print(MSE(23, 23).numpy())
0

당연히 0이나온다. 우리는 여기서 한가지 깨달아야 한다. w, b는 손실함수가 0이 되도록 하는 것이 목표라는 것을. 그리고 손실함수가 0이 되도록 하는 w, b를 찾아가는 것이 바로 학습이다.
자 어찌어찌 학습을 시켜서 $w$가 10, $b$가 3이라는 값을 얻었다고 해보자.
그렇다면 이 w와 b를 어디에 사용할 수 있을까?

x = [1, 2, 3, 4, 5]
y = [13, 23, 33, 43, 53]

이러한 값이 있고 $y = wx + b$ 식이 있다고 가정하자. 그리고 $x$에 7이라는 값이 추가로 들어왔을 때, $y$값은 어떻게 구할까? 당연히 기계도 이제 학습을 통해서 $w$, $b$의 값을 알았으니, 식에 넣에서 73이라는 값을 내보낼 것이다.

이것이 딥러닝에서의 학습과 예측이다. 딥러닝에서 모든 학습은 위와 같이 이루어진다. 단지, 위에서의 설명은 단순한 예시일 뿐이다.
실제 데이터를 다루게 된다면 적어도 수만에서 수백만개의 숫자로 이루어져 있고, 식도 단순하지가 않다.
그렇기 때문에 기계한테 x와 y의 규칙, 즉 식에 맞는 w, b를 찾도록 학습을 시키는 것이다.

위에서는 임의로 가중치의 값을 변화시켰는데, 실제 학습에서는 ‘오차역전파’ 라는 방식을 통해 손실값과 가중치의 미분을 통해서 가중치의 값을 서서히 변화시킨다.

아래 코드는 예제로 사용한 데이터로 $w$와 $b$를 구하는 방법을 나타낸 것이다.

import numpy as np

# 학습될 가중치와 편향을 선언
w = tf.Variable(4.0)
b = tf.Variable(1.0)

# 단순선형회귀의 계산 함수
def hypothesis(x):
  return w*x + b

# MSE loss 함수
def mse_loss(y_pred, y):
  return tf.reduce_mean(tf.square(y_pred - y))

# 데이터 선언
x = np.array([1, 2, 3, 4, 5])
y = np.array([13, 23, 33, 43, 53])
print(f"x: {x}")
print(f"y: {y}")

# SGD옵티마이저 사용. 학습률은 0.01
optimizer = tf.optimizers.SGD(learning_rate=0.01)

# 500번 반복학습
for i in range(501):
    with tf.GradientTape() as tape:
        # 현재 w, b에 기반한 입력 x에 대한 예측값
        y_pred = hypothesis(x)

        # loss 계산
        loss = mse_loss(y_pred, y)

    # 손실 함수에 대한 w, b의 미분값 계산
    gradients = tape.gradient(loss, [w, b])

    # w, b 업데이트
    optimizer.apply_gradients(zip(gradients, [w, b]))

    if i % 50 == 0:
        print("epoch : {:3} | w의 값 : {:5.4f} | b의 값 : {:5.4} | loss : {:5.6f}".format(i, w.numpy(), b.numpy(), loss))
x: [1 2 3 4 5]
y: [13 23 33 43 53]
epoch :   0 | w의 값 : 5.4400 | b의 값 :   1.4 | loss : 472.000000
epoch :  50 | w의 값 : 10.0732 | b의 값 : 2.736 | loss : 0.012791
epoch : 100 | w의 값 : 10.0618 | b의 값 : 2.777 | loss : 0.009116
epoch : 150 | w의 값 : 10.0522 | b의 값 : 2.812 | loss : 0.006497
epoch : 200 | w의 값 : 10.0440 | b의 값 : 2.841 | loss : 0.004631
epoch : 250 | w의 값 : 10.0372 | b의 값 : 2.866 | loss : 0.003300
epoch : 300 | w의 값 : 10.0314 | b의 값 : 2.887 | loss : 0.002352
epoch : 350 | w의 값 : 10.0265 | b의 값 : 2.904 | loss : 0.001676
epoch : 400 | w의 값 : 10.0224 | b의 값 : 2.919 | loss : 0.001195
epoch : 450 | w의 값 : 10.0189 | b의 값 : 2.932 | loss : 0.000852
epoch : 500 | w의 값 : 10.0159 | b의 값 : 2.942 | loss : 0.000607

카테고리:

업데이트:

댓글남기기