Recommanded Free YOUTUBE Lecture: <% selectedImage[1] %>

Contents

TensorFlow 소개

TensorFlow는 구글에서 만든 머신러닝을 위한 오픈소스 소프트웨어 라이브러리다. 이 문서에 있는 모든 예제들은 TensorFlow를 기반으로 한다. 머신러닝이 뜨면서, 많은 종류의 머신러닝 애플리케이션들이 공개되고 있는데, 왜 TensorFlow를 선택했는지가 궁금할 것이다. 아래 그래프를 보자.

이유는 간단하다. 누군가 머신러닝을 위해 사용하는 주요 라이브러리들에 대한 통계자료를 만들었다. TensorFlow가 압도적이다. 많은 사람들이 사용하고 있고, TensorFlow 기반의 모델, 소스코드, 학습자료를 쉽게 찾을 수 있다. 그리고 구글이 주도적으로 개발하고 있다. 많은 구글 프로젝트가 엎어지기도 하지만, 인기도 인기인데다가 맘먹고 지원하는 거라서, 이 바닥에서는 터줏대감 행세를 할 가능성이 높으니 배워볼만 하겠다.

TensorFlow는 아래와 같이 요약 설정할 수 있다.
  • 데이터 플로우 그래프(Data flow graphs)를 이용해서 수치 연산(numerical computation)을 한다.
  • Python을 이용해서 코드를 만들 수 있다.
TensorFlow는 다른 언어들도 지원하지만 Python관련 자료가 가장 많다. 배우고 써먹기가 좋아서일 것이다. 일반 CPU 버전과 GPU 버전을 모두 지원한다. 또한 구글의 TPU(Tensor Processing Unit)위에서도 작동을 한다.

Data Flow Graph란 무엇인가 ?

그래프는 "노드"와 노드들을 연결하는 "엣지"로 구성된 트리와 유사한 구조다. TensowFlow에서 노드는 하나의 "operation" 덧셈, 곱셈과 같은 계산이다. 엣지는 노드와 노드간에 주고 받는 다차원 데이터 배열(multidimensional data arrays)다. 다차원 데이터 배열이라니까 어려워 보이는데, 그냥 노드가 연산에 사용 할 데이터, 혹은 연산이 끝난 데이터라고 이해하면 된다.

 Data Flow Graph

이 데이터 배열을 Tensor라고 한다. 이 Tensor가 노드와 노드사이를 흘러(Flow)다니면서 학습이 이루어진다.

TensorFlow 설치

우분투리눅스 17.04를 기준으로 한다. 로컬 PC에 직접 설치할 경우 python 버전 때문에 골치아픈 일이 생길 수 있으니 그냥 docker로 설치한다.
$ docker pull gcr.io/tensorflow/tensorflow
$ docker run --name tensorflow -it -p 8888:8888 gcr.io/tensorflow/tensorflow
jupyter notebook이 실행되며, 브라우저를 이용해서 TensorFlow를 이용 할 수 있다. Jupyter notebook을 사용하는게 목적은 아니니, 그냥 shell 로 접근해서 python으로 작업을 한다.

$ docker exec -it tensorflow  /bin/bash
root@cd778473cca5:/notebooks# 
설치한 TensorFlow버전을 확인해 보자.
$ python
Python 2.7.12 (default, Nov 19 2016, 06:48:10) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import tensorflow as tf
>>> tf.__version__
'1.3.0'
TensorFlow 버전 1.3.0이 설치된걸 확인 할 수 있다.

Hello World !

Hello World를 출력하는 TensorFlow 예제를 만들어보자.
import tensorflow as tf

hello = tf.constant("Hello, TensorFlow!")

sess = tf.Session()

print(sess.run(hello))
  • tensorflow를 import 한다.
  • tf.constant라는 함수를 이용해서 "Hello, TensorFlow!" 데이터를 가지는 constant를 만든다. "Hello, TensorFlow!" 데이터를 가지는 하나의 노드를 가지는 그래프를 만든상태다.
  • 지금은 노드를 "만들기만"한 상태다. 노드를 실행하기 위해서는 세션(session)을 만들고, 이 세션에서 노드를 실행해야 한다. sess.run 함수를 이용해서 hello 노드를 실행했다. 이제 이 노드는 "Hello, TensorFlow!"를 반환하고, print 함수가 문자열을 화면에 출력한다.
