MY MEMO

[MACHINE LEARNING] Linear Regression 의 cost 최소화의 TensorFlow 구현 본문

MACHINE LEARNING/Sung Kim - 실습

[MACHINE LEARNING] Linear Regression 의 cost 최소화의 TensorFlow 구현

l_j_yeon 2017. 4. 7. 15:24
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import tensorflow as tf
import matplotlib.pyplot as plt
X = [1,2,3]
Y = [1,2,3]
 
W = tf.placeholder(tf.float32)
hypothesis = X*W
 
cost = tf.reduce_mean(tf.square(hypothesis-Y))
sess = tf.Session()
sess.run(tf.global_variables_initializer())
W_val = []
cost_val = []
for i in range(-30,50):
  feed_W = i * 0.1
  curr_cost,curr_W = sess.run([cost,W],feed_dict={W:feed_W})
  W_val.append(curr_W)
  cost_val.append(curr_cost)
 
plt.plot(W_val,cost_val)
plt.show()


이번에는 지난번에 했던 cost function을 이용하여 gradient descent 그래프를 그려볼것이다.


import matplotlib.pyplot 를 하기 위해서는 먼저 matplotlib를 깔아야한다.


window 사용자는 matplotlib를 pip로 깔고 font_manager.py에 코드를 추가시킨다.


출처 : http://blog.naver.com/udgttl12/220954605729


그럼 코드를 살펴보자.


data값이 주어졌고 W 0.1*i로 설정하였다.

그러기 위해 처음 W를 placeholder function을 사용하였다.


cost function을 구하고 session에 넣어준다.


cost function의 결과값을 W_val와 cost_val에 넣어주고 그것을 plot를 이용하여 그래프를 출력시키면



위와같은 그래프가 나온다. J function의 그래프이다.

여기서 step을 이용하여 가장 작은 값을 찾으면 

모든 데이터와 차이가 제일 작은 그래프를 그릴 수 있는 변수를 찾을 수 있다.



그래프를 그린 이후에 Gradient descent를 구하는 코드이다.

learning rate는 한 step의 크기이고

gradient 함수를 코드로 나타내면 위와 같다.

그럼 나온 값을 W에 계속 update해줘야하기 때문에 

update변수를 사용하여 계산한 값을 W에 assign해준다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import tensorflow as tf
x_data = [1,2,3]
y_data = [1,2,3]
 
w = tf.Variable(tf.random_normal([1]),name = 'weight')
x = tf.placeholder(tf.float32)
y = tf.placeholder(tf.float32)
 
hypothesis = x*w
 
cost = tf.reduce_sum(tf.square(hypothesis - y))
 
learning_rate = 0.1
gradient = tf.reduce_mean((w*x - y)*x)
descent = w - learning_rate*gradient
update = w.assign(descent)
 
sess = tf.Session()
sess.run(tf.global_variables_initializer())
for step in range(21):
 sess.run(update,feed_dict={x:x_data,y:y_data})
 print(step,sess.run(cost,feed_dict={x:x_data,y:y_data}),sess.run(w))

위와 같은 코드를 실행하면 가장 작은 수의 w가 나오게 된다.



cost가 점점 작아지고 w의 값이 1로 도달하는 것을 볼 수있다.


만약 w가 5부터 시작한다면 gradient descent 는 어떤식으로 돌아갈까?


w가 5이면 그래프의 오른쪽 위 방향부터 시작하여 minimum값을 찾는다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import tensorflow as tf
 
x = [1,2,3]
y = [1,2,3]
 
w = tf.Variable(5.0)
 
hypothesis = x*w
 
cost = tf.reduce_mean(tf.square(hypothesis - y))
 
optimizer = tf.train.GradientDescentOptimizer(learning_rate = 0.1)
train = optimizer.minimize(cost)
 
sess = tf.Session()
sess.run(tf.global_variables_initializer())
 
for step in range(100):
 print(step,sess.run(w))
 sess.run(train)


위의 코드를 실행시키면 9번째만에 1.0이라는 완벽한 정답 값을 찾는다.





