<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 이 노트북은 Hell, Tensorflow! 의 내용을 참고로 하여 노트북으로 재 정돈한 것입니다.
Step1:  텐서플로우의 디폴트 그래프는 직접 접근을 할 수 없고 get_default_graph 메소드를 이용합니다.
Step2:  초기에는 디폴트 그래프에 아무런 연산도 들어 있지 않고 비어 있습니다.
Step3:  실수 1.0 값을 가지는 상수 input_value 를 만듭니다. name 옵션을 사용하여 이름을 지정하면 텐서보드의 그래프에서 구분하기 편리합니다.
Step4:  상수 하나도 텐서플로우 그래프에서는 하나의 노드로 취급되어 get_operations 에서 리턴되는 리스트가 비어있지 않습니다.
Step5:  get_operations 로 받은 리스트에는 하나의 엘리먼트가 들어 있고 엘리먼트는 Operation 클래스의 인스턴스입니다.
Step6:  ops 의 첫번째 노드(여기서는 상수노드)의 정의를 조회하면 프로토콜 버퍼 형식으로 연산 노드를 표현하고 있음을 알 수 있습니다.
Step7:  input_value는 상수 텐서를 위한 일종의 연산 노드이며 값이 들어 있지 않습니다.
Step8:  텐서플로우의 세션을 생성한 후에 input_value 를 실행하면 결과 값이 리턴됩니다.
Step9:  두 수를 곱하는 연산을 만들어 보기 위해 weight 변수를 만듭니다. 상수 노드는 tensorflow.python.framework.ops.Tensor 의 객체인데 변수 노드는 tensorflow.python.ops.variables.Variable 의 객체입니다.
Step10:  이제 연산 노드는 다섯 개로 늘어납니다. 변수 텐서를 생성하면 그래프에 초기값과 할당, 조회에 관련된 노드가 추가로 생성되기 때문입니다.
Step11:  weight 변수와 input_value 상수를 곱하여 곱셈 노드로 만들어지는 output_value 텐서를 만듭니다.
Step12:  그래프의 노드를 다시 조회하면 mul 노드가 추가된 것을 확인할 수 있습니다.
Step13:  그래프의 모든 변수를 초기화하기 위해 init 노드를 만들고 run 메소드로 실행합니다.
Step14:  1 * 0.8 의 출력 값은 예상대로 0.8을 리턴합니다.
Step15:  SummaryWriter를 사용하여 log_simple_graph 디렉토리에 sess에서 만들어진 세션 그래프 정보를 기록합니다.
Step16:  쉘에서 tensorboard --logdir=log_simple_graph 명령으로 텐서보드를 실행하고 브라우저로 http
Step17:  실제 참 값(y_)을 0이라고 정의하고 예측값과의 차이의 제곱을 에러 함수(loss function or error function)로 정의합니다.
Step18:  학습속도를 0.025로 하고 그래디언트 디센트 최적화 방식을 선택합니다.
Step19:  수동으로 에러함수의 기울기를 계산해 보면 아래와 같이 1.6이 나옵니다. 가중치 값이 0.8 이므로 y = 0.8 * 1.0 = 0.8 이 되고 위에서 가정한 대로 y_ = 0 입니다. 에러 함수의 미분 방정식은 2(y - y_) 이므로 결과 값은 2 * 0.8 = 1.6 이 됩니다.
Step20:  계산된 그래디언트를 가중치에 반영하면 학습속도가 0.025 이므로 0.025 * 1.6 = 0.04 가 되어 w 가 0.04 만큼 감소됩니다.
Step21:  이 과정을 반복하도록 루프를 작성하고 summary_writer를 이용하여 결과 y 값을 기록하면 텐서보드에서 그래프로 값의 변화를 확인할 수 있습니다.
<ASSISTANT_TASK:>
Python Code:
%load_ext watermark
%watermark -vm -p tensorflow,numpy,scikit-learn
import tensorflow as tf
Explanation: 이 노트북은 Hell, Tensorflow! 의 내용을 참고로 하여 노트북으로 재 정돈한 것입니다.
End of explanation
graph = tf.get_default_graph()
Explanation: 텐서플로우의 디폴트 그래프는 직접 접근을 할 수 없고 get_default_graph 메소드를 이용합니다.
End of explanation
graph.get_operations()
Explanation: 초기에는 디폴트 그래프에 아무런 연산도 들어 있지 않고 비어 있습니다.
End of explanation
input_value = tf.constant(1.0, name='input_value')
Explanation: 실수 1.0 값을 가지는 상수 input_value 를 만듭니다. name 옵션을 사용하여 이름을 지정하면 텐서보드의 그래프에서 구분하기 편리합니다.
End of explanation
graph.get_operations()
Explanation: 상수 하나도 텐서플로우 그래프에서는 하나의 노드로 취급되어 get_operations 에서 리턴되는 리스트가 비어있지 않습니다.
End of explanation
ops = graph.get_operations()
len(ops), ops[0].__class__
Explanation: get_operations 로 받은 리스트에는 하나의 엘리먼트가 들어 있고 엘리먼트는 Operation 클래스의 인스턴스입니다.
End of explanation
op = ops[0]
op.node_def
Explanation: ops 의 첫번째 노드(여기서는 상수노드)의 정의를 조회하면 프로토콜 버퍼 형식으로 연산 노드를 표현하고 있음을 알 수 있습니다.
End of explanation
input_value.__class__, input_value
Explanation: input_value는 상수 텐서를 위한 일종의 연산 노드이며 값이 들어 있지 않습니다.
End of explanation
sess = tf.Session()
sess.run(input_value)
Explanation: 텐서플로우의 세션을 생성한 후에 input_value 를 실행하면 결과 값이 리턴됩니다.
End of explanation
weight = tf.Variable(0.8, name='weight')
weight
Explanation: 두 수를 곱하는 연산을 만들어 보기 위해 weight 변수를 만듭니다. 상수 노드는 tensorflow.python.framework.ops.Tensor 의 객체인데 변수 노드는 tensorflow.python.ops.variables.Variable 의 객체입니다.
End of explanation
ops = graph.get_operations()
for op in ops:
    print(op.name)
