[Deep Learning] MLP(Multi-layer perceptrons)
CS/Deep Learning

[Deep Learning] MLP(Multi-layer perceptrons)


[Deep Learning] 인공 신경망

 

순서

1. Linear regression

2. Single Layer Perceptron

3. Multi Layer Perceptron to slove XOR

 

신경망 모델

뉴런을 수학적으로 모델링 한 것. 뉴런이 다른 여러개의 뉴런으로부터 입력값을 받아서 외부로 출력값을 내보내는 것처럼, 인공신경망 모델은 여러 입력값을 받아서 일정 수준이 넘어서면 활성화되어 출력값을 내보낸다.

 

신경망 모델 학습 프로세스

  • 데이터 processing: 데이터 전처리하는 과정 (ex 784차원 --(reshape)-->28X28)
  • model 디자인: layer 종류, 개수 및 뉴런 개수 설정 + 각 layer마다의 activation function 설정
  • Loss function 설정: 결과값을 원하는 방향으로 바꿔주는 function
  • Optimizer 설정: 방향 설정시 영향을 얼마나 끼칠지 설정
  • 학습

입력값을 받아서 출력값을 내보내는 전체적인 학습 프로세스는 위와같이 이루어진다. 이제 하나하나 세부적으로 살펴보자.

 

관련 개념

  • Epoch : 전체 sample 데이터를 학습하는데 드는 시간
  • Step : 1 step당 weight와 Bias를 1회씩 업데이트 하게됨
  • Batch size: 1 step에서 사용한 데이터의 수
  • Learning rate : 경사 하강법에서 학습 단계별로 움직이는 학습 속도
  • EX) Batch Size가 100, Step이 10이면 약 1000개의 데이터를 이용

 

Linear Regression(선형 회귀)

Neural Network(NN)이 시작되기 전에는 W, b의 하나의 값만을 이용하여 Linear regression을 통해 해결이 가능하였다. 예제를 통해 풀어보자. 선형 회귀 모델에서 y = wx + b라는 식을 알수 있는데 이 간단한 식을 통하여 구현해보자. y=x라는 그래프가 있다. input = 1, 2, 3 output = 1, 2, 3을 가진다.

import tensorflow as tf

#Data processing
x_data = [1, 2, 3]
y_data = [1, 2, 3]

#Data Modeling
#1차원, -1 ~ 1 사이의 수
#hypothesis: 예측값
W = tf.Variable(tf.random_uniform([1], -1.0, 1.0))
b = tf.Variable(tf.random_uniform([1], -1.0, 1.0))

X = tf.placeholder(tf.float32, name="X")
Y = tf.placeholder(tf.float32, name="Y")

hypothesis = W * X + b

#cost 설정
cost = tf.reduce_mean(tf.square(hypothesis - Y))

#optimizer
Learning_rate = tf.Variable(0.1)
optimizer = tf.train.GradientDescentOptimizer(Learning_rate)
train_op = optimizer.minimize(cost)

#학습
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    
    for step in range(30):
        _, cost_val = sess.run([train_op, cost], feed_dict = {X : x_data, Y : y_data})
        
        print(step, cost_val, sess.run(W), sess.run(b))
        
    print("X : 6, Y: ", sess.run(hypothesis, feed_dict={X: 6}))
    print("X : 2.7, Y : ", sess.run(hypothesis, feed_dict={X : 2.7}))
    
