TensorFlow 무작정 따라하기 1 : Getting Started

머신러닝 라이브러리는 여러가지가 있지만 그 중에 우선 TensorFlow를 사용하는 방법을 간단히 익혀보도록 하겠다.

앞으로 작성할 예시는 TensorFlow 공식 홈페이지에서 확인할 수 있다.
https://www.tensorflow.org/get_started/ (영어)
https://tensorflowkorea.gitbooks.io/tensorflow-kr/content/ (한국어)

다만 영어로 작성된 글을 한국어로 정리를 하며 써서 그런지 세부적인 내용이 조금 다를 수 있다. 이 글은 영어로 작성된 공식 홈페이지를 보며 작성했다.

이 글을 처음부터 읽는 것보다는 공식 사이트를 보며 공부하다가 이해가 안 되는 부분만 이 글에서 따로 찾아보는 것을 추천한다. 이 글은 교육용 글이 아니라 공부 내용을 정리한 글이기 때문에 잘못된 내용이 있을 수 있다.

행렬 작성
TensorFlow로 행렬을 작성할 때는 대괄호 [ ] 를 사용해야 한다.
예를 들어,
m x n 행렬 : [m, n]
k x m x n 행렬 : [k, m, n]

만약에 동적인 행렬을 사용하고 싶다면 [None, n] 과 같이 행의 자리에 None을 사용하면 된다.

constant 변수 작성
변수라고는 하지만 다른 프로그래밍 언어처럼 직접 값을 대입할 수는 없다.
원문에서는 node라고 표현했는데, 그래프를 그릴 때 필요한 점들 정도로 이해했다.
우선 TensorFlow를 상단에 import 한 후에 작성한다.
import tensorflow as tf
node_int = tf.constant(3, dtype=tf.int32)
node_float = tf.constant(3.0, dtype=tf.int32)
node_string = tf.constant('hello', dtype=tf.string)
dtype은 해당 변수의 데이터 타입을 의미하는데 생략해도 무방하다.
위 코드는 아래와 같이 써도 같은 의미를 가진다.
node_int = tf.constant(3)
node_float = tf.constant(3.0)
node_string = tf.constant('hello')
float의 경우 3.0이 아닌 3. 만 써도 된다.

위의 코드를 작성한 후에 출력을 하려고 하면 변수의 값이 출력되는 것이 아니라
<tf.Tensor 'Const_1:0' shape=() dtype=float32> 과 같은 변수의 정보들이 출력된다.

결과값을 얻고 싶다면 Session 오브젝트를 생성한 후 run 함수를 실행해야 한다.
sess = tf.Session()
print(sess.run([node_int, node_float]))
그러면 아래와 같은 결과가 나온다.
[3, 3.0]
그런데 위의 방식대로 변수에 바로 값을 지정하는 것이 아니라
우선 변수를 담을 것이라고 정해놓은 후 나중에 값을 넣을 수도 있다.
a = tf.placeholder(tf.float32)
b = tf.placeholder(tf.float32)
adder_node = a + b
a와 b를 선언한 후에 adder_node라는 변수에서는 a+b를 실행하겠다고
연산의 방식만 정해놓았다.

그 후에 Session을 만들고 run 함수를 실행시키는데, 아까와 다른 점은
a와 b에 넣을 값을 지정해주는 것이다.
print(sess.run(adder_node, {a: 3, b:4.5}))
print(sess.run(adder_node, {a: [1,3], b: [2, 4]}))
그러면 결과는 다음과 같다.
7.5
[ 3.  7.]
run을 할 때 값에 상수를 넣으면 상수 결과가 나오고, 값에 배열을 넣으면
결과도 배열로 나오게 된다.

adder_node = a+b 를 원하는 식으로 마음대로 바꾼 후에 실행해도 된다.


variable 변수 작성
constant는 값을 지정했을 때 바로 값이 변수에 적용되는 반면
variable은 global_variables_initializer 라는 함수를 실행해야만 값이 변수에 적용이 된다.

만약
a = tf.Variable([2.], dtype=tf.float32)
라고 선언을 했을지라도, a는 아직 2.0의 값을 의미하지 않는다.
sess.run(tf.global_variables_initializer())
위 코드처럼 global_variables_initializer 를 실행한 후에 a는 2.0을 의미하게 되는 것이다.

GradientDescent 기법
GradientDescent을 우리말로 쓰면 경사하강법이라고 한다. 머신러닝을 할 때 사용하는 최적화 알고리즘 중 하나인데, 머신러닝을 배우기 시작하면 가장 먼저 배우는 알고리즘이다. 우선은 이런 알고리즘이 있고 어떻게 사용하는지만 알고 넘어가도록 하자.