Explanation: 이제 연산 노드는 다섯 개로 늘어납니다. 변수 텐서를 생성하면 그래프에 초기값과 할당, 조회에 관련된 노드가 추가로 생성되기 때문입니다.
End of explanation
output_value = weight * input_value
output_value
Explanation: weight 변수와 input_value 상수를 곱하여 곱셈 노드로 만들어지는 output_value 텐서를 만듭니다.
End of explanation
ops = graph.get_operations()
for op in ops:
    print(op.name)
Explanation: 그래프의 노드를 다시 조회하면 mul 노드가 추가된 것을 확인할 수 있습니다.
End of explanation
init = tf.initialize_all_variables()
sess.run(init)
Explanation: 그래프의 모든 변수를 초기화하기 위해 init 노드를 만들고 run 메소드로 실행합니다.
End of explanation
sess.run(output_value)
Explanation: 1 * 0.8 의 출력 값은 예상대로 0.8을 리턴합니다.
End of explanation
summary_writer = tf.train.SummaryWriter('log_simple_graph', sess.graph)
Explanation: SummaryWriter를 사용하여 log_simple_graph 디렉토리에 sess에서 만들어진 세션 그래프 정보를 기록합니다.
End of explanation
x = tf.constant(1.0, name='x')
w = tf.Variable(0.8, name='w')
y = tf.mul(w, x, name='y')
init = tf.initialize_all_variables()
sess.run(init)
Explanation: 쉘에서 tensorboard --logdir=log_simple_graph 명령으로 텐서보드를 실행하고 브라우저로 http://localhost:6006 으로 접속한 후 그래프 탭을 클릭하면 아래와 같은 그림이 보입니다. 이 그래프는 init 연산에서 weight 변수를 초기화하고 mul 연산에서 input_value 와 wegiht 를 사용하고 있다는 것을 잘 보여 주고 있습니다.
같은 값을 가지는 상수와 변수를 x, w 로 다시 만듭니다. 그리고 곱셉 노드를 파이썬의 곱셉 연산자를 사용하지 않고 텐서플로우에서 제공하는 수학 함수인 mul을 사용하여 표현할 수 있습니다.
End of explanation
y_ = tf.constant(0.0)
loss = (y - y_)**2
Explanation: 실제 참 값(y_)을 0이라고 정의하고 예측값과의 차이의 제곱을 에러 함수(loss function or error function)로 정의합니다.
End of explanation
optim = tf.train.GradientDescentOptimizer(learning_rate=0.025)
grads_and_vars = optim.compute_gradients(loss)
grads_and_vars
Explanation: 학습속도를 0.025로 하고 그래디언트 디센트 최적화 방식을 선택합니다.
End of explanation
sess.run(grads_and_vars[1][0])
Explanation: 수동으로 에러함수의 기울기를 계산해 보면 아래와 같이 1.6이 나옵니다. 가중치 값이 0.8 이므로 y = 0.8 * 1.0 = 0.8 이 되고 위에서 가정한 대로 y_ = 0 입니다. 에러 함수의 미분 방정식은 2(y - y_) 이므로 결과 값은 2 * 0.8 = 1.6 이 됩니다.
End of explanation
sess.run(optim.apply_gradients(grads_and_vars))
sess.run(w)
Explanation: 계산된 그래디언트를 가중치에 반영하면 학습속도가 0.025 이므로 0.025 * 1.6 = 0.04 가 되어 w 가 0.04 만큼 감소됩니다.
End of explanation
train_step = tf.train.GradientDescentOptimizer(0.025).minimize(loss)
summary_y = tf.scalar_summary('output', y)
for i in range(100):
    summary_str = sess.run(summary_y)
    summary_writer.add_summary(summary_str, i)
    sess.run(train_step)
Explanation: 이 과정을 반복하도록 루프를 작성하고 summary_writer를 이용하여 결과 y 값을 기록하면 텐서보드에서 그래프로 값의 변화를 확인할 수 있습니다.
End of explanation
<END_TASK>