'''RESULT
0 8.653675 [1.3083603] [-0.36245328]
1 0.12804268 [1.1655387] [-0.41330677]
2 0.025030373 [1.1763586] [-0.3968609]
3 0.02268356 [1.1705016] [-0.38803214]
4 0.021592237 [1.1665797] [-0.37862632]
5 0.020566441 [1.1625558] [-0.36953294]
6 0.019589515 [1.1586503] [-0.3606487]
7 0.018658994 [1.1548362] [-0.35197908]
8 0.01777269 [1.151114] [-0.34351775]
9 0.016928473 [1.1474813] [-0.3352598]
10 0.016124338 [1.143936] [-0.32720035]
11 0.015358425 [1.1404759] [-0.3193347]
12 0.014628902 [1.1370989] [-0.31165808]
13 0.013934019 [1.1338031] [-0.30416602]
14 0.013272133 [1.1305866] [-0.29685405]
15 0.012641695 [1.1274474] [-0.28971788]
16 0.012041208 [1.1243837] [-0.28275326]
17 0.01146924 [1.1213936] [-0.2759561]
18 0.010924436 [1.1184754] [-0.26932228]
19 0.01040552 [1.1156273] [-0.262848]
20 0.009911265 [1.1128477] [-0.2565293]
21 0.00944046 [1.110135] [-0.25036252]
22 0.008992038 [1.1074873] [-0.244344]
23 0.008564915 [1.1049033] [-0.23847014]
24 0.008158076 [1.1023816] [-0.23273747]
25 0.0077705444 [1.0999205] [-0.2271426]
26 0.0074014473 [1.0975184] [-0.2216823]
27 0.0070498767 [1.0951742] [-0.21635321]
28 0.0067149955 [1.0928862] [-0.21115224]
29 0.006396031 [1.0906533] [-0.20607628]
X : 6, Y:  [6.3378434]
X : 2.7, Y :  [2.7386875]
'''

위에서 언급했던 학습과정대로 코드가 진행된다.

(여기서 출력되는 const_val값이 높을 수록 우리가 원하는 값과 다르다.)

 

 

활성화 함수(Activation Function)

 

자세히 보기 : 활성화 함수(Activation function)

 

Cost function(손실 함수)

 

자세히 보기 : 손실 함수(Cost function)

 

Optimizer(최적화 함수)

GradientDescentOptimizer를 사용해서 손실값을 최소화하는 최적화 수행

0.001은 learning rate

optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001).minimize(cost)

 

퍼셉트론(Perceptron)

 오늘날 인공신경망에서 이용하는 구조이다. 퍼셉트론은 인공 신경망으로 다수의 입력으로부터 하나의 결과를 내보내는 알고리즘이다. 퍼셉트론은 실제 뇌를 구성하는 신경 세포 뉴런의 동작과 유사하다.

 

 처음에는 입력과 가중치들의 곱을 모두 더한 뒤 활성화 함수를 적용해서 그 값이 0보다 크면 1, 0보다 작으면 -1을 출력하는 선형분류기 구조였다. 그러나 이런 선형 분류기 구조는 OR와 AND와 같은 분류는 할수 있으나 XOR 분류를 수행할 수 없었다. 이것이 밝혀지고 난 후, 인공지능에 대한 모든 투자와 연구가 중단된 시기인 '인공지능 겨울'이 시작되었다.

 

 이후에 한계를 극복할 수 있는 방법이 제시되었는데, 그것이 바로 다층 퍼셉트론(MLP, Multi-Layer Perceptron)이다. 퍼셉트론을 여러 layer로 쌓으면 XOR문제를 해결할 수 있다. 하지만 퍼셉트론을 여러 층으로 쌓을 수록 학습하기가 어려운 문제가 발생했는데, 이 문제도 역전파 알고리즘(Backpropagation Algorithm)으로 해결이 된다. 역전파 알고리즘은 순방향 연산 후 예측값과 정답 사이의 오차를 후방으로 다시 보내주면서 학습시키는 방법이다.

그럼 이제 단층 퍼셉트론과 다층 퍼셉으론으로 각각 AND, XOR 문제를 풀어보자.

 

 

AND 문제

Single Layer Perceptron

AND문제는 single layer perceptron으로 풀수 있는 문제다. 

1) 학습 데이터 제시

x_data = [[0, 0], [0, 1], [1, 0], [1, 1]]
y_data = [[0], [0], [0], [1]]

 

2) 가중치, 바이어스 초기화 및 변수 placeholder 설정

X = tf.placeholder(tf.float32, [None, 2])
Y = tf.placeholder(tf.float32, [None, 1])

W = tf.Variable(tf.random_uniform([2, 1], -1.0, 1.0))
b = tf.Variable(tf.random_uniform([1], -1.0, 1.0))

 

 

여기서 변수별로 차원을 맞춰주는게 중요하다.

