신경망의 구조를 조금 알게 되었으니 MINIST를 사용하여 신경망이 이미지를 분류하게 만들어본다. 이와 같은 추론 과정을 순전파(forward propagation)라고 한다.
링크에 들어가 MINIST 파일을 받을 수 있는 mnist.py 를 다운로드 한다
import sys, os
from minist import load_mnist
(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)
실행하여 올바른 결과가 나오는지 확인해본다. ministy.py에서 load_mnist 함수를 가져온 것이고 이후 데이터 셋을 가져오는 것이다. 상세한 내용은 나중에 살펴보고 MINIST 파일 중 하나를 읽어본다.
import sys, os
from minist import load_mnist
import numpy as np
from PIL import Image
def img_show(img):
pil_img = Image.fromarray(np.uint8(img))
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)
실행해보면 이미지를 하나 내뱉는 것을 알 수 있다. flatten=True로 들어왔기 때문에 이미지가 1차원으로 저장되어 있다. 이 것을 유의하여 reshape 해주어야 제대로 출력을 볼 수 있다.
신경망을 구현해본다. 입력층 뉴런이 784개, 출력층은 10개이다. 입력은 28*28=784이고 0~9까지이기 때문에 10개로 정해주었다. 은닉층은 2층으로 50개, 100개로 정해주었다.
import sys, os
from minist import load_mnist
import numpy as np
from PIL import Image
import pickle
def sigmoid(x):
return 1 / (1+np.exp(-x))
def softmax(a):
c = np.max(a)
exp_a = np.exp(a-c)
sum_exp_a = np.sum(exp_a)
y = exp_a / sum_exp_a
return y
def img_show(img):
pil_img = Image.fromarray(np.uint8(img))
pil_img.show()
def get_data():
(x_train, t_train), (x_test, t_test) = load_mnist(flatten=True, normalize=False)
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
init_network() 함수를 살펴보면 sample_weight.pkl에서 load 해온다. 네트워크라고 적힌걸 보니 여기에 가중치와 편향이 저장되어 있는 것 같다. 궁금하니 출력해본다.
이런 값들이 저장되어 있다. 그렇다면 한 번 테스트를 해보고 정확도를 따져본다.
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)
if p == t[i]:
accuracy_cnt += 1
print("Accuracy:" + str(float(accuracy_cnt) / len(x)))
책에는 93%의 정확도라는데 왜 나는 92밖에 안될까. 보니까 sigmoid 가 overflow가 난다고 한다. 찾아보니 정확도가 높아질수록 numpy에 의해 sigmoid가 오버플로 날 확률이 높아진다는데..^^ 무슨 소린지 모르겠고 다음과 같은 말이 있다.
지금 코드는 사진 한 장씩을 predict에 넣고 있다. 이 것을 빠르게 진행하기 위해서 batch라는 것이 있다. 배치 처리라는 것인데 큰 배열을 한꺼번에 계산시켜 한번에 결과를 얻는 것이다. 컴퓨터는 자잘한 일을 반복해서 하는 것보다 큰 일을 한번에 하는 것을 더 잘한다. 당장 곱셈같은 것만 생각해도 2*2*2*2*2 를 하는 것보다 2^5를 하는 것이 훨씬 빠르다(실제로는 똑같은 것처럼 보이지만) 배치를 구현해본다.
x, t = get_data()
network = init_network()
batch_size = 100
accuracy_cnt = 0
for i in range(0, len(x), 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)))
for문을 보면 range(:1, :2, :3)으로 들어간 것을 알 수 있는데 이는 :1 값부터 시작해서 :2값까지 :3의 간격으로 돌라는 소리다.
for i in range(1, 10, 2):
print(i)
1
3
5
7
9
이렇게 나온다. 따라서 0부터 x의 길이까지 돌되 100개씩 처리해주라는 소리다.
x_batch = x[i:i+batch_size] 는 안봐도 x[0:100], x[100:200] 이런식으로 배열을 생성해주는 것이고 y_batch는 x_batch를 하나씩 predict 해준다. 이후 p에서 최대값의 인덱스를 가져오는 것인데 axis=1이다. 1차원 배열마다 찾아서 오라는 이야기이다.
x = np.array([[0.1,0.8,0.3],[0.3,0.4,0.5],[0.7,0.9,0.2]])
y = np.argmax(x, axis=1)
print(y)
#[1 2 1]
x = np.array([[0.1,0.8,0.3],[0.3,0.4,0.5],[0.7,0.9,0.2]])
y = np.argmax(x)
print(y)
#7
이렇게 axis를 정해주고 안정해주고가 차이나는 것을 알 수 있다. 이제 확률을 구해주는데 배열에서 True가 몇 개인지 세어주는 것이다. 이렇게 하면 데이터를 배치로 처리할 수 있다.
'Python > DeepLearning' 카테고리의 다른 글
퍼셉트론에서 신경망으로(6) (0) | 2019.04.23 |
---|---|
퍼셉트론에서 신경망으로(5) (0) | 2019.04.23 |
퍼셉트론에서 신경망으로(3) (0) | 2019.04.22 |
퍼셉트론에서 신경망으로(2) (0) | 2019.04.22 |
퍼셉트론에서 신경망으로(1) (0) | 2019.04.22 |