예를 들어, y = Wx + b 라는 함수가 있고 사용자가 알고 있는 값은 x,y 값이라고 하자.
이 때 W, b의 값을 알아내기 위해 GradientDescent 알고리즘을 사용해보는 코드는 다음과 같다.
import numpy as npimport tensorflow as tf
# Model parameters
W = tf.Variable([.3], dtype=tf.float32)
b = tf.Variable([-.3], dtype=tf.float32)
# Model input and output
x = tf.placeholder(tf.float32)
linear_model = W * x + b
y = tf.placeholder(tf.float32)
# loss
loss = tf.reduce_sum(tf.square(linear_model - y)) # sum of the squares
# optimizer
optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)
# training data
x_train = [1,2,3,4]
y_train = [0,-1,-2,-3]
# training loop
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init) # reset values to wrong
for i in range(1000):
  sess.run(train, {x:x_train, y:y_train})
# evaluate training accuracy
curr_W, curr_b, curr_loss = sess.run([W, b, loss], {x:x_train, y:y_train})
print("W: %s b: %s loss: %s"%(curr_W, curr_b, curr_loss))
공식 홈페이지의 코드를 그대로 가져왔다.

x_train 과 y_train은 우리가 이미 알고있는 x, y의 값이다.
W와 b는 우리가 알고싶은 값인데 현재는 그 값을 모르기 때문에 우선 아무 값이나 써놓은 것이다.
optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)
위 부분에서 optimizer는 경사하강법 알고리즘에서 learning rate(학습속도)를 0.01로 설정한 것이며, train에서 경사하강법 알고리즘을 이용해 loss의 값이 최소가 되도록 계산을 할 것이라고 설정했다. loss가 나타내는 것을 Cost Function 또는 Loss Function 이라고 한다. 우리말로하면 비용함수 또는 손실 함수이다.

learning rate 라는 말이 갑자기 나와서 이해가 안 될텐데, 알고리즘이 얼마나 빠르게 loss의 값이 최소가 되는 지점을 찾을지를 결정하는 값이라고 생각하면 된다.
그렇다면 learning rate를 높게 하면 더 빨리 찾을 최소점을 찾을텐데 왜 0.01 이라는 작은 값을 설정했는지 의문이 들 것이다. 이 글에서 설명하기에는 내용을 벗어났기 때문에 설명하지 않겠지만, 이 글의 가장 밑에 공부에 도움이 되는 주소를 남겨놓겠다.
for i in range(1000):
  sess.run(train, {x:x_train, y:y_train})
위 코드에서 경사하강법을 1000번 사용하여 W와 b의 값을 찾아내는 것이다.
curr_W, curr_b, curr_loss = sess.run([W, b, loss], {x:x_train, y:y_train})
마지막 코드에서는 [W, b, loss]를 각각 [curr_W, curr_b, curr_loss]로 대입하는 것이다. 이 때 sess.run을 사용한 이유는 위에서 TensorFlow에서 만든 변수는 일반 변수처럼 값 대입이 되지 않기 때문에 사용한 것이다. 그리고 {x:x_train, y:y_train}은 loss에 넣기 위한 값이다. 왜 이 값이 필요하냐면, loss 는 y=Wx+b 의 함수로 구한 y값과 실제 우리가 알고있는 y값의 차이를 제곱하여 평균을 하겠다는 모델일 뿐이지 어떤 값을 가진 변수가 아니기 때문이다. 따라서 경사하강법을 이용하여 구한 W,b가 적용된 loss 모델에 다시 우리가 아는 값 x,y 를 넣었다.

curr_W, curr_b, curr_loss에 대입하지 않고
sess.run([W, b, loss], {x:x_train, y:y_train})
라고만 해도 값은 정상적으로 출력된다.


---------------------------------------------------------------------------
TensorFlow는 머신러닝의 이론을 잘 모르더라도 누구나 쉽게 활용할 수 있도록 해주는 라이브러리이다. 따라서 TensorFlow를 잘 다루기 위해서는 머신러닝 이론을 따로 공부해주는 것이 도움이 될 것이다. 처음 머신러닝을 공부하기가 막막한 사람은 아래 링크에서 공부를 시작해보는 것을 추천한다.

https://www.coursera.org/learn/machine-learning/home/welcome

Coursera 사이트는 전 세계의 뛰어난 교수님들의 강의를 무료로 들을 수 있는 사이트이다. 위 링크에서 머신러닝을 강의하시는 분은 Andrew Ng 이라는 분인데 꽤나 간단하게 머신러닝 이론들을 설명을 해주고 있다. 또한 강의를 들은 후 실제로 코딩을 통해 과제를 제출함으로써 배운 이론들을 정리할 수 있다.