y = Wx + b를 보면 실제로 계산시에는 y = xW + b로 계산하게 되는데

x가 [1, 2] W가 [2, 1] b가 [1, 1]이므로 최종 y는 [1, 1]이 된다.

 

3) 학습 데이터에 대한 출력값 계산 및 activation function 적용

logits = tf.add(tf.matmul(X, W), b)
output = tf.nn.sigmoid(logits)

여기서 활성화 함수는 sigmoid함수 사용

 

4) cost 함수 설정 및 optimizer 설정

cost = tf.reduce_mean(tf.square(output - Y))
opt = tf.train.GradientDescentOptimizer(Learning_rate=0.1)
train_op = opt.minimize(cost)

 

5) 학습

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    
    for step in range(100):
        for x, y in zip(x_data, y_data):
            _, cost_val = sess.run([train_op, cost], feed_dict = {X:[x], Y:[y]})
        print(step, cost_val, sess.run(W), sess.run(b))

 

 

XOR 문제

input 1 input 2 output
0 0 0
0 1 1
1 0 1
1 1 0

XOR문제는 Neural Network를 시작시킨 문제라고 해도 과언이 아니다. single layer perceptron으로는 구현할수 없기 때문이다. 따라서 Multi layer perceptron으로 풀어야한다. single layer perceptron에서 layer를 하나더 만들어서 나온 결과 값을 새로운 layer의 입력 값으로 넣는 과정을 통해 최종 결과 값을 도출해 낸다.

 

따라서 layer를 하나더 만들어 주면되는데

첫번째 레이어부터 생각해보자.

layer1 = x * W1 + b1이다.

여기서 x는 1*2행렬이고 W1은 2*3행렬이고 b1은 1*3 행렬이다.

따라서 layer1은 1*3이다.

 

두번째 레이어에서는

output = layer1 * W2 + b2이다.

여기서 layer1은 1*3이고 W2는 3*1이고 b2는 1*1이므로

최종 output은 1*1이 된다.

 

Single layer perceptron에서 Multi layer perceptron는 layer가 하나 더 추가되므로

Model Design을 할때 layer를 추가해주면된다.

W1 = tf.Variable(tf.random_uniform([2,2], -1.0, 1.0))
b1 = tf.Variable(tf.random_uniform([2], -1.0, 1.0))
layer1 = tf.nn.sigmoid(tf.matmul(X, W1) + b1)

W2 = tf.Variable(tf.random_uniform([2,1], -1.0, 1.0))
b2 = tf.Variable(tf.random_uniform([1], -1.0, 1.0))
output = tf.nn.sigmoid(tf.matmul(layer1, W2) + b2)

따라서 위와 같다.

 

최종 코드는 아래와 같다.

import tensorflow as tf

x_data = [[0, 0], [0, 1], [1, 0], [1, 1]]
y_data = [[0], [1], [1], [0]]

X = tf.placeholder(tf.float32, [None, 2])
Y = tf.placeholder(tf.float32, [None, 1])

W1 = tf.Variable(tf.random_uniform([2,3], -1.0, 1.0))
b1 = tf.Variable(tf.random_uniform([3], -1.0, 1.0))
layer1 = tf.nn.sigmoid(tf.matmul(X, W1) + b1)

W2 = tf.Variable(tf.random_uniform([3,1], -1.0, 1.0))
b2 = tf.Variable(tf.random_uniform([1], -1.0, 1.0))
output = tf.nn.sigmoid(tf.matmul(layer1, W2) + b2)

cost = tf.reduce_mean(tf.square(output - Y))
opt = tf.train.GradientDescentOptimizer(0.1)
train_op = opt.minimize(cost)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    
    for step in range(10000):
        for x, y in zip(x_data, y_data):
            _, cost_val = sess.run([train_op, cost], feed_dict = {X:[x], Y:[y]})
    print(sess.run(output, feed_dict={X:x_data}))      
    
'''RESULT
[[0.02951288]
 [0.97240365]
 [0.96656513]
 [0.02604762]]
 '''

 

 

참고자료

 

https://brunch.co.kr/@gdhan/6

728x90
반응형