comnic's Dev&Life

[머신러닝 - TensorFlow]예제 1 - Simple linear regression 본문

머신러닝(ML)

[머신러닝 - TensorFlow]예제 1 - Simple linear regression

comnic 2019. 2. 23. 09:51
반응형

머신러닝(machine learning)을 배우면서 소스 위주로 정리하고 공유합니다.



간단하게 파이썬 소스 위주로 설명 및 정리만 하고자 합니다.

즉, 이론은 따로 정리하고, 바로 소스를 보면서 이해 할 수 있도록 정리하고자 합니다.


- tessorflow설치

$ pip3 install tensorflow





1. Simple Linear Regression


먼저 가장 심플한 선형회귀(linear regression)를 코드로 보면서 텐서플로가 어떻게 작성되는지 보자.


파이썬과 tensorflow는 설치가 되었다고 가정한다.



아래는 가장 간단한 방정식 [y = ax + b]에 대한 구현이다.

이 식은 x의 값에 따른 y의 값을 구하는 것이다.

a가 1이고 b가 0이라면,

(x, y)는 (1,1), (2,2), (3,3) ... 과 같은 값을 가질 것입니다.


이때,

x의 데이터는 [1,2,3]이 될 것이고,

y의 데이터는 [1,2,3]이 될 것입니다.


그렇다면 이런 식과 데이터로 무엇을 하느냐!?

바로 주어진 x에 대한 답(y)을 보고 학습하여,

주어지지 않은 x에 대해 예측을 해 보라는 것입니다.

다시 말해, 위 데이터로 학습한 후 x=4일때 y의 값을 구해보라고 할 수 있습니다.


이렇게 기계를 학습시키기 위해서는 아래와 같은 것들이 필요합니다.

hypothosis(가설) : 위 방정식

cost(비용) : 가장 중요한 부분이 cost인 듯 합니다. 

기계가 학습을 하는 방법이 

주어진 가설의 식을 완성(?)하는 것으로 볼 때,

이를 위해 필요한 값을 추정하고 맞는지 확인 하는 과정을 무수히 되풀이하면서 조금씩 맞춰 나갑니다.

이 때 어느정도 맞는지를 판단 할 수 있는 기준이 cost라고 생각하시면 됩니다. 

cost가 점점 작아지는 방향으로 학습을 하다가 0에 가까우면 정확도가 높은 결과가 나오는 것입니다.

이 cost는 우리가 미리 제공한 해답인 y의 값과 자신이 예측한 값의 차입니다.

실제 주어진 x데이터들에 대해 모두 차를 구하고 제곱 후 평균을 구하면서 좋은 결과가 나오도록 되풀이 하면 됩니다.



자 그럼, 본격적으로 코드를 작성해 보도록 하겠습니다.


1. 먼저 tensorflow를 import 합니다.

import tensorflow as tf


2. 학습할 데이터를 제공합니다.

x_train = [1,2,3]
y_train = [1,2,3] #[2,3,4], [3,4,5]


먼저 가장 간단한 데이터로 테스트 해 봅니다. 우리의 hypothesis가 [y = xa + b]라고 할 때 위에서 설명했듯이 x에 1을 넣었을 때 y가 1이되는 경우, 2을 넣었을 때 2가되는 경우 ... 이때 우리는 쉽게 a와 b를 예측 할 수 있습니다. 

바로 a=1, b=0 이겠죠?


그럼 주석처리 해 둔 y의 값을 [2,3,4]로 바꾸면 어떻게 될까요?

a=1, b=1 이겠죠?


이제부터 a를 w(weight)로 바꾸어 설명하도록 하겠습니다. 그리고 b는 bias입니다.


이렇게 실제로 학습이 이뤄지는지 보기 위해 코드를 작성하고 이해를 돕고자 하는 것입니다.


3. Variable(변수) 정의

W = tf.Variable(tf.random_normal([1]), name='weight')
b = tf.Variable(tf.random_normal([1]), name='bias')


이제 부터는 텐서플로의 사용법을 익히셔야 합니다. 하나씩 차근차근 살펴보도록 하겠습니다.

