티스토리 뷰
[모두의딥러닝] Neural Network 1: XOR 문제와 학습방법, Backpropagation (1986 breakthrough)
Sh.TK 2017. 9. 4. 14:47모두의 딥러닝
Neural Network 1: XOR 문제와 학습방법, Backpropagation (1986 breakthrough)
강의-1
이제부터는 뉴럴 네트워크에 대해서 강의한다.
우선 이전 강의에서 XOR에 대한 문제와 그리고 문제를 해결하는 방법에 대해 간략히 말했다.
XOR의 그래프는 다음과 같이 Layer를 2개 이상 둬 해결할 수 있었다. 그러나 Minsky 교수님께서 Layer를 여러 개 사용하여 XOR 문제를 풀 순 있지만, 학습을 시키기 위해 W와 b값을 조절해야 하는데, 그 값을 조절할 수 없다고 한다.
물론 이 부분은 Back-propagation이란 알고리즘으로 해결된다.
위의 이미지는 뉴럴 네트워크를 사용하여 XOR 을 해결할 수 있는걸 보여준다. 해당 부분에 대해 김성훈 교수님은 상세히 여러 이미지를 사용하셔서 설명하나, 하나의 이미지로 대체하고, 설명해보겠다.
(보라색)X1, X2에 Sigmoid 한 값이 Y1 이고 (초록색)X1, X2에 Sigmoid 한 값이 Y2이다. 그리고 해당 값들 Y1, Y2를 입력 받고(검은색) Sigmoid한 값이 우리가 찾는 Y hat 값이다.
해당 이미지는 X1 = 1그리고 X2 = 1일 때, Y hat값이 0인 것을 나타내준다.
처음부터 하나씩 대입해보자.
X1 = 0, X2 = 0 일 때, (보라색) 0, (초록색) 1 이다. Sigmoid를 사용하기 때문에, 값은 0~1사이의 값이 나오므로 다음과 같은 결과가 나온다.
그리고 (검은색)0, 1을 넣으면, 최종적으로 0이 나온다.
X1 = 0, X2 = 1, (보라색) 0, (초록색) 0 = (검은색) 1
X1 = 1, X2 = 0, (보라색) 0, (초록색) 0 = (검은색) 1
X1 = 1, X2 = 1, (보라색) 1, (초록색) 0 = (검은색) 0
이다.
해당 이미지가 지금까지 한 내용을 나타내주는 이미지이다. X1, X2 값들을 각각의 노드에 넣고 각 출력 값들을 Sigmoid한 다음, 그 값들을 입력으로 다른 노드에 넣는다. 그리고 그 값을 Sigmoid한 값이 Y hat이다.
위의 이미지들처럼 뉴럴 네트워크 또한 그림과 같이 매트릭스로 한번에 구성할 수 있다.
이제 뉴럴 네트워크를 구성해, XOR의 문제를 해결하게 되었다. 그러나 문제는 해결했지만, w와 b값을 학습 시킬 수 있을까?
우선, 위의 이미지를 보면, 우리가 지금까지 본 XOR을 학습하는 과정들을 간단히 텐서플로우로 구현할 수 있다. K(x)는 1번째 Layer(Input Layer)에서 나온 값이다. 그 값을 다음 Layer(Output Layer)에 그대로 입력 값으로 대입해주면, 우리가 원하는 뉴럴 네트워크를 구성할 수 있다.
강의-2
강의를 하기 전에 김성훈 교수님께서는 미분에 대한 기본 동영상을 미리 감상하길 권한다.
동영상 내용을 간단히 정리하면, 미분이란, 순간 변화 값이다.
고등학교 때 배운 lim을 자세히 보면 델타x가 0으로 간다고 되어있다. 그래서 델타x를 임의의 값 0과 가까운 0.01로 잡고 각 함수들에 대입하는 이미지이다.
f(x) = 3, 인 경우는 모든 값(x)에 3이다. 그래서 결국 0/0.01이 되어 0이 된다.
f(x) = x, 인 경우는 입력과 출력이 같다. 그래서 x + 0.01 – x / 0.01이 되어 1이 된다.
f(x) = 2x, 인 경우는 출력이 입력의 2배이다. 그래서 2x + 0.02 – 2x / 0.01 이 되어 2가 된다.
위의 이미지에서 5개의 함수가 있다. 1,2,3 번째는 기존에 보았던 형태이고, 4,5번째는 못봤던 형태이기 때문에, 간략히 설명하면 4번째 함수는 x로 미분을 하는 것이다 그래서 af/ax로 표현되고 5번째 함수는 y로 미분한다는 뜻으로, af/ay로 표현된다.
그리고 오른쪽은 체인 미분에 대해서 설명하는 그림인데. f(g(x))는 어떻게 미분을 할까?
우선 안쪽 g(x)부터 x로 미분(ag/ax)한 다음, f(g(x))를 g로 미분(af/ag) 하면 af/ax = af/ag*ag/ax와 같이 나타낼 수 있다.
강의-3
이번 강의는 미분 특별 강의 때문에 처음으로 3강까지 나누게 되었다.
이번 강의는 뉴럴 네트워크에서 w와 b는 어떻게 학습을 시키는지에 대해 다룬다.
우리가 모델을 학습시키는 목적은 Cost함수를 적게 만드는 w와 b값을 찾는 것이다.
Minsky 교수님께서 말씀하신 w와 b를 학습시키는 방법은 위의 Back-propagation알고리즘을 사용함으로 해결할 수 있다. 간단히 Propagation은 앞에서 뒤로 w와 b를 조절하는 것이고, 반대방향으로 w와 b값을 조절하는 것이 Back-propagation이다.
이제부터 왜 김성훈 교수님이 미분 특강을 했는지 알 수 있는 부분이다. 어떻게 Back propagation으로 이전 값들을 추적할 수 있을까? 우리는 오퍼레이션(+,-,*,/)을 알 수 있기 때문이다. 더 자세히 말하면, 체인 미분을 통해 해결할 수 있다.
w=-2, x=5, b=3이라고 가정했을 때, 우리는 g=wx값과 f=g+b값을 구할 수 있다.
이 부분은 Propagatation이다.
우선 각각의 함수들을 미분한다.
ag/aw = x, ag/ax = w, af/ag = 1, af/ab = 1
이걸 통해서 우리는 af/aw, af/ax, af/ab를 구할 수 있다.
af/aw = af/ag*ag/aw = 5
af/ax = af/ag*ag/ax = -2
af/ab = 1
이다.
이런 식으로 우리는 w와 x 값들을 바꿀 수 있고,
이런 방식으로 복잡한 Sigmoid 또한 구할 수 있다.
이제 왜 텐서플로우가 이미지와 같은 그래프 모양이 되었는지 알 수 있을 것 같다.
Lab-1
그림과 같은 XOR을 Logistic regression으로 구현해보자.
import tensorflow as tf
import numpy as np
x_data = np.array([[0,
0], [0, 1], [1, 0], [1, 1]], dtype=np.float32)
y_data = np.array([[0], [1], [1],
[0]], dtype=np.float32)
X = tf.placeholder(tf.float32)
Y = tf.placeholder(tf.float32)
W = tf.Variable(tf.random_normal([2, 1]), name='weight')
b = tf.Variable(tf.random_normal([1]), name='bias')
hypothesis = tf.sigmoid(tf.matmul(X, W) + b)
cost = -tf.reduce_mean(Y * tf.log(hypothesis) + (1
- Y) * tf.log(1
- hypothesis))
train = tf.train.GradientDescentOptimizer(learning_rate=0.1).minimize(cost)
predicted = tf.cast(hypothesis > 0.5, dtype=tf.float32)
accuracy = tf.reduce_mean(tf.cast(tf.equal(predicted,
Y), dtype=tf.float32))
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for
step in
range(10001):
sess.run(train, feed_dict={X:
x_data, Y:
y_data})
if
step % 100
== 0:
print(step, sess.run(cost, feed_dict={X:
x_data, Y:
y_data}), sess.run(W))
hypothesis_,
predicted_, accuracy_ = sess.run([hypothesis,
predicted, accuracy], feed_dict={X: x_data, Y:
y_data})
print("\nHypothesis: ", hypothesis_, "\nCorrect: ",
predicted_, "\nAccuracy:
", accuracy_)
소스는 위와 같고,
결과값은 위와 같다. 10000번이나 돌렸음에도 불구하고, 정확도가 0.5밖에 안된다. 더 많이 돌려도 결과는 똑같을 것이다. 이전 강의에서 설명했듯이, XOR은 Layer를 2개 이상 사용하는 뉴럴 네트워크를 사용해야 해결할 수 있기 때문이다.
그렇다면 뉴럴 네트워크는 어떻게 사용하면 될까?
import tensorflow as tf
import numpy as np
x_data = np.array([[0,
0], [0, 1], [1, 0], [1, 1]], dtype=np.float32)
y_data = np.array([[0], [1], [1],
[0]], dtype=np.float32)
X = tf.placeholder(tf.float32)
Y = tf.placeholder(tf.float32)
W1 = tf.Variable(tf.random_normal([2, 2]), name='weight1')
b1 = tf.Variable(tf.random_normal([2]), name='bias1')
L1 = tf.sigmoid(tf.matmul(X, W1) + b1)
W2 = tf.Variable(tf.random_normal([2, 1]), name='weight2')
b2 = tf.Variable(tf.random_normal([1]), name='bias2')
hypothesis = tf.sigmoid(tf.matmul(L1, W2) + b2)
cost = -tf.reduce_mean(Y * tf.log(hypothesis) + (1
- Y) * tf.log(1
- hypothesis))
train = tf.train.GradientDescentOptimizer(learning_rate=0.1).minimize(cost)
predicted = tf.cast(hypothesis > 0.5, dtype=tf.float32)
accuracy = tf.reduce_mean(tf.cast(tf.equal(predicted,
Y), dtype=tf.float32))
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for
step in
range(10001):
sess.run(train, feed_dict={X:
x_data, Y:
y_data})
if
step % 100
== 0:
print(step, sess.run(cost, feed_dict={X:
x_data, Y:
y_data}), sess.run(W1))
hypothesis_,
predicted_, accuracy_ = sess.run([hypothesis,
predicted, accuracy], feed_dict={X: x_data, Y:
y_data})
print("\nHypothesis: ", hypothesis_, "\nCorrect: ",
predicted_, "\nAccuracy:
", accuracy_)
위의 소스가 뉴럴네트워크를 구성한 부분이다.
기존의 소스과 똑같으나 유의해서 볼 부분은 L1과 W2, b2부분이다. L1은 Layer1(Input Layer)을 나타내고 다음에 나오는 hypothesis가 Layer2(Output Layer)를 나타낸다.
위의 소스 일부만 수정했음에도 불구하고, 50% 정확도에서 100%로 변경되었다.
위의 이미지처럼 출력 값을 증가시켜 다음 Layer의 입력 값이 많아지도록 하는 것이 Wide 뉴럴 네트워크 이다.
그리고 그림처럼 Layer를 많이 만드는 것이 Deep 뉴럴 네트워크 이다. Wide하거나 Deep하게 학습을 시키면 Cost 값이 대부분 잘 떨어진다. 그러나 너무 잘 맞게 학습되어 Overfitting현상이 생길 수도 있다.
Lab-2
이번 강의에서 배울 내용은 텐서보드이다. 텐서플로우가 동작하는 내용을 시각화하여 보여주는 툴이라고 생각한다.
왼쪽은 기존에 사용하던 Console방식이고, 오른쪽은 텐서보드를 이용한 이미지이다. 텐서보드를 사용한 게 훨씬 한눈에 파악하기 쉬워 보인다.
위의 그림과 같이 5 Step만 지키면 텐서보드를 사용할 수 있다.
import tensorflow as tf
import numpy as np
x_data = np.array([[0,
0], [0, 1], [1, 0], [1, 1]], dtype=np.float32)
y_data = np.array([[0], [1], [1],
[0]], dtype=np.float32)
X = tf.placeholder(tf.float32)
Y = tf.placeholder(tf.float32)
with tf.name_scope("layer1") as scope:
W1 = tf.Variable(tf.random_normal([2, 2]), name='weight1')
b1 = tf.Variable(tf.random_normal([2]),
name='bias1')
L1 = tf.sigmoid(tf.matmul(X, W1) + b1)
# 텐서보드 Layer1
구성
w1_hist
= tf.summary.histogram("weights1", W1)
b1_hist = tf.summary.histogram("biases1", b1)
layer1_hist = tf.summary.histogram("layer1", L1)
with tf.name_scope("lyaer2") as scope:
W2 = tf.Variable(tf.random_normal([2, 1]), name='weight2')
b2 = tf.Variable(tf.random_normal([1]),
name='bias2')
hypothesis = tf.sigmoid(tf.matmul(L1, W2) + b2)
# 텐서보드 Layer2
구성
w2_hist
= tf.summary.histogram("weights2", W2)
b2_hist = tf.summary.histogram("biases2", b2)
hypothesis_hist =
tf.summary.histogram("hypothesis", hypothesis)
cost = -tf.reduce_mean(Y * tf.log(hypothesis) + (1
- Y) * tf.log(1
- hypothesis))
train = tf.train.GradientDescentOptimizer(learning_rate=0.1).minimize(cost)
predicted = tf.cast(hypothesis > 0.5, dtype=tf.float32)
accuracy = tf.reduce_mean(tf.cast(tf.equal(predicted,
Y), dtype=tf.float32))
# 텐서보드 Scalar 입력
cost_summ = tf.summary.scalar("cost", cost)
summary = tf.summary.merge_all()
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
writer = tf.summary.FileWriter("./logs/xor_logs")
writer.add_graph(sess.graph)
for
step in
range(10001):
s,
_ = sess.run([summary,
train], feed_dict={X: x_data, Y: y_data})
writer.add_summary(s, global_step=step)
if
step % 100
== 0:
print(step, sess.run(cost, feed_dict={X:
x_data, Y:
y_data}), sess.run(W1))
hypothesis_,
predicted_, accuracy_ = sess.run([hypothesis,
predicted, accuracy], feed_dict={X: x_data, Y:
y_data})
print("\nHypothesis: ", hypothesis_, "\nCorrect: ",
predicted_, "\nAccuracy:
", accuracy_)
주석으로 설명은 대체하겠다.
위의 그림과 같이 입력을 하면, TensorBoard를 볼 수 있는 서버가 열린다. 기본포트는 6006이다.
텐서보드를 통해 볼 수 있는 이미지들이다. 물론 더 많은 그래프 또한 볼 수 있고, 마우스를 갖다 대면 더 상세한 내용을 볼 수 있다.
교수님께서 하나의 팁이라고 Remote로 텐서보드에 접근하는 방법에 대해서도 알려주신다. 위의 이미지대로 적용하면, 기본 Port를 변경하고 Remote로 텐서보드를 동작시킬 수 있다.
교수님은 다음과 같이 2개(또는 이상)을 학습시키며, Cost함수를 비교 또한 할 수 있다고 말씀하셨다. Log파일을 작성하는 부분은 각각 상위 폴더(logs)만 동일하게 설정 후, 하위 폴더를 따로둔 다음, 텐서보드를 실행할 때는 상위폴더로 디렉토리 옵션 설정을하면, 위의 이미지와 같이 비교가 가능하다.
'AI > Tensorflow' 카테고리의 다른 글
[모두의딥러닝] Convolutional Neural Networks (0) | 2017.09.04 |
---|---|
[모두의딥러닝] Neural Network 2: ReLU and 초기값 정하기 (2006/2007 breakthrough) (0) | 2017.09.04 |
[모두의딥러닝] 딥러닝의 기본 개념과, 문제, 그리고 해결 (0) | 2017.09.03 |
[모두의딥러닝] ML의 실용과 몇가지 팁 (0) | 2017.08.23 |
[모두의딥러닝] Softmax Regression (Multinomial Logistic Regression) (0) | 2017.08.23 |
- Docker
- Configuration
- tensorflow
- BigData
- AWS
- Gradle
- Error
- 머신러닝
- 중앙정보처리학원
- TDD
- serverless
- API
- executor
- 텐서플로우
- 파이썬
- javascript
- spark
- AI
- Maven
- memory
- python
- NIO
- mysql
- spring
- web
- 모두의딥러닝
- 점프투파이썬
- Java
- mybatis
- ML
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |