Linear Regression?

세상에 있는 많은 현상, 데이터들은 Linear 한 경우가 많다.

(예를 들어, 공부하는 시간이 늘어날수록 점수가 높아진다던가 집의 크기가 클수록 가격이 올라가는 등)

수식으로 표현하면 H(x) = Wx + b ( y = ax + b )와 같은 형태가 될 것이며 이 것을 가설(Hypothesis) 또는 모델(Model)이라 부른다. 

이런 데이터들을 가장 잘 대변하는 직선 방정식을 찾는 것을 Linear Regression이라 한다.

한마디로, 어떤 직선이 우리의 데이터에 가장 근접할 것인가?라는 생각을 가지고 W와 b 값을 결정해 주는 것을 의미한다.

 

Cost function

Cost( Loss, Error )란, 우리가 생각하는 가설( H(x) = Wx +b )과 실제 데이터와의 차이라고 할 수 있다.

 

위와 같이 단순히 차이라고 한다면 가설에서 실제 데이터인 y를 빼는 H(x) - y라고 생각할 수 있지만 수식의 결괏값이 양수가 나올 수도 있고 음수가 나올 수도 있기 때문에 차이 값의 합을 구하는 것은 의미가 없어질 수 있다.

따라서 우리는 ( H(x) - y ) 값을 제곱해서 그것을 평균을 낸 값을 Cost로 사용하고 그 수식을 Cost function이라 한다.

우리가 원하는 직선은 실제 데이터와 가장 근접해야 하기 때문에 이런 Cost 값이 가장 적은 것을 목표로 W 값과 b 값을 구해주어야 한다. 이렇게 W, b 값을 정해 주는 것을 "학습한다."라고 말할 수 있다.

 

 

그렇다면 TensorFlow를 이용하여 이런 Linear Regression을 구현하고 이해해보자.

import tensorflow as tf

# input data, output data
# x값과 y값이 같으므로 H(x) = x 모양의 가설이 되야하고 그렇다면 W=1, b=0가 되어야한다.
# 결과값에서 W와 b를 출력해보고 실제로 1과 0이 되는지를 확인해 보자.
x_data = [1, 2, 3, 4, 5]
y_data = [1, 2, 3, 4, 5]

# Variable() 함수를 이용하여 W와 b 선언, 초기 값은 임의로 주어줌
W = tf.Variable(2.9)
b = tf.Variable(0.5)

learning_rate = 0.01


for i in range(100+1):

    # 경사 하강 알고리즘 구현 ( 경사가 하강하면서 cost가 minimize 되는 W와 b 값을 찾는다. )
    # with 함수를 이용하여 구문 내의 변화를 tape에 기록
    with tf.GradientTape() as tape:
    
        # 가설 설정 ( H(x) = WX +b )
        hypothesis = W * x_data + b
        
        # tf.square()은 제곱을 수행해준다.
        # tf.reduce_mean()은 평균을 내주는데 이때, reduce는 "차원을 내려준다"라는 의미를 내포하고 있다.
        # 실제로 1차원의 list 내의 값들의 평균을 내서 0차원의 Scalar 값으로 반환시켜준다.
        cost = tf.reduce_mean(tf.square(hypothesis - y_data))
        
    # cost에 대한 W 값과 b 값을 미분하여 각각 반환
    W_grad, b_grad = tape.gradient(cost, [W, b])
    
    # W와 b 값 업데이트
    # learning_rate은 gradient 값을 얼만큼 반영할 것인지 결정
    # assign_sub() 함수는 A -= B 의 형태
    W.assign_sub(learning_rate * W_grad)
    b.assign_sub(learning_rate * b_grad)
   
   # 결과 출력
    if i % 10 ==0:
        print("{:5}|{:10.4f}|{:10.4}|{:10.6f}".format(i, W.numpy(), b.numpy(), cost))

해당 코드에서 cost 값이 Minimize 되어야 하니 (hypothesis - y_data) 값은 실질적으로 0에 가까워져야 하고

W는 1, b는 0에 가까워져야 하는 것을 직관적으로 생각할 수 있다.

cost -> hypothesis -> W, b와 같은 순서로 해당하는 값을 구하는 것을 알 수 있다.

 

결과

 

결과 값을 보면 우리가 예상한 대로 W 값은 1에 수렴하고 b 값은 0에 수렴하는 것을 볼 수 있다.

또한, cost 값이 처음에는 큰 값을 가지지만 급격하게 0에 수렴하며 실제 데이터와 우리의 모델의 차이가 줄어드는 것을 확인할 수 있다.

그렇다면 이 W와 b 값을 가진 우리의 hypothesis 즉, 우리의 model이 어떻게 변화하였는지 그림으로 확인해보자.

 

처음에는 우리의 가설인 직선과 실제 데이터 간의 차이가 큰 것을 확인할 수 있는데 학습 과정이 끝난 후에는 우리의 모델이 실제 데이터와 밀접하게 변경되었음을 확일할 수 있다.

 

 

아래의 코드는 tensorflow 1.5 버전에서 진행한 코드이다.

import tensorflow as tf

# Variable는 tensorflow가 자체적으로 변경시키는 값(trainable하다..)
# w와 b에 [1] 형태의 random 값을 주어줌
W = tf.Variable(tf.random_normal([1]), name='weight')
b = tf.Variable(tf.random_normal([1]), name='bias')
X = tf.placeholder(tf.float32, shape=[None])
Y = tf.placeholder(tf.float32, shape=[None])

hypothesis = X * W + b

# cost/loss function
cost = tf.reduce_mean(tf.square(hypothesis - Y))

# Minimize
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
train = optimizer.minimize(cost)

#Session
sess = tf.Session()

# variable 초기화
sess.run(tf.global_variables_initializer())

# Fit the Line
for step in range(2001):
    cost_val, W_val, b_val, _ = sess.run([cost, W, b, train],
        feed_dict={X: [1, 2, 3, 4, 5],
                   Y: [2.1, 3.1, 4.1, 5.1, 6.1]})
    if step % 20 == 0:
        print(step, cost_val, W_val, b_val)

# Testing our model
print(sess.run(hypothesis, feed_dict={X: [1, 5]}))

결과

 

결과 값을 보면 우리가 하고자 했던 training이 성공적으로 이루어져서 모델을 만들었다고 할 수 있다.

X = 1 -> Y = 2.1

X = 5 -> Y = 6.1

'Machine Learning & Deep Learning' 카테고리의 다른 글

6. Loading Data from File  (0) 2020.04.18
5. Multi-variable linear regression  (0) 2020.04.17
4. Hypothesis and Cost  (0) 2020.04.16
2. Tensorflow 사용 환경 구축  (0) 2020.04.15
1. Machine Learning  (0) 2020.04.14

+ Recent posts