ML
김성훈 교수님의 머신러닝 강의 시즌1을 참고하여 블로깅을 진행하겠다.
기본적인 개념 설명은 건너뛰고 TensorFlow 진행부터 시작하도록 하겠다.
개인 스터디 그룹에서 진행했던 개념사항이 있는데, 보고싶다면 https://koocci.gitbooks.io/aiclub-d/content/를 참고하자.
TensorFlow 는 구글에서 만든 Machine Intelligence를 위한 open-source 라이브러리
다
사실 TensorFlow 말고도 다른 라이브러리가 많은데, TensorFlow를 사용하는 이유는 의외로 간단하다. Popularity, contributor, forks, issue 등에 있어서 압도적 1위라 공부할 수 있는 환경이 잘 조성되어 있기 때문이다.
TensorFlow를 좀 더 알아보면, numerical computation using data flow graph
라는 말이 나오며, python을 이용해 많은 인기를 가지고 있다.
그럼 data flow graph 는 무엇일까?
Node와 Node를 잇는 edge가 있는 것을 그래프라 하는데, Node들이 Operation 이다. (덧셈, 곱셈) 그리고 edge는 data array 다.(tensor)
즉, tensor가 돌아다닌다 라는 의미에서 TensorFlow라 명명된 것이라 보인다.
설치 방법은 각자 알아서 찾아보고 하도록 하자.
설치가 완료되면
import tensorflow as tf
tf.__version__
위 코드를 이용해, 제대로 설치되었는지 확인하도록 하자.
이제 가장 기본 코드를 실행해보자.
import tensorflow as tf
# 그래프 속에 노드가 있고, 해당 노드에 Hello, TensorFlow!가 들어있다.
hello = tf.constant('Hello, TensorFlow!')
# session을 만들고
sess = tf.Session()
# hello를 실행
print(sess.run(hello))
출력의 맨 앞에 b 가 나오는데, byte stream
이라는 뜻이니 크게 걱정하지 말자.
그럼 조금 더 복잡한 Computational Graph를 만들자.
A와 B라는 노드가 +로 연결되는 그래프
다.
import tensorflow as tf
# tf.float32 -> 데이터 타입
node1 = tf.constant(3.0, tf.float32)
node2 = tf.constant(4.0)
# 더하기 노드
node3 = tf.add(node1, node2)
# node3 = node1 + node2 도 가능
# 결과값이 나오지않고 어떤 형태의 Tensor라는 것만 말해준다
# print("node1 : ", node1, "node2 : ", node2)
# print("node3 : ", node3)
# 세션을 만들자
sess = tf.Session()
print("sess.run(node1, node2) : ", sess.run([node1, node2]))
print("sess.run(node3) : ", sess.run(node3))
해당 설명은 코드 내에 있다.
TensorFlow 안의 진행을 보자.
- 그래프를 빌드
- sess.run을 이용해 그래프 실행
- 값이 update되거나 return이 된다.
프로그램으로 확인하자.
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))
위 코드가 sess.run
을 통해 그래프를 실행했고, 그 결과가 print 된다.
그럼 그래프를 그려서 실행하는 법은 알았는데, 그래프를 미리 만들어놓고 실행시킬 값을 주고 싶으면 어떻게 할까
이때도 마찬가지로 node를 만드는데 placeholder 라는 특별한 노드로 만든다.
import tensorflow as tf
# placeholder node 만들기
a = tf.placeholder(tf.float32)
b = tf.placeholder(tf.float32)
# adder_node라는 새로운 node
adder_node = a + b
sess = tf.Session()
# feed_dict를 통해 값 전달
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]}))
그럼 이제 Tensor 라는 걸 이해해보자.
기본적으로 Tensor는 기본적으로 array 를 말한다.
여기서 성질로 Ranks , Shapes , Types 가 나온다.
Rank 는 몇차원 Array냐
를 의미한다.
0 : Scalar
1 : Vector
2 : Matrix
3 : 3-Tensor
n : n-Tensor
와 같이 Rank가 부여된다.
Shape 는 각각의 element에 몇개씩 들어있느냐
를 말한다.
[] : 0-Dimension
[D0] : 1-D
[D0, D1] : 2-D
[D0,D1,D2] : 3-D
[D0,D1,…,Dn-1] : n-D
와 같이 나뉜다.
t = [[1,2,3], [4,5,6], [7,8,9]]
라면 [3 3)
혹은 [3,3]
로 나타내며 제일 안쪽이 3개, 그 것이 3개 있다는 의미다.
Type 은 데이터 타입
이고, 대부분 float32 혹은 int32를 많이 사용한다.
이제 Linear Regression의 cost 최소화 를 구현해보자
Hypothesis 나 cost function(Loss function) 은 개인적으로 알아보도록 하자.
이것을 TensorFlow로 구현할 것이다.
물론 위와 같이 그래프를 빌드하고, session을 통해 실행시키고 실행 결과를 그래프를 update하거나 return하게 만들 것이다.
import tensorflow as tf
# H(x) = Wx + b
# 우리가 학습할 데이터
x_train = [1,2,3]
# x가 1일때 1, 2일때 2, 3일때 3이되는 결과 값
y_train = [1,2,3]
# Variable이라는 node로 정의 : Variable의 개념이 기존의 변수 개념과 다름
# TensorFlow가 사용하는 Variable이라는 개념. 즉, TensorFlow가 자체적으로 변경시키는 값
# 혹은 Trainable한 변수라고 생각하면 좋다.
# 이런 TensorFlow의 Variable를 만들 땐 이 TensorFlow의 Shape을 생각한다.
# 이럴때 Random하게 줄 방법 중 하나로 random_normal을 쓴다
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은 tensor가 주어졌을 때 평균내는 것
cost = tf.reduce_mean(tf.square(hypothesis - y_train))
# cost minimize하는 방법 중 하나가 GradientDescent
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
# cost가 최소값이 되도록, train이 node의 이름
train = optimizer.minimize(cost)
# 실행
sess = tf.Session()
# W와 b를 사용했는데 그전에 tf.global_variables_initializer를 실행해 주어야 한다.
# 그렇게 해야 variable을 initialize 하게 된다
sess.run(tf.global_variables_initializer())
#train을 실행
for step in range(2001):
# 해당 노드를 실행
sess.run(train)
# 20번에 한번씩 출력
if step % 20 == 0:
print(step, sess.run(cost), sess.run(W), sess.run(b))
위 코드에서 train을 실행시키면 하위에 cost, hypothesis, w, b가 연결되어 조정할 수 있게 된다.
이런 경우는 쉽게 상상할 수 있다. (W = 1, b = 0)
실행해보면 cost는 매우 작은값으로 감소하고, W는 1, b는 0으로 가까워진다.
그럼 placeholder 를 사용해서 구현해보자.
import tensorflow as tf
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 = tf.reduce_mean(tf.square(hypothesis - Y))
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(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)
위 코드가 진행되면 W = 1, b = 1.1에 가깝게 나올 것이다.
이후는 다음에 진행하도록 하자.