아마존 웹 서비스 중 머신 러닝을 향해 달려가기 위해 사전에

딥러닝이 어떤 것이고 이런 기술 들은 어떤 것들이 있는지 확인하기 위해 찾아본 항목들

 

 

 

 

 

 

 

TensorFlow 기본 개념


아래의 글은 Machine Learning, Andrew Ng 강의에서도 나오는 말이긴 하다.

A computer program is said to learn from experience E with respect to some class of taks T and performance tasks in T, as measured by P, improves with experience E, Tom M. Mitchell

Tensor는 뭔가?

많은 데이터를 효과적으로 다룰 자료구조이다.

다차원 array, list라고 생각하면 된다.
이래서 NumPy를 확장한것이 TensorFlow라는것도 말이 된다.

# What is tensor?
tensor1 = 7          # 0-dimensional
tensor2 = [7]        # 1-dimensional
tensor3 = [[1,2,3],  # 2-dimensional
           [4,5,6]]  ...
           ...

Flow의 의미는 Graph이다.
즉 모든 계산을 쉽게하기위해서 각각의 연산을 잘게 쪼개고 이것을 graph로 연결 한 것이다.
미분 chain rule 같은것을 생각해보면 왜 연산이 간단해 지는지 알 수 있다.

Graph, node, edge

선언과 실행이 지점이 다름

a=1이라고 설정해도 나중에 그렇게 한다는 뜻이지 지금 당장 a는 1이 아니다. 기본적인 python 프로그래밍과는 다르다.

결국 어떻게 잘 동작하겠다 하는 계획을 graph로 표현한 것이 TensorFlow이다.

동작을 정의한 것은 operation 이다.

operation 정의를 포함한 것이 node이다.
node와 node를 연결하는 것이 edge이다.

이러한 구조에서 tensor데이터 구조가 이동하면서 operation에 의해서 연산을 하는 방식이다.

import tensotflow as tf

일단 import 하면 내부적으로 default_graph_stack에 default Graph가 생긴다.

tf.get_default_graph()명령어로 접근 가능
이 graph에 저장된 operation을 확인해 보면 []비어 있는 것을 알 수 있다.

상수를 하나 선언 하면 아래처럼 주소가 기록된다.
이러한 의미는 operation이 리스트 형태로 들어가 있는 것이다.

import tensorflow as tf
graph = tf.get_default_graph()
graph.get_operations()
input = tf.constant(1.0)
operations = graph.get_operations()
operations
[<tensorflow.python.framework.ops.Operation at 0x7f94695fbd90>,
 <tensorflow.python.framework.ops.Operation at 0x7f944788a990>]

operation을 감싸고 있는 node를 출력해보자.

>>> operations[0].node_def
## name: "Const"
## op: "Const"
## attr {
##   key: "dtype"
##   value {
##     type: DT_FLOAT
##   }
## }
## attr {
##   key: "value"
##   value {
##     tensor {
##       dtype: DT_FLOAT
##       tensor_shape {
##       }
##       float_val: 1.0
##     }
##   }
## }

TensorFlow는 내부적으로 protocol buffer를 이용한다.
어떤 google style의 JSON이라고 생각하면 쉽다. 위에 출력도 JSON 스럽기 때문이다.

왜 tensorflow는 이처럼 고유한 특징의 구조나 타입들을 가지는 것일까?

Numpy는 기본적으로 matrix을 연산을 위해서 C++로 개발 되었다. 하지만 여전히 많은 overhead를 발생 시킨다.
완전히 Python 영역 밖에서 동작 시킴으로 성능을 끌어 올린다.
이러한 방법은 Theano또는 Torch에서 수행하는 방식이다.

그냥 input을 출력해 보자

In [27]: input
Out[27]: <tf.Tensor 'Const_9:0' shape=() dtype=float32>

32비트 float tensor를 확인 할 수 있다. no dimension 이며 그냥 싱글 숫자이다.

이제 실제로 input값을 session으로 실행하자.
default에 의해서 default graph에서 값을 꺼내오는 방식이다.

>>> sess = tf.Session()
>>> sess.run(input_value)
## 1.0

초 간단 TensorFlow neuron

Hadley Wickham said Names have objects rather than the reverse이다.
표현 하면 아래의 그림과 같다.

여기서 말하는 초간단 neron은 non-identity activation function도 없고 bias도 없는 것을 말한다.

