본문 바로가기
Machine Learning/Basic Machine Learning

[ML/DL] 선형회귀(Linear Regression)를 TensorFlow로 구현하기

by Sin_ 2021. 10. 18.
728x90

안녕하세요 뚜디 입니다:)

Machine Learning에 대해서 간단하게 공부하고 있어

공부한 내용을 간단하게 공유하는 포스팅입니다.


선형회귀를 TensorFlow로 구현하기


이번 포스팅에서는 저번 포스팅(선형회귀(Linear Regression)의 개념)에 연장선입니다.
1. 이론적인 정의에서 TensorFlow 코드로 가상함수, 비용함수에 대해 정의해보도록 하겠습니다.
2. Cost가 최소화되도록 하는 w와 b를 찾는 minimization알고리즘에대해 알아보도록 하겠습니다.

먼저 그 전에 선형회귀의 개념을 보시지않으셨다면 아래 링크를 참고해주세요

[ML/DL] 선형회귀(Linear Regression)의 개념 (tistory.com)

 

[ML/DL] 선형회귀(Linear Regression)의 개념

안녕하세요 뚜디 입니다:) Machine Learning에 대해서 간단하게 공부하고 있어 공부한 내용을 간단하게 공유하는 포스팅입니다. Machine Learning에서의 Linear Regression의 개념 1. 학습 전 요약(Summary) * 회..

sindh718.tistory.com

 

1. Build hypothesis and cost

hypothesis = w * x_data + b

cost = tf.reduce_mean(tf.square(hypothesis - y_data))
import tensorflow as tf

x_data = [1,2,3,4,5]
y_data = [1,2,3,4,5]

w = tf.Variable(2.9)
b = tf.Variable(0.5)

hypothesis = w * x_data + b
cost = tf.reduce_mean(tf.square(hypothesis - y_data))
hypothesis(가상함수), cost(비용함수) 에대해 소스코드로 정의할수 있습니다.

cost = tf.reduce_mean(tf.square(hypothesis - y_data)) 에 대해 자세히 알아보도록 하겠습니다.

● tf.reduce_mean()

reduce = '줄어들다' 라는 뜻이 있듯이 reduce_mean 즉, 차원(랭크)이 줄어들면서 mean을 구한다.

v = [1., 2., 3., 4.,]
tf.reduce_mean(v) #2.5
예제를 보시면 v는 1차원 입니다. 1차워 v를 reduce_mean을하게 되면 결과는 2.5
즉 1차원에서 0차원으로 줄어들었습니다.

● tf.square()

square는 입력 받은 값을 제곱합니다.

tf.square(3) 은 3의 제곱이 되며 결과는 9

 

2. Gradient descent(경사 하강)
<정의>
1. Gradient descent의 Gradient는 경사, 기울기 descent는 아래로 하강 이라는 말 따라서, 경사 하강 알고리즘 혹은 기울기 하강 알고리즘으로 불립니다.
2. Gradient descent는 cost를 minimize하게 하는 w와 b를 찾는 알고리즘입니다.

 

#Learning_rate initialize
learning_rate = 0.01

#Gradient descent
with tf.GradientTape() as tape:
    hypothesis = w * x_data + b
    cost = tf.reduce_mean(tf.square(hypothesis - y_data))

w_grad, b_grad = tape.gradient(cost, [w, b])

w.assign_sub(learning_rate * w_grad)
b.assign_sub(learning_rate * b_grad)
Gradient descent 알고리즘은 일반적으로 tensorflow에서 GradientTape()을 가지고 구현합니다.
GradientTape()은 보통 with 구문과 함께쓰이며, with 구문 안에 있는 블록 변수들의 변화를 테이프에 기록합니다.
with tf.GradientTape() as tape:
   hypothesis = w * x_data + b
   cost = tf.reduce_mean(tf.square(hypothesis - y_data))
현재 블록에는 변수가 w와 b가 있습니다. 이 변수를 tape에 기록하고, 이후에 tape.gradient 메서드를 호출해서 경사도 값 즉, 미분 값을 구합니다.
w_grad, b_grad = tape.gradient(cost, [w, b])
gradient 함수는 cost에 대해서 변수들[w, b]에 대한 개별 미분 값(기울기)을 구해서 튜플로 반환합니다.
w에 대한 gradient(기울기)는 w_grad, b에 대한 gradient(기울기)는 b_grad로 가각 assign됩니다.
그리고 나서 w와 b값을 업데이트 해줍니다.
w.assign_sub(learning_rate * w_grad)
b.assign_sub(learning_rate * b_grad)
이때 learning_rate는 기울기 값을 구했을때, 기울기를 얼마만큼 반영할것인지를 하는 역할
(보통 0.001, 0.0001로 매우 작은값을 사용)
해당 소스가 한번 실행될때, w와 b가 한번 업데이트 된 것입니다.
하지만, 이작업은 한번에 끝나지 않고, 이것을 여러 차례 걸쳐 w와 b를 업데이트 하게됩니다.

● A.assign_sub(B)

A = A - B ( A -= B )

< Full Code >

import tensorflow as tf

# Data
x_data = [1,2,3,4,5]
y_data = [1,2,3,4,5]
# w, b initialize
w = tf.Variable(2.9)
b = tf.Variable(0.5)

learning_rate = 0.01

for i in range(101): # w, b update
	# Gradient descent
    with tf.GradientTape() as tape:
        hypothesis = w * x_data + b
        cost = tf.reduce_mean(tf.square(hypothesis - y_data))

    w_grad, b_grad = tape.gradient(cost, [w, b])

    w.assign_sub(learning_rate * w_grad)
    b.assign_sub(learning_rate * b_grad)
    if i % 10 == 0:
         print("{:5}|{:10.4f}|{:10.4f}|{:10.6f}".format(i, w.numpy(), b.numpy(), cost))

Gradient descent 알고리즘을 통해 w와 b값을 업데이트가 핵심이며, w와 b값이 어떻게 변화하는지 한번 확인해보세요.

# w, b initialize 에서 초기값 w = 2.9, b = 0.5
w는 2.9 -> 1로 수렴, b는 0.5 -> 0로 수렴 하는것을 보실수 있습니다.
x_data = [1, 2, 3, 4, 5]
y_data = [1, 2, 3, 4, 5]
w = 1, b = 0 이 되는것이 가장 인상적인 값이였는데, 거의 수렴했으며,
cost의 값도 보면(cost값은 작으면 작을수록 좋습니다.)
100번 이상일경우 거의 0에 가까워진것을 보실수 있습니다.
이 결과는, 모델이 실제 데이터와 거의 유사하다고 보실수 있습니다.
(즉, 모델이 실제 값을 예측하는데 굉장히 잘 맞게 되었다.)

초기 w = 2.9, b = 0.5 에서 100 번을 반복하여 학습을 했을때, w = 1, b = 0에 수렴했으며, 100번을 반복한 모델(주황색 선)은 실제 값과 유사한 모양이 되었습니다.
학습을 시작하기 전 주황색 선은 임의의 랜덤한 곳에 자리를 잡지만 학습이 이루어질수록 점점 실제 데이터 위치에 점점 가까워지며, 오차가 없어지게됩니다. -> cost = 0 : 실제데이터 = 모델

 

728x90