자 실행해보자.
$ python hello.py 
2017-09-26 15:12:35.090053: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE4.1 instructions, but these are available on your machine and could speed up CPU computations.
2017-09-26 15:12:35.090083: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE4.2 instructions, but these are available on your machine and could speed up CPU computations.
2017-09-26 15:12:35.090090: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use AVX instructions, but these are available on your machine and could speed up CPU computations.
2017-09-26 15:12:35.090098: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use AVX2 instructions, but these are available on your machine and could speed up CPU computations.
2017-09-26 15:12:35.090140: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use FMA instructions, but these are available on your machine and could speed up CPU computations.
Hello, TensorFlow!
실행된 것 같은데, 엄청나게 많은 메시지를 출력한다. 에러메시지는 아니고 "TensorFlow를 소스에서 빌드하면 더 빠르게 작동 할 수 있다"는 단순한 경고성 메시지다. 아래와 같은 코드를 넣는 것으로 경고 메시지를 없앨 수 있다.
import os
import tensorflow as tf

os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
리눅스 시스템이라면 "export TF_CPP_MIN_LOG_LEVEL=2"로 환경변수를 설정해서 경고메시지를 없앨 수 있다.

Computational Graph

조금 더 복잡한 문제를 풀어보자. 이 문제는 두 개의 노드로 구성된다. 이 두 개의 노드는 더하기 연산을 하는 노드로 연결되는 그래프를 만든다.

 Simple node

a와 b라는 노드가 있고, 이 두개의 노드가 출력하는 값을 adder_no 노드로 보내서 연산을 한다.

import tensorflow as tf
node1 = tf.constant(3.0, tf.float32)
node2 = tf.constant(4.0)
node3 = tf.add(node1, node2)

sess = tf.Session()
print("sess.run(node1, node2)", sess.run([node1, node2]))
print("sess.run(node3)", sess.run(node3))
  1. constant 3.0과 4.0을 가지는 node1, node2 두 개의 노드를 만들었다.
  2. 두개의 노드를 add() 함수를 이용해서 더하는 node3를 만들었다.
  3. 3개의 노드로 구성된 그래프를 만들었다.
  4. run() 함수를 이용해서 node1과 node2를 실행하고
  5. run() 함수를 이용해서 node3를 실행했다. node3은 node1과 node2를 더한다.
실행 결과는 아래와 같다.
('sess.run(node1, node2)', [3.0, 4.0])
('sess.run(node3)', 7.0)

TensorFlow의 실행 구조

TensorFlow의 실행 구조는 아래와 같다.

  1. 먼저 텐서플로우 연산을 수행할 그래프를 만든다.
  2. 다음 "sess.run(op)"를 이용해서 그래프를 실행한다.
  3. 그래프의 노드들이 실행되면서, 값들이 업데이트되거나 출력된다.
앞서 다루었던 예지를 이용해서, 위의 3단계로 연산이 진행되는지 확인해 보자.

  1. 먼저 node1, node2, node3 3 개의 노드를 구성했다.
    node1 = tf.constant(3.0, tf.float32)
    node2 = tf.constant(4.0)
    node3 = tf.add(node1, node2)
2. sess.run(op)를 이용해서 그래프의 노드를 실행해서 값을 가져오고 add() 연산을 수행했다.
sess = tf.Session()
print("sess.run(node1, node2)", sess.run([node1, node2]))
print("sess.run(node3)", sess.run(node3))
3. sess.run(op)의 실행결과 그래프의 변수들이 업데이트되고, 연산 값을 리턴한다.

Placeholder

그래프를 만들고(build)하고 실행해서 결과를 가져오는 방법을 공부했다. 그런데, 앞선 예제는 노드의 데이터로 constant 즉, "상수"를 사용했다. 그래프를 만드는 단계가 아닌, 실행 단계에서 데이터를 입력하고 싶다면 어떻게 해야 할까. ? 이때 노드를 placeholder 노드로 만들면 된다.

a = tf.placeholder(tf.float32)
b = tf.placeholder(tf.float32)
adder_node = a+b # + provides a shortcut for tf.add(a,b)

sess = tf.Session()
print(sess.run(adder_node, feed_dict={a:3, b: 4.5}))
print(sess.run(adder_node, feed_dict={a:[1,3], b: [2,4]}))
placeholder 타입의 노드 a와 b를 만들었다. 이렇게 만든 노드는 세션을 run 하는 시점에 값을 입력 할 수 있다. 프로그래밍에서의 변수와 비슷한 역할을 하는 녀석이라고 볼 수 있겠다.
7.5
[ 3.  7.]

Everything is Tensor

TensorFlow는 Tensor의 흐름을 다루는 라이브러리다. 따라서 Tensor에 대해서 이해를 할 필요가 있다. 기본적으로 텐서는 배열(Array)이다.
3   # rank 0 tensor; this is a scala with shape []
[1., 2., 3.]    # rank 1 tensor; this is a vector with shape [3]
[[1., 2., 3.],[4., 5., 6. ]] # rank 2 tensor; a matrix with shape [2,3]
[[[1., 2., 3.]],[[4., 5., 6. ]]] # rank 3 tensor with shape [2,1,3]

Tensor Ranks