constant는 상수를 의미하고, variable은 계속 변화하는 값을 의미 한다.

weight = tf.Variable(0.8)
#지원하는 operation 이름 확인
for op in graph.get_operations(): print op.name

x에 w를 곱해서 y라는 출력값을 만들어냄
이때 참값 은 y_로 0이다.

입력값은 1로 고정 시킨다면 당연히 참값 y_ = 0과 일치시키는 w는 0일것이다.

단순한 방적이다.

1 * w = 0 일떄 당연히, w는 0이 optimal한 값이다.
하지만 이러한 해를 wieght값 w를 조정하면서 전체 cost를 줄이는 방법으로 차근 차근 찾아보자.
w의 시작값을 0.8로 설정 한다.
이때의 cost는
0.8 * 1 = 0.8 이다.

이 코스트를 계산하는 것이 최소제곱법이 있다.

 

minimum(y^y)2


이것을 최소화로 만들어주는 방법은 y를 결정하는 함수 f(x) = wx 입니다. 결국 w를 조정해서 해를 찾을 수 있게 된다.
그리고 이러한 과정에 쓰이는 데이터를 트레이닝 데이터라고 하고 과정을 러닝 한다라고 한다.

 

이 cost function을 하는 방법은 gradient descent algorihtm을 사용하게 됩니다.

optim = tf.train.GradientDescentOptimizer(learning_rate = 0.025)

이것을 이해보면 결국 cost 함수를 미분한 것입니다.

cost 함수를 미분하면 2 * 0.8 = 1.6의 값이 됩니다.
이떄 learing rate을 0.025로 했기 때문에 
1.6 * 0.025 = 0.04가 됩니다.

아래코드는 이러한 과정을 수행하는 전체 코드이다.

import tensorflow as tf
x = tf.constant(1.0, name='input')
w = tf.Variable(0.8, name='weight')
y = tf.mul(w, x, name='output')
y_ = tf.constant(0.0, name='correct_value')
loss = tf.pow(y - y_, 2, name='loss')
train_step = tf.train.GradientDescentOptimizer(0.025).minimize(loss)
for value in [x, w, y, y_, loss]:
    tf.scalar_summary(value.op.name, value)
summaries = tf.merge_all_summaries()
sess = tf.Session()
summary_writer = tf.train.SummaryWriter('log_simple_stats', sess.graph)
sess.run(tf.initialize_all_variables())
for i in range(100):
    if i % 10 ==0:
        print("epoch {}, output: {}".format(i, sess.run(y)))
    summary_writer.add_summary(sess.run(summaries), i)
    sess.run(train_step)

출력결과

epochs 0, output: 0.800000011921
epochs 10, output: 0.478989481926
epochs 20, output: 0.286788702011
epochs 30, output: 0.171710968018
epochs 40, output: 0.10280970484
epochs 50, output: 0.0615559667349
epochs 60, output: 0.0368558317423
epochs 70, output: 0.0220669470727
epochs 80, output: 0.0132122989744
epochs 90, output: 0.00791069027036

output은 weight 값 w를 의미하며 정답인 0에 거의 근접한것을 알 수 있다.

해당 결과를 Tensor Board를 통해서 시각적으로 확인 할 수도 있다.
프로젝트 디렉터리에서 log_simple_stats에 저장한다고 했으니 그곳에서 아래의 명령어를 수행 한다.

tensorboard --logdir=./

그다음 크롬을 이용해서 http://192.168.188.129:6006/#graphs아래 주소로 접속 한다.
IP Address는 각자 맞춰서 한다. 그냥 local에서 작업한다면 localhost:6006/#graphs라고 쓰면 된다.

참고자료

https://www.oreilly.com/learning/hello-tensorflow
https://jihobak.github.io/2016-06-26-deeplearning-ninja001/

 

  . 참고 링크 : http://goodtogreate.tistory.com/475

 

 

 

- TensorFlow - MNIST For ML Beginnners (한글 번역)
https://aiforum.kr/t/tensorflow-mnist-for-ml-beginnners/57

 

- 딥러닝 관련 블로그
http://blog.naver.com/PostList.nhn?blogId=sogangori&from=postList&categoryNo=6


- 돈되는 인공지능 뉴스
http://www.hellot.net/new_hellot/magazine/magazine_read.html?code=205&sub=001&idx=29475