1. 퍼셉트론(Perceptron)이란?
: 프랑크 로젠블라트가 1957년에 고안한 알고리즘으로 Neural-Network(신경망)의 기원이 되는 알고리즘.
: 가장 오래되고 단순한 형태의 판별 함수 기반 예측 모형(discriminant function based predition model) 중 하나
: 퍼셉트론은 다수의 신호를 받아(input) 하나의 신호(0 또는 1)로 출력(output).
Perceptron Example
x1, x2라는 신호 입력이 y라는 신호로 출력이 되는 과정 자체가 퍼셉트론입니다.
이때 각 입력신호(x1,x2)는 weight(w1,w2)가 곱해지게 됩니다.
** 동그라미를 뉴런 혹은 노드라고 말한다.
1) Weight(가중치), Bias(편향치), Theta(임계점)
: 입력 신호는 각 weight와 곱해져 w1*x1 + w2*x2가 되고, 이 값에 bias(b)가 더해져 w1*x1 + w2*x2 + b가 된다.
: 여러 입력신호가 하나의 신호로 출력되어야 하기 때문에 bias는 뉴런(위 그림에서 동그라미를 의미)당 1개씩 더해진다.
: 또한 출력값이 0 또는 1로 출력되어야 하기때문에 w1*x1 + w2*x2 + b를 0 또는 1로 만들어줘야한다.
: 이때 사용하는 개념이 임계점(Theta)이고, w1*x1 + w2*x2 + b이 설정해놓은 임계점을 기준으로 0 또는 1로 바뀐다.
: 예를 들어, 'w1*x1 + w2*x2 + b < theta이면 0, w1*x1 + w2*x2 + b > theta이면 1' 이런식으로!!
2. 단순 논리회로(AND, OR, NAND)
x1 |
x2 |
y : AND |
y : OR | y : NAND |
0 |
0 |
0 |
0 | 1 |
1 |
0 |
0 |
1 | 1 |
0 |
1 |
0 |
1 | 1 |
1 |
1 |
1 |
1 | 0 |
AND : 입력이 모두 1인 경우에만, 1을 출력(나머지 경우엔 0을 출력)
def AND(x1, x2): x = np.array([x1, x2]) w = np.array([0.5, 0.5]) b = -0.7 tmp = np.sum(w*x) + b if tmp <= 0: return 0 else: return 1
OR : 입력중 하나 이상이 1인 경우, 1을 출력(모두 0이면 0을 출력)
# OR 구현 def OR(x1, x2): """ AND와 weights와 bias만 다르다 """ x = np.array([x1, x2]) w = np.array([0.5, 0.5]) b = -0.2 tmp = np.sum(w*x) + b if tmp <= 0: return 0 else: return 1
NAND : AND와 반대, 모두 1인 경우 0출력 출력(나머지 경우엔 1을 출력)
# NAND 구현 def NAND(x1, x2): """ AND와 weights와 bias만 다르다 """ x = np.array([x1, x2]) w = np.array([-0.5, -0.5]) b = 0.7 tmp = np.sum(w*x) + b if tmp <= 0: return 0 else: return 1
(위 그림의 직선 : w1*x1 + w2*x2 + b)
AND/NAND, OR은 해당 직선(판별함수라도도 할 수 있음)으로 두 영역(black, white)을 구분할 수 있다
3. 한계점 : XOR 문제
x1 |
x2 |
y : XOR |
0 |
0 |
0 |
1 |
0 |
1 |
0 |
1 |
1 |
1 |
1 |
0 |
XOR : OR의 반대가 아니다!!! 입력값 모두 1인 경우만 1을 출력(나머지 경우엔 0을 출력)
직선(w1*x1 + w2*x2 + b)으로 black/white 두 영역으로 나눌 수가 없다....
Python코드를 예를 들어보면,
np.random.seed(0) X_xor = np.random.randn(200, 2) y_xor = np.logical_xor(X_xor[:, 0] > 0, X_xor[:, 1] > 0) y_xor = np.where(y_xor, 1, -1) plt.scatter(X_xor[y_xor==1, 0], X_xor[y_xor==1, 1], c='b', marker='o', label='1', s=100) plt.scatter(X_xor[y_xor==-1, 0], X_xor[y_xor==-1, 1], c='r', marker='s', label='-1', s=100) plt.ylim(-3.0) plt.legend() plt.title("XOR problem") plt.show()
3.1 해결책 : 다층 퍼셉트론(Multi-Layer Perceptron)
이 XOR 문제를 해결하기 위해 퍼셉트론 두 개를 이어 붙여 해결할 수 있다.
이것을 '층을 쌓는다'라 하며,
이렇게 만들어진 퍼셉트론을 다층 퍼셉트론(Multi-Layer Perceptron)이라 한다..
# XOR 구현 # AND, NAND, OR 조합하여 구현하기 def XOR(x1, x2): """ 다층 구조를 가진 다층 퍼셉트론 """ s1 = NAND(x1,x2) # 1층 s2 = OR(x1,x2) # 1층 y = AND(s1,s2) # 2층 return y
Tensorflow로 다층 퍼셉트론(MLP)를 만들어보자.
: Tensorflow로 MNIST데이터를 분류하는 MLP를 만들어보자!
: 코드 위주로 설명 진행.
0. Data Load
import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('data/', one_hot=True)
1. Parameter Setting
이미지 데이터 1개가 28x28(흑백)으로 구성되어있는데,
위처럼 데이터를 불러오면 28x28=784로 한줄로 펴진 vector로 온다.
그래서 n_input이 784인 것이다.
n_input = 784 n_hidden_1 = 256 n_hidden_2 = 128 n_classes = 10 # set input and output x = tf.placeholder(dtype='float', shape=[None, n_input]) y = tf.placeholder(dtype='float', shape=[None, n_classes]) # set network parameters(weights, biases) stddev = 0.1 weights = { # 가중치의 초기값은 # 평균 : 0(default), 표준편차 : 0.1 인 정규분포에서 random으로 뽑는다 # hidden layer1의 노드 수는 256개, hidden layer2의 노드 수는 128개 # out layer의 노드 수 = label 갯수 = 10개(0~9, 숫자 10개) 'h1' : tf.Variable(initial_value=tf.random_normal(shape=[n_input, n_hidden_1],stddev=stddev)), # 784 x 256 matrix 'h2' : tf.Variable(initial_value=tf.random_normal(shape=[n_hidden_1, n_hidden_2], stddev=stddev)), # 256 x 128 matrix 'out' : tf.Variable(initial_value=tf.random_normal(shape=[n_hidden_2, n_classes], stddev=stddev)), # 128 x 10 matrix } biases = { 'b1' : tf.Variable(initial_value=tf.random_normal(shape=[n_hidden_1])), # 256개 'b2' : tf.Variable(initial_value=tf.random_normal(shape=[n_hidden_2])), 'out' : tf.Variable(initial_value=tf.random_normal(shape=[n_classes])), } print("Network Ready!!!")
2. Define Graph
multilayer_perceptron 함수에서 최종 출력값을 logit(Wx+b 형태)으로 뽑고,
이를 Cross Entropy에 적용
→ tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels=y, logits=pred))
# model def multilayer_perceptron(_x, _weights, _biases): layer_1 = tf.nn.sigmoid(tf.add(tf.matmul(_x, _weights['h1']), _biases['b1'])) # 1번째 layer 통과 layer_2 = tf.nn.sigmoid(tf.add(tf.matmul(layer_1, _weights['h2']), _biases['b2'])) # 2번째 layer 통과 # return은 logit을 뽑아야 한다.(softmax 취하기 전 형태) # softmax취해서 return하면 성능 떨어짐... return (tf.matmul(layer_2, _weights['out']) + _biases['out']) # prediction pred = multilayer_perceptron(x, weights, biases) # Loss and Optimizer cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels=y, logits=pred)) optimizer = tf.train.AdamOptimizer(learning_rate=0.001).minimize(cost) correct = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1)) accuracy = tf.reduce_mean(tf.cast(correct, 'float')) # Initialize init = tf.global_variables_initializer() print("Function Ready!!!")
3. Run
training_epochs = 20 batch_size = 100 display_step = 4 # Launch the Graph sess = tf.Session() sess.run(init) # Optimize for epoch in range(training_epochs): avg_cost = 0 total_batch = int(mnist.train.num_examples / batch_size) # Iteration for i in range(total_batch): batch_xs, batch_ys = mnist.train.next_batch(batch_size=batch_size) feeds = {x: batch_xs, y: batch_ys} sess.run(optimizer, feed_dict=feeds) avg_cost += sess.run(cost, feed_dict=feeds) avg_cost = avg_cost / total_batch # Display if (epoch+1) % display_step == 0: print("Epoch: %03d/%03d cost: %.9f" % (epoch, training_epochs, avg_cost)) feeds = {x: batch_xs, y: batch_ys} train_acc = sess.run(accuracy, feed_dict=feeds) print("Train Accuracy: %.3f" % (train_acc)) feeds = {x: mnist.test.images, y: mnist.test.labels} test_acc = sess.run(accuracy, feed_dict=feeds) print("Test Accuracy: %.3f" % (test_acc)) print("Optimization Finished!!")
출력: Epoch: 003/020 cost: 0.119634462 Train Accuracy: 0.980
Test Accuracy: 0.964
Epoch: 007/020 cost: 0.047141746
Train Accuracy: 0.990
Test Accuracy: 0.975
Epoch: 011/020 cost: 0.018645706
Train Accuracy: 1.000
Test Accuracy: 0.977
Epoch: 015/020 cost: 0.006685954
Train Accuracy: 1.000
Test Accuracy: 0.981
Epoch: 019/020 cost: 0.002408720
Train Accuracy: 1.000
Test Accuracy: 0.979
Optimization Finished!! |
Activation Function을 ReLU로 바꿔보자
1. Parameter Setting
n_input = 784 n_hidden_1 = 256 n_hidden_2 = 128 n_hidden_3 = 64 n_classes = 10 # set input and output x = tf.placeholder(dtype='float', shape=[None, n_input]) y = tf.placeholder(dtype='float', shape=[None, n_classes]) # set network parameters(weights, biases) stddev = 0.1 weights = { 'h1' : tf.Variable(initial_value=tf.random_normal(shape=[n_input, n_hidden_1],stddev=stddev)), 'h2' : tf.Variable(initial_value=tf.random_normal(shape=[n_hidden_1, n_hidden_2], stddev=stddev)), 'h3' : tf.Variable(initial_value=tf.random_normal(shape=[n_hidden_2, n_hidden_3], stddev=stddev)), 'out' : tf.Variable(initial_value=tf.random_normal(shape=[n_hidden_3, n_classes], stddev=stddev)), } biases = { 'b1' : tf.Variable(initial_value=tf.random_normal(shape=[n_hidden_1])), 'b2' : tf.Variable(initial_value=tf.random_normal(shape=[n_hidden_2])), 'b3' : tf.Variable(initial_value=tf.random_normal(shape=[n_hidden_3])), 'out' : tf.Variable(initial_value=tf.random_normal(shape=[n_classes])), } print("Network Ready!!!")
2. Define Graph
# model def multilayer_perceptron(_x, _weights, _biases): layer_1 = tf.nn.relu(tf.add(tf.matmul(_x, _weights['h1']), _biases['b1'])) layer_2 = tf.nn.relu(tf.add(tf.matmul(layer_1, _weights['h2']), _biases['b2'])) layer_3 = tf.nn.relu(tf.add(tf.matmul(layer_2, _weights['h3']), _biases['b3'])) # return은 logit을 뽑아야 한다.(softmax 취하기 전 형태) # softmax취해서 return하면 성능 떨어짐... return (tf.matmul(layer_3, _weights['out']) + _biases['out']) # prediction pred = multilayer_perceptron(x, weights, biases) # Loss and Optimizer cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels=y, logits=pred)) optimizer = tf.train.AdamOptimizer(learning_rate=0.001).minimize(cost) correct = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1)) accuracy = tf.reduce_mean(tf.cast(correct, 'float')) # Initialize init = tf.global_variables_initializer() print("Function Ready!!!")
3. Run
training_epochs = 20 batch_size = 100 display_step = 4 # Launch the Graph sess = tf.Session() sess.run(init) # Optimize for epoch in range(training_epochs): avg_cost = 0 total_batch = int(mnist.train.num_examples / batch_size) # Iteration for i in range(total_batch): batch_xs, batch_ys = mnist.train.next_batch(batch_size=batch_size) feeds = {x: batch_xs, y: batch_ys} sess.run(optimizer, feed_dict=feeds) avg_cost += sess.run(cost, feed_dict=feeds) avg_cost = avg_cost / total_batch # Display if (epoch+1) % display_step == 0: print("Epoch: %03d/%03d cost: %.9f" % (epoch, training_epochs, avg_cost)) feeds = {x: batch_xs, y: batch_ys} train_acc = sess.run(accuracy, feed_dict=feeds) print("Train Accuracy: %.3f" % (train_acc)) feeds = {x: mnist.test.images, y: mnist.test.labels} test_acc = sess.run(accuracy, feed_dict=feeds) print("Test Accuracy: %.3f" % (test_acc)) print("Optimization Finished!!")
출력: Epoch: 003/020 cost: 0.040441343 Train Accuracy: 1.000
Test Accuracy: 0.974
Epoch: 007/020 cost: 0.011998331
Train Accuracy: 0.990
Test Accuracy: 0.978
Epoch: 011/020 cost: 0.004996898
Train Accuracy: 1.000
Test Accuracy: 0.979
Epoch: 015/020 cost: 0.004258974
Train Accuracy: 0.990
Test Accuracy: 0.979
Epoch: 019/020 cost: 0.002940170
Train Accuracy: 1.000
Test Accuracy: 0.978
Optimization Finished!! |
다른거 손대지 않고 Graph만 바꿔주면 된다는 것이 TensorFlow의 장점!
참고
"데이터사이언스 스쿨"
https://datascienceschool.net/view-notebook/342b8e2ecf7a4911a727e6fe97f4ab6b/
"밑바닥으로 시작하는 딥러닝"
http://www.hanbit.co.kr/store/books/look.php?p_code=B8475831198
소스코드
https://github.com/Junhojuno/DeepLearning-Beginning/blob/master/5.MLP_NumberClassifier.ipynb
'딥러닝 > 신경망 기초' 카테고리의 다른 글
Recurrent Neural Network (RNN) (0) | 2018.11.04 |
---|---|
Convolutional Neural Network(CNN) (0) | 2018.11.01 |
이미지 데이터 다루기 (0) | 2018.10.31 |
소프트맥스(Softmax) (0) | 2018.10.25 |
활성화 함수(Activation Function) (0) | 2018.10.24 |