ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 2. 신경망(5)
    AI 모델(딥러닝 기초)/2. 신경망 2023. 1. 5. 13:29
    728x90

    ※ MNIST 데이터셋

     

    - 손글씨 숫자 이미 집합

    - 0~9까지의 숫자 이미지로 구성되고 훈련 이미지와 시험 이미지로 구성됨

    - 훈련 이미지로 학습 후 시험 이미지로 테스트 하여 정확성을 판별

     

    <기본 MNIST 데이터셋>

    # coding: utf-8
    try:
        import urllib.request
    except ImportError:
        raise ImportError('You should use Python 3.x')
    import os.path
    import gzip
    import pickle
    import os
    import numpy as np
    
    
    url_base = 'http://yann.lecun.com/exdb/mnist/'
    key_file = {
        'train_img':'train-images-idx3-ubyte.gz',
        'train_label':'train-labels-idx1-ubyte.gz',
        'test_img':'t10k-images-idx3-ubyte.gz',
        'test_label':'t10k-labels-idx1-ubyte.gz'
    }
    
    dataset_dir = os.path.dirname(os.path.abspath(__file__))
    save_file = dataset_dir + "/mnist.pkl"
    
    train_num = 60000
    test_num = 10000
    img_dim = (1, 28, 28)
    img_size = 784
    
    
    def _download(file_name):
        file_path = dataset_dir + "/" + file_name
        
        if os.path.exists(file_path):
            return
    
        print("Downloading " + file_name + " ... ")
        urllib.request.urlretrieve(url_base + file_name, file_path)
        print("Done")
        
    def download_mnist():
        for v in key_file.values():
           _download(v)
            
    def _load_label(file_name):
        file_path = dataset_dir + "/" + file_name
        
        print("Converting " + file_name + " to NumPy Array ...")
        with gzip.open(file_path, 'rb') as f:
                labels = np.frombuffer(f.read(), np.uint8, offset=8)
        print("Done")
        
        return labels
    
    def _load_img(file_name):
        file_path = dataset_dir + "/" + file_name
        
        print("Converting " + file_name + " to NumPy Array ...")    
        with gzip.open(file_path, 'rb') as f:
                data = np.frombuffer(f.read(), np.uint8, offset=16)
        data = data.reshape(-1, img_size)
        print("Done")
        
        return data
        
    def _convert_numpy():
        dataset = {}
        dataset['train_img'] =  _load_img(key_file['train_img'])
        dataset['train_label'] = _load_label(key_file['train_label'])    
        dataset['test_img'] = _load_img(key_file['test_img'])
        dataset['test_label'] = _load_label(key_file['test_label'])
        
        return dataset
    
    def init_mnist():
        download_mnist()
        dataset = _convert_numpy()
        print("Creating pickle file ...")
        with open(save_file, 'wb') as f:
            pickle.dump(dataset, f, -1)
        print("Done!")
    
    def _change_one_hot_label(X):
        T = np.zeros((X.size, 10))
        for idx, row in enumerate(T):
            row[X[idx]] = 1
            
        return T
        
    
    def load_mnist(normalize=True, flatten=True, one_hot_label=False):
        """MNIST 데이터셋 읽기
        
        Parameters
        ----------
        normalize : 이미지의 픽셀 값을 0.0~1.0 사이의 값으로 정규화할지 정한다.
        one_hot_label : 
            one_hot_label이 True면、레이블을 원-핫(one-hot) 배열로 돌려준다.
            one-hot 배열은 예를 들어 [0,0,1,0,0,0,0,0,0,0]처럼 한 원소만 1인 배열이다.
        flatten : 입력 이미지를 1차원 배열로 만들지를 정한다. 
        
        Returns
        -------
        (훈련 이미지, 훈련 레이블), (시험 이미지, 시험 레이블)
        """
        if not os.path.exists(save_file):
            init_mnist()
            
        with open(save_file, 'rb') as f:
            dataset = pickle.load(f)
        
        if normalize:
            for key in ('train_img', 'test_img'):
                dataset[key] = dataset[key].astype(np.float32)
                dataset[key] /= 255.0
                
        if one_hot_label:
            dataset['train_label'] = _change_one_hot_label(dataset['train_label'])
            dataset['test_label'] = _change_one_hot_label(dataset['test_label'])    
        
        if not flatten:
             for key in ('train_img', 'test_img'):
                dataset[key] = dataset[key].reshape(-1, 1, 28, 28)
    
        return (dataset['train_img'], dataset['train_label']), (dataset['test_img'], dataset['test_label']) 
    
    
    if __name__ == '__main__':
        init_mnist()

     

    <MNIST 데이터셋 불러오기>

    # coding: utf-8
    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()
    
    (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)

     

     

    <MNIST 데이터셋을 활용한 신경망의 accuracy 출력시키기>

    # coding: utf-8
    import sys, os
    sys.path.append(os.pardir)  # 부모 디렉터리의 파일을 가져올 수 있도록 설정
    import numpy as np
    import pickle
    from dataset.mnist import load_mnist
    
    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 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
    
    # normalize=True를 통해서 0~255 범위인 각 픽셀의 값을 0.0~1.0 범위로 변환함(픽셀 값을 255로 나눔) 
    # 정규화 : 데이터를 특정 범위로 변환하는 처리(전처리)
    
    
    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)))

     

     

    MNIST 데이터셋을 활용해서 데이터를 특정 범위로 변환하는 처리를 하는 정규화와 전처리 과정을 살펴보았고, mnist 데이터셋을 load하여 train 시키고 predict함수를 통해 구축해 둔 간단한 신경망 안에서 예측값 출력, 그리고 최종accuracy까지 뽑아내 보았다.

     

    이 과정을 거치면서 이전 데이터 공모전에 출전하여 아무것도 모르는 상태에서 영상 classification 작업을 진행해 본 것이 떠올랐다. 데이터 전처리, 모델 학습, 학습된 모델을 새로운 테스트 데이터셋에 예측 적용, accuracy 뽑아내기 등을 살펴볼 수 있었다. 이 과정에서 epoch만 적절히 조정해 준다면 영상 딥러닝의 기본적인 과정을 모두 살펴볼 수 있는 시간이라고 생각한다. 

    728x90

    'AI 모델(딥러닝 기초) > 2. 신경망' 카테고리의 다른 글

    2. 신경망(6)  (2) 2023.01.05
    2. 신경망(4)  (0) 2023.01.04
    2. 신경망(3)  (0) 2023.01.02
    2. 신경망(2)  (1) 2022.12.27
    2. 신경망(1)  (0) 2022.12.26
Designed by Tistory.