본문 바로가기
Drawing (AI)/DeepLearning

딥러닝 직접 구현하기 - (신경망)

by 생각하는 이상훈 2023. 7. 1.
728x90

손글씨 숫자 인식

MNIST 데이터셋을 이용하여 손글씨 숫자를 분류하는 실습을 진행해 보았다. 이때의 추론 과정은 신경망의 순전파를 통해 진행된다. MNIST 데이터 셋은 아래와 같이 28 x 28 사이즈의 회색조 이미지이다. 훈련 이미지 60,000장, 테스트 이미지 10,000장이 존재한다. 이러한 데이터셋을 구분해내는 능력이 현재 학계에서 평가하는 지표로 많이 쓰이곤 한다.

 

아래와 같은 코드를 이용해 MNIST 데이터셋을 내려받아 이미지를 넘파이 배열로 전환할 수 있다.

import sys, os
sys.path.append(os.pardir) # 부모 디렉터리의 파일을 가져올 수 있도록 설정
from dataset.mnist 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)  

'''
(60000, 784)
(60000,)
(10000, 784)
(10000,)

load_mnist 함수의 인수는 normalize, flatten, one_hot_label 세가지가 존재하고 모두 bool 값이다. normalize는 입력 이미지의 픽셀 값을 0.0~1.0 사이의 값으로 정규화할지를 결정하고 False를 선택한다면 0~255 사이의 원래 값을 유지한다. 두번째 인수인 flatten은 입력 이미지를 1차원 배열로 만들지 결정하고 False를 선택하면 입력 이미지를 1 x 28 x 28의 3차원 배열로 저장한다. 세번째 인수인 one_hot_label은 레이블을 원-핫 인코딩 형태로 저장할지를 결정한다.

matplotlib inline
import sys, os
sys.path.append(os.pardir)
import numpy as np
from dataset.mnist import load_mnist
from PIL import Image

def img_show(img):
    pil_img = Image.fromarray(np.uint8(img))
    #pil_img.show()
    plt.imshow(np.array(pil_img))
    
(x_train, t_train), (x_test, t_test) = load_mnist(flatten=True, normalize=False)

img = x_train[0]
label = t_train[0]

print(label) # 5

print(img.shape)          # (784,)
img = img.reshape(28, 28) # 원래 이미지의 모양으로 변형
print(img.shape)          # (28, 28)

img_show(img)

위의 코드를 보면 flatten=True였기 때문에 reshape을 통해 1차원 배열을 재조합하여 출력하는 것을 볼 수 있다.


신경망의 추론 처리

입력층 뉴런을 784개, 출력층 뉴런을 10개로 구성한다. 이때 입력층 뉴런은 28 x 28 = 784이기 때문에 784개로 구성한다. 첫 번째 은닉층은 50개의 뉴런, 두 번째 은닉층은 100개의 뉴런을 배치한다. 이때 50, 100은 임의로 결정된 값이다.

import pickle

def get_data():
    (x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, flatten=True, one_hot_label = 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
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)))

#Accuracy:0.9352

predict() : 각 레이블의 확률을 넘파이 배열로 반환

np.argmax() : 가장 큰(확률이 가장 높은) 원소의 인덱스를 구함 => 예측 결과

#배치 처리(각 층의 가중치 형상을 출력)

x, _ = get_data()
network = init_network()
W1, W2, W3 = network['W1'], network['W2'], network['W3']

x.shape
#(10000, 784)

x[0].shape
#(784,)

W1.shape
#(784, 50)

W2.shape
#(50, 100)

W3.shape
#(100, 10)

 

100장 분량 입력 데이터의 결과가 한 번에 출력된다. 배치란 하나로 묶은 데이터인데 이를 이용한 배치처리의 이점은 이미지 1장당 처리 시간을 대폭 줄이고 버스에 주는 부하를 줄이는 것이다. (CPU, GPU로 순수 계산을 수행하는 비율이 높아짐)

#배치 처리 구현

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)))

#Accuracy:0.9352
# range(start, end, step) 처럼 인수를 3개 지정하면 start에서 end-1까지 step 간격으로 증가하는 리스트를 반환

list( range(0, 10) )
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
list( range(0, 10, 3) )
[0, 3, 6, 9]

x[i:i+batch_n]은 입력 데이터 i번째부터 i+batch_n번째까지 데이터를 묶는다는 의미이다.

#argmax axis 예시

x = np.array([[0.1, 0.8, 0.1], [0.3, 0.1, 0.6], [0.2, 0.5, 0.3], [0.8, 0.1, 0.1]])
y = np.argmax(x, axis=1)

array([1, 2, 1, 0])
#True 개수 세는 예제

y = np.array([1, 2, 1, 0])
t = np.array([1, 2, 0, 0])
print(y==t)
np.sum(y==t)
[ True  True False  True]
3

 

728x90

'Drawing (AI) > DeepLearning' 카테고리의 다른 글

CNN for NLP  (0) 2023.07.22
딥러닝 직접 구현하기 - (신경망 학습)  (0) 2023.07.06
딥러닝 직접 구현하기 - (퍼셉트론)  (0) 2023.06.21
Word Embedding(2)  (0) 2023.05.14
Word Embedding(1)  (2) 2023.05.11