3강에서는 인공신경망의 기본적인 개념들과 인공신경망을 코드로 어떻게 구현할 수 있는지에 대해 학습했습니다.
교재에 나와있는 3층 신경망의 구조부터 우선 살펴보겠습니다. 교재의 3층 신경망은 아래의 사진처럼 입력층에 2개의 퍼셉트론이 있고 은닉층에 각각 3개, 2개의 퍼셉트론이 있으며 출력층에 2개의 퍼셉트론이 있는 구조입니다.
은닉층에 위치한 퍼셉트론의 입력값과 출력값을 모두 표기하면 아래의 사진과 같습니다. (x1, x2)는 입력된 값이며 a는 입력된 값들에 가중치를 곱하고 편향을 더한 값을 의미합니다. h는 활성화 함수를 의미하고 z는 활성화 함수의 출력값이며 다음층에 전달되는 신호입니다.
각 층에 위치한 퍼셉트론, 가중치 등의 구분은 윗첨자와 아래첨자를 이용하여 표기합니다. 만약 x1에서 1층의 첫번째 퍼셉트론에 연결된 값의 가중치라면 처럼 윗첨자에 (1)을 적고 아래첨자에 11을 적어 표현합니다. 이때 아래첨자에 쓴 11은 이전 층의 첫번째 퍼셉트론에서 다음 층의 첫번째 퍼셉트론을 연결했슴을 의미합니다. 1층의 첫번째 퍼셉트론에 입력되는 신호들을 모두 표시하면 아래의 사진과 같습니다.

위에서 살펴본 인공신경망의 각 층에서 신호가 어떻게 연산되는지 살펴보겠습니다. 이번 인공신경망의 활성화 함수는 sigmoid이며 마지막 출력층에서는 softmax를 이용합니다. 우선 1층에 위치한 퍼셉트론 3개의 값을 계산하기 위한 식을 모두 적으면 아래와 같습니다.
1층의 첫번째 퍼셉트론 :
1층의 두번째 퍼셉트론 :
1층의 세번째 퍼셉트론 :
매번 이렇게 식을 일일이 적을 수 없으므로 인공신경망의 연산에서는 주로 행렬식을 이용해서 표현합니다. 위 연산을 행렬식으로 바꾸면 아래와 같이 깔끔하게 식을 표현할 수 있습니다.
= +
이제 2층의 신호를 연산을 살펴보겠습니다. 한 가지 주의할 점은 의 값은 단순히 입력된 값들의 가중치와 편향을 계산한 결과라는 것입니다. 머신러닝이 제대로 학습을 하기 위해서는 반드시 활성화 함수를 거친 값을 출력해줘야 한다는 것을 빠트리면 안됩니다. 따라서 2층에 입력된 신호들은 이 아니라 1층의 활성화 함수의 출력값인 을 입력값으로 계산해야 합니다. 따라서 2층에 위치한 퍼셉트론의 연산은 아래와 같습니다.
= +
출력층의 연산 또한 앞선 과정과 동일합니다. 을 입력값으로 처리해주면 됩니다.
= +
마지막으로 출력층은 앞서 1,2층에서 사용한 활성화 함수인 sigmoid 함수가 아니라 softmax 함수를 이용해야 한다는 점에 주의해야 합니다.
인공신경망을 코드로 구현하기 위해 어떤 것들이 필요한지 먼저 살펴보겠습니다. 인공신경망을 처리하기 위해서는 각 층의 가중치, 임계값(편향)이 필요하며 활성화 함수도 필요합니다. 따라서 코드로 구현할 때는 각 층의 가중치, 편향을 담은 리스트들 그리고 sigmoid 함수, softmax 함수를 만들고 각 층을 연결하면 되겠습니다. 가중치, 편향, 활성화 함수를 우선 코드로 구현하면 아래와 같습니다.
import numpy as np
import math
def init_network():
network={}
network['w1']=np.array([[1,2,3],[-4,-5,-6]])
network['b1']=np.array([0,0,0])
network['w2']=np.array([[5,0],[0,-3],[4,0]])
network['b2']=np.array([0,0])
return network
def sigmoid(x):
return 1/(1+np.exp(-x))
def softmax(x):
if x.ndim==2:
x=x.T
x=x-mp.max(x, axis=0)
y=np.exp(x)/np.sum(np.exp(x), axis=0)
return y.T
x=x-np.max(x)
return np.exp(x)/np.sum(np.exp(x))
다음으로 각 층의 퍼셉트론을 연결한 코드를 살펴보겠습니다. 퍼셉트론들을 코드로 연결할 때는 이전층의 신호와 가중치, 편향을 모두 연산한 값들과 활성화 함수를 통과한 값인 을 분리해 연산합니다.
def forward(network,x):
w1, w2=network['w1'], network['w2']
b1, b2=network['b1'], network['b2']
a1=np.dot(x,w1)+b1
z1=sigmoid(a1)
a2=np.dot(z1,w2)+b2
y=softmax(a2)
return y
forward 함수의 network는 가중치와 편향을 담은 리스트를 의미합니다. 인공신경망의 값을 출력하기 위한 다음 코드를 살펴보면 바로 알 수 있습니다.
network=init_network()
x=np.array([math.log(4),math.log(2)])
y=forward(network,x)
print(y)
network에 가중치와 편향을 담은 init_network()를 복사해주고 x에는 인공신경망의 입력층에 들어갈 값을 입력합니다. y는 앞서 만든 인공신경망 함수인 forward에 x 값들을 연산한 결과를 담게 되고 print(y)를 통해 그 값을 확인할 수 있습니다.
4강에서는 머신러닝에 활용되는 대표적인 데이터셋인 MNIST에 대해 간단히 살펴보고 데이터의 구조가 어떻게 이뤄져 있는지에 대해 학습했습니다.
MNIST는 LeCun 교수가 만든 데이터 셋이며 Hello, World처럼 딥러닝을 처음 배울 때 사용하게 되는 데이터셋입니다. 데이터셋은 손으로 쓴 숫자들의 흑백 이미지이며 훈련용 데이터 6만개와 테스트용 데이터 1만개로 구성되어 있습니다. 각 이미지의 크기는 28*28로 통일되어 있으며 이미지의 중심부에 손글씨가 위치해 있습니다. 각 픽셀은 0~255 사이의 값으로 밝기를 표현하며 픽셀의 값이 클수록 검은색에 가깝습니다. MNIST의 데이터 중 일부를 살펴보면 아래와 같습니다.
MNIST의 훈련용 데이터셋의 shape을 살펴보면 (60000,1,28,28)과 같습니다. 여기서 앞의 60000은 데이터의 수이며 1은 채널의 수 입니다. MNIST의 경우 흑백사진이기 때문에 채널의 수가 1개이지만 컬러 이미지의 경우 RGB 각각의 값을 저장해줘야 하기 때문에 3개의 채널이 필요합니다. shape의 마지막 부분인 28, 28은 이미지의 가로 세로 길이를 나타내며 MNIST는 한 변이 28픽셀인 정사각형의 형태이기 때문에 28,28이라고 나옵니다.