어떤 문제를 푸느냐에 따라 출력층에서의 활성화 함수가 달라짐
기계학습 문제는 분류(classification) 와 회귀(regression) 로 나뉨
분류 : 데이터가 어느 클래스(class)에 속하느냐는 문제 (ex. 사진 속 인물의 성별 분류)
회귀 : 입력 데이터에서 연속적인 수치를 예측하는 문제 (ex. 사진 속 인물의 몸무게 예측)
identity function
항등 함수는 입력을 그대로 출력
그래서 출력층에 항등 함수를 사용하면 입력 신호가 그대로 출력 신호가 됨
softmax function
exp(x)는 e^{x}를 뜻하는 지수 함수
n : 출력층의 뉴런 수
yk : 그 중 k번째 출력
분자는 입력 신호의 지수 함수, 분모는 모든 입력 신호의 지수 함수의 합!
분모에서 알 수 있듯이 출력층의 각 뉴런이 모든 입력 신호에서부터 영향을 받는다.
소프트맥스 함수의 구현은 다음과 같다.
def softmax(a):
exp_a = np.exp(a)
sum_exp_a = np.sum(exp_a)
y = exp_a / sum_exp_a
return y
softmax 함수는 컴퓨터로 계산 시 오버플로 문제가 발생할 수 있다.
따라서 다음과 같이 개선하는 것이 좋다.
여기서 입력 신호 중 최댓값을 빼주는 방식으로 계산이 진행될 수 있도록 C의 값을 선택하면 올바른 계산이 이루어질 수 있다.
출력의 총합이 1이라는 성질 덕분에 소프트 맥스 함수의 출력을 '확률'로 해석할 수 있다.
신경망을 이용한 분류에서는 일반적으로 가장 큰 출력을 내는 뉴런에 해당하는 클래스로 인식
소프트맥스 함수를 적용해도 출력이 가장 큰 뉴런의 위치는 달라지지 않으므로
신경망으로 분류할 때에는 소프트함수 맥스를 생략해도 됨
기계학습의 문제 풀이는 학습과 추론의 두 단계를 거쳐 이뤄짐
학습 → 모델을 학습
추론 → 학습한 모델로 미지의 데이터에 대해 추론(분류) 수행
MNIST 데이터셋이라는 손글씨 숫자 이미지 집합을 이용한다.
MNIST 데이터셋은 0부터 9까지의 숫자 이미지로 구성됨
MNIST 이미지 데이터는 28x28 크기의 회색조 이미지이며,
각 픽셀은 0에서 255까지의 값을 취한다.
다음의 코드를 통해 MNIST 데이터를 쉽게 가져올 수 있다.
import sys
import os
sys.path.append(os.pardir) # 부모 디렉토리의 파일을 가져올 수 있도록 설정
from dataset.mnist import load_mnist # dataset 폴더의 mnist파일에서 load_mnist 함수 import
(x_train, t_train), (x_test, t_test) = \
load_mnist(flatten=True, normalize=False)
# 각 데이터의 형상 출력
print(x_train.shape)
print(t_train.shape)
print(x_test.shape)
print(t_test.shape)
load_mnist 함수는 MNIST 데이터를
"(훈련 이미지, 훈련 레이블), (시험이미지, 시험 레이블)"의 형식으로 반환한다.
인수
normalize : 입력 이미지의 픽셀 값을 0.0~1.0 사이의 값으로 정규화 할지 정함
flatten : 입력 이미지를 1차원 배열로 만들지 정함 (False → 1x28x28(3차원), True →784(1차원))
one_hot_label : 원-핫 인코딩 형태로 저장할 지 정함
** 원-핫 인코딩은 [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]처럼 정답을 뜻하는 원소만 1이고 나머지는 0인 배열
아래의 코드로 MNIST 이미지를 화면으로 부를 수 있다.
import sys
import os
import numpy as np
sys.path.append(os.pardir)
from dataset.mnist import load_mnist
from PIL import Image
def img_show(img):
pil_img = Image.fromarray(np.uint8(img)) # 넘파이로 저장된 이미지 데이터를 PIL용 데이터 객체로 변환
pil_img.show()
(x_train, t_train), (x_test, t_test) = \
load_mnist(flatten=True, normalize=False)
img = x_train[0]
label = t_train[0]
print(label)
print(img.shape)
img = img.reshape(28,28) # 원래 이미지 모양으로 복구
print(img.shape)
img_show(img)
MNIST 데이터셋은 이미지 크기가 28x28=784이고, 0부터 9까지의 숫자를 구분해야 하므로
입력층 뉴런을 784, 출력층 뉴런을 10개로 구성
순서대로 작업을 처리해줄 세 함수는 다음과 같다.
def get_data():
(x_train, t_train), (x_test, t_test) = \
load_mnist(flatten=True, normalize=False, one_hot_label=False) # 1차원 넘파이 배열로 저장
return x_test, t_test
def init_network():
with open("sample_weight.pkl",'rb') as f:
network = pickle.load(f)
return network
def predict(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 = softmax(a3)
return y
위의 세 함수를 통해 신경망 추론 및 정확도 평가는 다음과 같이 진행할 수 있다.
x, t = get_data()
network = init_network()
accuracy_cnt = 0
for i in range(len(x)):
y = predict(network,x[i])
p = np.argmax(y)
# 정답을 맞춘 case를 count
if p == t[i]:
accuracy_cnt += 1
print('Accuracy:' + str(float(accuracy_cnt)/len(x)))
하나로 묶은 입력 데이터를 배치(batch)라고 한다.
배치 처리는 컴퓨터로 계산 시 이미지 1장당 처리 시간을 대폭 줄여주는 이점이 있다.
앞에서 진행한 MNIST 데이터셋에 배치 처리를 적용하면 다음과 같이 처리가 가능하다.
x, t = get_data()
network = init_network()
batch_size = 100 # 배치 크기
accuracy_cnt = 0
for i in range(0,len(x), batch_size): # 0부터 batch_size 만큼 묶음
x_batch = x[i:i+batch_size]
y_batch = predict(network, x_batch)
p = np.argmax(y_batch,axis = 1)
accuracy_cnt += np.sum(p == t[i:i+batch_size])
print('Accuracy:' + str(float(accuracy_cnt)/len(x)))