AI/밑바닥부터 시작하는 딥러닝

[밑바닥부터 시작하는 딥러닝] 파이썬으로 신경망 순전파 구현하기 (Neural Network forward propagation in python)

슈퍼짱짱 2019. 9. 16. 08:00
반응형

지난 포스팅에서는 신경망과 활성화 함수에 대해 알아보았다.


>> 신경망이란? 바로가기

>> 활성화함수란? 바로가기


이번에는 파이썬에서 3층으로 이루어진 신경망의 순방향(입력부터 출력까지)을 구현하는 방법에 대해 알아보겠다.




파이썬으로 뉴럴 네트워크 Feed Forward 구현하기


다음과 같은 3층 신경망을 구현하겠다.

input layer (0층)는 2개, 첫 번째 hidden layer (1층)는 3개, 두 번째 hidden layer (2층)는 2개, output layer (3층)는 2개의 노드로 구성된다.


1. 0층 -> 1층


입력층 (0층) 에서 첫 번째 은닉층 (1층) 으로 가는 신호는 다음과 같다.

a1을 식으로 나타내면 다음과 같다.

이를 다시 일반화 하면 다음과 같다.


즉, input layer -> 1st hidden layer의 과정 전체를 일반화하면 다음과 같다.


이때, W의 차원이 헷갈린다면, 입력층과 출력층의 차원을 참고하면 된다.

입력층 X의 dimension이 1X2, 출력층이 1X3이기 때문에 W는 2X3이어야 한다.

행렬의 곱셈에서 차원은 (1X2) * (2X3) = (1X3) 이기 때문이다.


이 과정을 python에서 구현하면 다음과 같다.


1
2
3
4
5
6
7
import numpy as np
 
= np.array([1.00.5])
W1 = np.array([[0.10.30.5],[0.20.40.6]])
B1 = np.array([0.10.20.3])
 
A1 = np.dot(X, W1) + B1
cs


여기에 sigmoid 활성화함수를 적용하면 다음과 같다.


1
2
3
4
def sigmoid(x):
    return 1/(1+np.exp(-x))
 
Z1 = sigmoid(A1)
cs


>> print(A1)

[0.3 0.7 1.1]


>> print(Z1)

[0.57444252 0.66818777 0.75026011]



2. 1층 -> 2층


첫 번째 은닉층에서 두 번째 은닉층으로의 전달도 같은 과정으로 이루어진다.

단, 앞서 첫 번째 은닉층의 출력값이 새 입력값이 된다. 즉, 코드상으로 X자리에 Z1이 온다.


1
2
3
4
5
W2 = np.array([[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]])
B2 = np.array([0.1, 0.2])
 
A2 = np.dot(Z1, W2) + B2
Z2 = sigmoid(A2)
cs


>> print(A2)

[0.51615984, 1.21402696]


>> print(Z2)

[0.62624937, 0.7710107 ]


3. 2층 -> 3층


두 번째 은닉층에서 출력층의 전달도 같은 과정으로 이루어지나, 마지막 출력의 형태는 정의에 따라 다를 수 있다.

일반적으로 마지막에는 활성화함수를 적용하지 않으며, 분류문제라면 softmax를 적용하지만, 우선은 softmax를 적용하지 않은 형태로 구현한다.


1
2
3
4
5
6
7
8
def identity_function(x):
    return x
 
W3 = np.array([[0.10.3], [0.20.4]])
B3 = np.array([0.10.2])
 
A3 = np.dot(Z2, W3) + B3
= identity_function(A3)
cs


>> print(Y)

[0.31682708, 0.69627909]


4. 3층 신경망 구현 (3-layer Neural Network Feed Forward in python)


앞서 구현했던 것들을 하나로 함쳐서 정리하면 다음과 같다.


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
32
33
def sigmoid(x):
    return 1/(1+np.exp(-x))
 
def identity_function(x):
    return x
 
def init_network():
    network = {}
    network['W1'= np.array([[0.10.30.5], [0.20.40.6]])
    network['b1'= np.array([0.10.20.3])
    network['W2'= np.array([[0.10.4], [0.20.5], [0.30.6]])
    network['b2'= np.array([0.10.2])
    network['W3'= np.array([[0.10.3], [0.20.4]])
    network['b3'= np.array([0.10.2])
    
    return network
 
def forword(network, x):
    W1, W2, W3 = network['W1'], network['W2'], network['W3']
    b1, b2, b3 = network['b1'], network['b2'], network['b3']
    
    a1 = np.dot(x, W1) + b1
    z1 = sigmoid(a1)
    a2 = np.dot(z1, W2) + b2
    z2 = sigmoid(a2)
    a3 = np.dot(z2, W3) + b3
    y = identity_function(a3)
    
    return y
 
network = init_network()
= np.array([1.00.5])
= forword(network, x)
cs


>> print(y)

[0.31682708 0.69627909]




본 포스팅에서는 정해진 W, b로 뉴럴 네트워크의 입력부터 출력까지의 과정을 알아보았다.

마지막 output layer에서 identity_function()을 정의했다. 사실 output layer는 네트워크의 목적에 따라 다른 function이 정의될 수있다. 예를들어 일반 회귀(regression)에서는 identity_function()을, 분류(classification)문제에서는 softmax를 사용한다. 이는 다음 포스팅에서 알아보겠다.


또한, 사실 뉴럴 네트워크는 back propagation(역전파)을 통해 W와 b를 스스로 학습한다. back propagation에 대해서는 더 후에 알아보도록 하겠다.



반응형