만약에 w가 왼쪽 위 갑부터 시작하면 값은 어떻게 변할까?



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import tensorflow as tf
 
x = [1,2,3]
y = [1,2,3]
 
w = tf.Variable(-3.0)
 
hypothesis = x*w
 
cost = tf.reduce_mean(tf.square(hypothesis - y))
 
optimizer = tf.train.GradientDescentOptimizer(learning_rate = 0.1)
train = optimizer.minimize(cost)
 
sess = tf.Session()
sess.run(tf.global_variables_initializer())
 
for step in range(100):
 print(step,sess.run(w))
 sess.run(train)


-3부터 w가 시작해도 마찬가지로 빠르게 정확한 답을 찾는다.



이번에는 우리가 계산한 gradient와 함수로 계산한 gradient가 과연 같은 값을 갖는지 비교해보자


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import tensorflow as tf
 
x = [1,2,3]
y = [1,2,3]
 
w = tf.Variable(5.)
 
hypothesis = x*w
gradient = tf.reduce_mean((w*x - y)*x)*2
 
cost = tf.reduce_mean(tf.square(hypothesis - y))
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
 
gvs = optimizer.compute_gradients(cost)
apply_gradients = optimizer.apply_gradients(gvs)
 
sess = tf.Session()
sess.run(tf.global_variables_initializer())
 
for step in range(100):
 print(step,sess.run([gradient,w,gvs]))
 sess.run(apply_gradients)


apply_gradient 는 컴퓨터가 저절로 gradient를 해주는 것이고 gradient는 우리가 직접 짠 함수이다. 
하지만 이코드를 실행하는 와중에 
TypeError: Fetch argument None has invalid type 이러한 에러가 떴다. 
sess.run()을 실행하는 와중에 생긴 오류같은데 해결할 수가 없다. 지금은 멘탈이 나갔으니 다음에 찾아보기로 한다.

gvs = optimizer.compute_gradients(cost, [w]) 이렇게 변경해주면 오류가 해결된다.


위를 실행하면



우리가 만든 함수의 gradient와 w 가 앞에 출력되고 이후 computer에서 실행되는 gradient와 w가 출력된다.

위를 보면 두개의 값이 정확히 일치한다는 것을 알 수 있다.


+)

tensorflow 홈페이지에가면 optimizers에 대한 설명이 코드와 함께 나와있다.

직관적으로 optimizers함수가 무엇을 할지 알수있지만

정확하게 공부를 하는 것도 필요하다.


1
2
3
4
5
6
7
8
9
10
11
12
# Create an optimizer.
opt = GradientDescentOptimizer(learning_rate=0.1)
 
# Compute the gradients for a list of variables.
grads_and_vars = opt.compute_gradients(loss, <list of variables>)
 
# grads_and_vars is a list of tuples (gradient, variable).  Do whatever you
# need to the 'gradient' part, for example cap them, etc.
capped_grads_and_vars = [(MyCapper(gv[0]), gv[1]) for gv in grads_and_vars]
 
# Ask the optimizer to apply the capped gradients.
opt.apply_gradients(capped_grads_and_vars)

+) 최적화(optimization) : 손실함수(loss function)을 최소화시카는 파라미터(parameter/weight, W)들을 찾는 과정


+) compute_gradients() 는 손실에 대한 변수들의 기울기를 tf.gradient() 로 구합니다. 함수의 인자로 변수들을 넣어 주지 않아도, TF가 알아서 이 손실을 계산하는 데 필요한 모든 변수를 알아서 가져오고 그 변수들에 대해 기울기를 구합니다. 

물론, var_list 라는 인자를 통해 특정 변수들에 대해서만 기울기를 계산할 수도 있습니다! 전체 그래프의 일부 변수만을 업데이트하고 싶을 때 유용하게 쓰일 수 있습니다. 

apply_gradients() 는 위에서 구한 기울기 (혹은 외부에서 구해 온 기울기) 를 변수들에 업데이트합니다

출처 : http://deepestdocs.readthedocs.io/en/latest/001_tensorflow/0010/


Comments