본문 바로가기
Data Science/머신러닝&딥러닝 기초 이론

[딥러닝 실습] MNIST 손글씨 인식 실습하기

by titaniumm 2020. 4. 18.

손글씨 이미지들을 가져와서 인식하는 실습이다. 코드의 구성은 다음과 같다.

1. MNIST 글씨들을 다운 후 저장되어 있는 파일을 내가 원하는 형식으로 저장하기

import gzip
import numpy as np

fnames =['train-images-idx3-ubyte.gz','train-labels-idx1-ubyte.gz','t10k-images-idx3-ubyte.gz','t10k-labels-idx1-ubyte.gz']
with gzip.open(fnames[0],'rb') as f:
    train_image = np.frombuffer(f.read
                                (),np.uint8,offset =16)
with gzip.open(fnames[1],'rb') as f:
    train_label = np.frombuffer(f.read(),np.uint8,offset =8)
with gzip.open(fnames[2],'rb') as f:
    test_image = np.frombuffer(f.read(),np.uint8,offset =16)
with gzip.open(fnames[3],'rb') as f:
    test_label = np.frombuffer(f.read(),np.uint8,offset =8)

train_image = train_image.reshape(-1,28*28)
test_image = test_image.reshape(-1,28*28)
print(train_image.shape)
print(train_label.shape)
print(test_image.shape)
print(test_label.shape)
np.savez('MNIST_array.npz',train_image=train_image,train_label=train_label,test_image=test_image,test_label=test_label)

2. 활성화 함수들 준비하기

import numpy as np
import matplotlib.pyplot as plt

def step_function(x):
    y = x>0
    return y.astype(np.int)
    #astype(np.xx)는 xx형태로 타입을 바꿔주는것

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

def rulu(x):
    return np.maximum(0,x)

x = np.arange(-5.0,5.0,0.01)
y1 = step_function(x)
y2 = sigmoid(x)

plt.plot(x,y1,"r",label ="step function")
plt.plot(x,y2,"b",label ="sigmoid function")
plt.legend(loc="lower right")
plt.xlim(-5,5)
plt.ylim(-0.1,1.1)
plt.xlabel('$x$')
plt.ylabel("activation function value")
plt.title("graph of activation functions")
plt.grid(True)
plt.show()

#활성화 항수(softmax함수)
import numpy as np
import matplotlib.pyplot as plt
#C를 활요해준 이유는 값의 overflow를 막기 위함(c=최대값)

#1차원 일때 softmax함수
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

#2차원 일때 softmax함수
def softmax(x):
    if x.ndim ==2:
        x = x - x.max(axis=1,keepdims =True)
        x = np.exp(x)
        x /= x.sum(axis = 1,keepdims =True)
    elif x.ndim == 1:
        x = x-np.max(x)
        x = np.exp(x) / np.sum(np.exp(x))
    return x

3. 글씨가 정확히 보이는지 확인

#read_mnist_array.py
import numpy as np
import matplotlib.pyplot as plt

MNIST_arrays = np.load('MNIST_array.npz')
MNIST_arrays.files


x_train = MNIST_arrays['train_image']
t_train = MNIST_arrays['train_label']
x_test = MNIST_arrays['test_image']
t_test = MNIST_arrays['test_label']

print(x_train.shape)
print(t_train.shape)
print(x_test.shape)
print(t_test.shape)

#랜덤으로 이미지 만들기
idx = np.random.choice(x_train.shape[0],1)
img = x_train[idx].reshape(28,28)
img =255 -img
label = t_train[idx]

plt.figure(figsize=(5,5))
plt.imshow(img,cmap='gray')
plt.title(str(t_train[idx]))
plt.xticks([]),plt.yticks([])

4. 3-layer 신경망 만들기

#predict
import sys
sys.path.append('..')
import numpy as np
import pickle
from common.functions import sigmoid,softmax

def get_test_data():
    MNIST_arrays =np.load('../dataset/MNIST_array.npz')
    
    x_test = MNIST_arrays['test_image']
    t_test = MNIST_arrays['test_label']
    
    x_test = x_test.astype(np.float32)
    x_test /= 255.0
    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_test ,t_test = get_test_data()
network = init_network()

accuracy =0
for i in range(len(x_test)):
    y = predict(network, x_test[i])
    pred_label = np.argmax(y)
    if pred_label == t_test[i]:
        accuracy +=1
        
print("Accuracy:" +str(float(accuracy) / len(x_test)))
# 50 - 100 : accuracy 0.9352        

50 - 100은 first layer 와 second layer의 신경망 수이다.

댓글