티스토리 뷰

모두의 딥러닝

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) 동일하게 설정 , 하위 폴더를 따로둔 다음, 텐서보드를 실행할 때는 상위폴더로 디렉토리 옵션 설정을하면, 위의 이미지와 같이 비교가 가능하다.

댓글
공지사항
최근에 올라온 글
링크
«   2024/05   »
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
글 보관함