ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 딥러닝 MNIST 필기체 인식
    인공지능 2020. 6. 3. 15:37
    728x90

     

    Mnist 는 딥러닝 공부를 할 때 기초적이면서도 흥미로운 연습 문제에요

    Training Data set(csv)Test Data set(csv) 파일 링크입니다.

    Training Data set 에는 6만개의 이미지 데이터가 들어있습니다. 하나의 이미지는 28 * 28 사이즈로 784개의 숫자로 이루어져있습니다.

    csv 파일을 열어보시면

    5, 0, 0, 0, 78, 80, 32, ... , 30  이런 숫자들의 모임이 있는데 처음 숫자 5는 정답 숫자에 대한 정보이고, 나머지 784개의 숫자는 이미지를 나타내는 정보로, 픽셀 하나의 밝기 값이라고 생각하시면 됩니다. 따라서 0에 가까운 숫자일수록 검정색에 가깝고, 255에 가까운 숫자일 수록 하얀색에 가깝습니다.

     

    데이터 로딩

    import numpy as np
    
    training_data = np.loadtxt('mnist_train.csv', delimiter=',', dtype=np.float32)
    test_data = np.loadtxt('mnist_test.csv', delimiter=',', dtype=np.float32)

    위 코드로 데이터를 로딩할 수 있습니다.

     

    MNIST 입력 정리

    학습을 위한 데이터에서는 하나의 이미지가 784개의 숫자를 가진 1차원 배열로 표현되지만

    실제 이미지는 28 * 28 의 숫자를 가진 2차원 배열로 표현됩니다. 그래서 이 이미지를 직접 보고싶다면 아래와 같이 코딩하면 됩니다.

    이미지 직접 보는 법

    import numpy as np
    import matplotlib.pyplot as plt
    
    # 데이터 로딩
    training_data = np.loadtxt('mnist_train.csv', delimiter=',', dtype=np.float32)
    test_data = np.loadtxt('mnist_test.csv', delimiter=',', dtype=np.float32)
    
    # 이미지로 보기
    img = training_data[0][1:].reshape(28, 28)
    plt.imshow(img, cmap='gray')
    plt.show()

    5

    설계

    입력층

    784개의 입력 데이터 픽셀이 있으므로 입력층은 784개의 노드로 구성되어있습니다.

     

    은닉층

    은닉층은 한 개만 두었으며 100개의 노드를 갖고 있습니다. 노드의 갯수와 층의 깊이는 구현하기 나름이므로 변경하고싶다면 바꿀 수 있습니다. 다만 너무 많은 노드와 깊은 층은 학습 시간이 지나치게 오래걸릴 수 있으므로 주의해야합니다.

     

    출력층

    출력층은 One-hot encoding 기법을 사용하기 위해 10개의 노드를 갖고 있습니다.

    One-hot encoding 기법이란 기존의 Logistic Regression 은 0 또는 1 이라는 이분법적인 Classification 에 대한 문제를 해결하기 위한 방법이였지만 필기체 구분 같은 경우 0 ~ 9 사이의 숫자 중 어느것인지 분류해내는 문제입니다.

    따라서 1차원 배열에 각각의 숫자일 확률을 기록하고 그 확률이 가장 높은것을 정답으로 취급하는 방법을 One-hot encoding 이라 합니다.

     

     

     

    코드

    import numpy as np
    
    train_data = np.loadtxt('mnist_train.csv', delimiter=',', dtype=np.float32)
    test_data = np.loadtxt('mnist_test.csv', delimiter=',', dtype=np.float32)
    print('load datas')
    
    def sigmoid(x):
        return 1 / (1 + np.exp(-x))
    
    
    def numerical_derivative(f, input_data):
        delta_x = 1e-4
        ret = np.zeros_like(input_data)
        it = np.nditer(input_data, flags=['multi_index'])
    
        while not it.finished:
            idx = it.multi_index
            tmp_val = input_data[idx]
    
            input_data[idx] = float(tmp_val) + delta_x
            fx1 = f(input_data)
    
            input_data[idx] = float(tmp_val) - delta_x
            fx2 = f(input_data)
            ret[idx] = (fx1 - fx2) / (2 * delta_x)
    
            input_data[idx] = tmp_val
            it.iternext()
    
        return ret
    
    
    class NeuralNetwork:
    
        def __init__(self, input_nodes, hidden_nodes, output_nodes):
            self.__input_nodes = input_nodes
            self.__hidden_nodes = hidden_nodes
            self.__output_nodes = output_nodes
    
            self.__learning_rate = 1e-3
    
            self.__W2 = np.random.rand(input_nodes, hidden_nodes)
            self.__b2 = np.random.rand(hidden_nodes)
    
            self.__W3 = np.random.rand(hidden_nodes, output_nodes)
            self.__b3 = np.random.rand(output_nodes)
    
            self.__data = np.array([])
            self.__one_hot = np.array([])
    
        def __feed_forward(self):
            delta = 1e-7
    
            z2 = np.dot(self.__data, self.__W2) + self.__b2
            a2 = sigmoid(z2)
    
            z3 = np.dot(a2, self.__W3) + self.__b3
            y = sigmoid(z3)
    
            return -np.sum(self.__one_hot * np.log(y + delta) + (1 - self.__one_hot) * np.log(1 - y + delta))
    
        def loss_val(self):
            delta = 1e-7
    
            z2 = np.dot(self.__data, self.__W2) + self.__b2
            a2 = sigmoid(z2)
    
            z3 = np.dot(a2, self.__W3) + self.__b3
            y = sigmoid(z3)
    
            return -np.sum(self.__one_hot * np.log(y + delta) + (1 - self.__one_hot) * np.log(1 - y + delta))
    
        def predict(self, input_data):
            z2 = np.dot(input_data, self.__W2) + self.__b2
            a2 = sigmoid(z2)
    
            z3 = np.dot(a2, self.__W3) + self.__b3
            y = sigmoid(z3)
    
            return np.argmax(y)
    
        def accuracy(self, test_data):
            count = 0
            for index in range(len(test_data)):
                label = int(test_data[index, 0])
                data = test_data[index, 1:]
                predicted_val = self.predict(data)
                if predicted_val == label:
                    count += 1
    
            print('Accuracy = ', 100 * (count / float(len(test_data))))
    
        def train(self, train_data):
            label = int(train_data[0])
            self.__data = (train_data[1:] / 255.0 * 0.99) + 0.01
            self.__one_hot = np.zeros(self.__output_nodes) + 0.01
            self.__one_hot[label] = 0.99
    
            f = lambda x: self.__feed_forward()
            self.__W2 -= self.__learning_rate * numerical_derivative(f, self.__W2)
            self.__b2 -= self.__learning_rate * numerical_derivative(f, self.__b2)
            self.__W3 -= self.__learning_rate * numerical_derivative(f, self.__W3)
            self.__b3 -= self.__learning_rate * numerical_derivative(f, self.__b3)
    
    
    mnist = NeuralNetwork(784, 50, 10)
    for step in range(30001):
        mnist.train(train_data[step])
    
        if step % 400 == 0:
            print('step = ', step, 'loss_val = ', mnist.loss_val())
    
    mnist.accuracy(test_data)
    

    '인공지능' 카테고리의 다른 글

    AI 필체인식(Mnist) Back propagation 구현  (1) 2020.06.07
    AI Back propagation(오차역전파)  (1) 2020.06.06
    딥러닝 기초 (XOR 문제 해결)  (0) 2020.06.01
    AI Multi layer (XOR 문제)  (0) 2020.05.29
    AI Logistic regression 예제  (0) 2020.05.26

    댓글

Designed by Tistory.