먼저 텟서플로는 Variable을 class로 정의하고 있습니다. 자세한 설명은 공식 사이트(https://www.tensorflow.org/api_docs/python/tf/Variable)에서 자세히 살펴보실 수 있습니다. 여기서는 우리가 Variable을 생성해야 하기에 생성자만 살펴보겠습니다.


# Create a variable.
w
= tf.Variable(<initial-value>, name=<optional-name>)


위 처럼 인자를 2개 받고 있습니다. 바로 초기 값과 옵션인 이 변수의 이름 입니다. 여기에서 이름은 그냥 명시적인 것이라 생각하시면 됩니다. 이를 이해하기 위해서는 텐서플로의 구조를 좀 더 이해하셔야 합니다. 지금은 단지 이렇게 만든다고 생각하시고, 우리는 w를 이 후 사용하면 된다고 알고 넘어 가겠습니다.


위 소스 코드처럼 weight와 bias를 나타낼 변수 2개를 w와 b라고 정의하고, 각각 초기값을 랜덤으로 주었습니다.


4. 가설(hypothesis) 정의

hypothesis = x_train * W + b


위에서 설명 드렸듯이 우리는 가장 간단한 방정식을 가설로 세웠습니다. 바로 y = ax + b => h = wx + b

x의 값을 실제 데이터가 있는 배열을 줬다는 것이 특이점 입니다.


5. 비용(cost) 정의

cost = tf.reduce_mean(tf.square(hypothesis - y_train))


비용은 위에서 설명드렸듯이, 가설로 구해진 값에 실제 제공된 해답과의 차를 구하는 것입니다. 이를 제곱하여 틀린 예상이 나왔을 때 비용을 높게 해서 벌칙(?)을 주는 것입니다. 이를 평균한 것을 cost라고 합니다. 

세부적으로 다시 보겠습니다.

hypothesis - y_train은 예상값에서 우리가 제공한 답을 빼는 것이며,

tf.square는 예상하셨듯이 제곱을 하는 것입니다.

tf.reduce_mean도 예상되 듯 평균을 구하는 것입니다. 자세한 설명은 공식사이트(https://www.tensorflow.org/api_docs/python/tf/math/reduce_mean)를 참고 하시기 바랍니다.  사이트에서는 간단히 "Computes the mean of elements across dimensions of a tensor." 로 정의 하고 있네요.


6. 최적화 정의

optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)

우리가 최적화한다는 것은 cost를 0으로 혹은 가깝게 만드는 것입니다. 이때 경사하강법을 사용하게 되는데 , 이 것이 tf.train.GradientDescentOptimizer()입니다.


7. training 정의

train = optimizer.minimize(cost)

6번에서 설명 했듯이 우리는 cost를 최소화 하는 것이 목적이므로, optimizer를 minimize하도록 정의 합니다


8. 세션 정의

sess = tf.Session()
sess.run(tf.global_variables_initializer())

7번까지 정의한 것들을 실제로 실행하기 위해서는 세션을 만들고 돌려 주어야 합니다. 이는 텐서플로의 방식이라 생각하시면 됩니다.

이를 위해 세션을 만들고 초기화 합니다.


9. training

for step in range(2001):
sess.run(train)
if step % 20 == 0:
print(step, sess.run(cost), sess.run(W), sess.run(b))

이제 실제로 학습을 진행하면서 학습이 얼마나 잘 이뤄지고 있는지 출력해 보는 것입니다. 20번마다 한번씩 출력하도록 합니다.


아래는 실제 결과 입니다.


0     9.740825 [-0.6625525] [0.51474833]

20   0.22892462 [0.44772384] [0.9445984]

40   0.12977746 [0.57195866] [0.94343925]

60   0.11715749 [0.60143316] [0.9032177]

80   0.10639789 [0.62105536] [0.86116177]

100 0.096632235 [0.63894933] [0.82072765]

120 0.087762915 [0.6559254] [0.78216]

140 0.079707704 [0.67209643] [0.7454017]

...

...

1900 1.6677723e-05 [0.9952569] [0.01078224]

1920 1.5146715e-05 [0.9954798] [0.01027551]

1940 1.3756621e-05 [0.99569225] [0.0097926]

1960 1.2494164e-05 [0.9958947] [0.00933238]

1980 1.1347351e-05 [0.9960876] [0.00889378]

2000 1.0305946e-05 [0.9962715] [0.0084758]


처음 cost값이 9.740825이지만 이후 바로 0에 가까운 값으로 수렴하는 것을 볼 수 있습니다.

이때 우리가 원하는 값 W와 b는 1에 가까운 값과 0에 가까운 값을 만들어 내는 것을 볼 수 있습니다.




그럼, y_train값을 [2,3,4]라 바꾸어 돌려보겠습니다.


0 0.30147278 [0.41524753] [1.8983669]

20 0.123657264 [0.5789661] [1.9160781]

40 0.11094618 [0.6117255] [1.8787322]

60 0.10075074 [0.6312082] [1.8379785]

80 0.0915033 [0.64865774] [1.7986482]

100 0.08310471 [0.66518074] [1.7611195]

...

...

1940 1.18310345e-05 [0.9960051] [1.0090812]

1960 1.0745008e-05 [0.9961929] [1.0086545]

1980 9.758181e-06 [0.9963718] [1.0082476]

2000 8.862747e-06 [0.9965424] [1.00786]


W가 1, b가 1에 가까운 값이 되었습니다.



마지막으로, y_train값을 [5,7,9]라 바꾸어 돌려보겠습니다. 예상하건데, W는 2, b는 3이어야 겠죠!?


0 30.04692 [0.59989] [0.4392455]

20 0.61493117 [2.4815636] [1.3583975]

40 0.31664327 [2.631838] [1.5116085]

60 0.28538767 [2.6186082] [1.5888001]

80 0.25917396 [2.5911033] [1.6558108]

100 0.23538576 [2.563473] [1.7190484]

120 0.21378095 [2.5370061] [1.7792544]

140 0.19415951 [2.5117702] [1.8366256]

...

...

1920 3.6896192e-05 [2.0070548] [2.9839628]

1940 3.3509856e-05 [2.0067234] [2.9847164]

1960 3.0432993e-05 [2.0064073] [2.9854345]

1980 2.7641414e-05 [2.0061061] [2.986119]

2000 2.5103713e-05 [2.0058193] [2.9867716]


예상대로 2와 3에 가까운 값이 되었습니다.


아래는 전체 코드 입니다.


import tensorflow as tf
x_train = [1,2,3]
y_train = [1,2,3] #[2,3,4] [3,4,5] [5,7,9]
W = tf.Variable(tf.random_normal([1]), name='weight')
b = tf.Variable(tf.random_normal([1]), name='bias')
hypothesis = x_train * W + b
cost = tf.reduce_mean(tf.square(hypothesis - y_train))
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
train = optimizer.minimize(cost)
sess = tf.Session()
sess.run(tf.global_variables_initializer())
for step in range(1000):
sess.run(train)
if step % 20 == 0:
print(step, sess.run(cost), sess.run(W), sess.run(b))


반응형
Comments