3.3 다차원 배열

 

간단하게 고등학교에서 배운 행렬의 내적 연산에 대해서 다룬다. 

기억할 부분은 행렬 A, B를 내적하는 메소드가

np.dot(A, B)

라는 것이다. 내적이 영어로 dot product이므로, 단순히 dot으로 사용한다. 마찬가지로 외적을 하고 싶다면 np.cross로 

 

3.4  3층신경망 구현하기

2개의 입력층, 은닉층 2층이 각각 3개와 2개, 출력층은 2개의 뉴런으로 구성

입력층에서 1층으로 신호전달

수식을 통해서 다음과 같이 표현 할 수 있다. 

import numpy as np

X=np.array([1.0, 0.5])
W1=np.array([[0.1,0.3,0.5],[0.2,0.4,0.6]])
B1=np.array([0.1,0.2,0.3])

print(W1.shape) #(2,3)
print(X.shape) #(2,)
print(B1.shape) #(3,)

A1=np.dot(X,W1)+B1
print(A1)

이를 코드로 옮기면 다음과 같다. 값은 임의로 설정하였다.

주의 할 점은 1 x n 꼴의 행렬은 (1, n)이 아니라 (n, )으로 표현된다는 것이다.

 

이제 위 그림의 활성화 함수 h( )를 적용해보자, 활성화 함수는 sigmoid 함수를 사용할 것이다.

Z1=sigmoid(A1)
print(Z1)

이전 게시물에 만들어 놓은 것을 참고해보자

 

 

1층에서 2층으로 신호전달

 

W2=np.array([[0.1,0.4],[0.2,0.5],[0.3,0.6]])
B2=np.array([0.1,0.2])

print(Z1.shape) #(3,)
print(W2.shape) #(3,2)
print(B2.shape) #(2,)

A2 = np.dot(Z1,W2)+B2
Z2 = sigmoid(A2)

입력층에서 1층으로 가는 것하고, 행렬의 생김새가 다르다는 것 제외하고는 아예 동일한 과정이다. 이 과정을 통해

1X2행렬이 만들어졌다.

 

 

2층에서 출력층으로 신호전달

 

출력층의 구현도 거의 동일한데, 활성화 함수만 지금까지의 은닉층과 다르다. 위 예시에서는 항등함수를 사용하였다.

def identity_function(x):
    return x

W3=np.array([[0.1,0.3],[0.2,0.4]])
B3=np.array([0.1,0.2])

A3=np.dot(Z2,W3)+B3
Y=identity_function(A3)

 

구현 전체 정리

import numpy as np

def sigmoid(x):
    return 1/(1+np.exp(-x))

def identity_function(x):
    return x

def init_network():
    network = {} #dictionary 꼴
    network['W1']=np.array([[0.1,0.3,0.5],[0.2,0.4,0.6]])
    network['b1']=np.array([0.1,0.2,0.3])
    network['W2']=np.array([[0.1,0.4],[0.2,0.5],[0.3,0.6]])
    network['b2']=np.array([0.1,0.2])
    network['W3']=np.array([[0.1,0.3],[0.2,0.4]])
    network['b3']=np.array([0.1,0.2])
    
    return network

def forward(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 #입력층에서 1층
    z1=sigmoid(a1)
    a2=np.dot(z1,W2)+b2#1층에서 2층
    z2=sigmoid(a2)
    a3=np.dot(z2,W3)+b3#2층에서 출력층
    y=identity_function(a3)
    
    return y

network=init_network()
x=np.array([1.0, 0.5])
y=forward(network,x)
print(y)

init_network() 함수는 가중치와 편향을 초기화하고 dictionary 변수에 저장한다.

forward() 함수는 입력 신호를 출력으로 변환하는 처리 과정을 모두 구현하고 있다.

 

이름이 forward인 것은 신호가 순방향으로 전달됨을 알리기 위함이다. 

"순전파"라는 이름은 여기서 기인한 것이다. 마찬가지로 역으로 일으킨다면 "역전파"가 된다.

+ Recent posts