인공지능

AI 필체인식(Mnist) Back propagation 구현

KyooDong 2020. 6. 7. 15:10
728x90

2020/06/06 - [AI] - AI Back propagation(오차역전파)

 

AI Back propagation(오차역전파)

2020/06/03 - [AI] - 딥러닝 MNIST 필기체 인식 딥러닝 MNIST 필기체 인식 Mnist 는 딥러닝 공부를 할 때 기초적이면서도 흥미로운 연습 문제에요 Training Data set(csv) 과 Test Data set(csv) 파일 링크입니다...

bubble-dev.tistory.com

이 전 글에서 오차역전파 공식을 유도하는 법에 대해서 알아봤습니다.

아래 코드의 수식들은 이 전글에서 유도된 공식으로 궁금하신 분들은 보고 오시면 좋을것같네요

 

코드

import numpy as np

# 데이터 로딩
test_data = np.loadtxt('mnist_test.csv', delimiter=',', dtype=np.float32)
train_data = np.loadtxt('mnist_train.csv', delimiter=',', dtype=np.float32)

# 시그모이드
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

class NeuralNetwork:
    def __init__(self, input_nodes, hidden_nodes, output_nodes, learning_rate):
        self.__input_nodes = input_nodes
        self.__hidden_nodes = hidden_nodes
        self.__output_nodes = output_nodes

        self.__learning_rate = learning_rate

        # 임의의 가중치 및 바이어스 할당
        self.__W2 = np.random.randn(input_nodes, hidden_nodes) / np.sqrt(input_nodes / 2)
        self.__b2 = np.random.rand(hidden_nodes)
        self.__W3 = np.random.randn(hidden_nodes, output_nodes) / np.sqrt(hidden_nodes / 2)
        self.__b3 = np.random.rand(output_nodes)

        # 출력층
        self.__A3 = np.zeros([1, output_nodes])
        self.__Z3 = np.zeros([1, output_nodes])

        # 은닉층
        self.__A2 = np.zeros([1, hidden_nodes])
        self.__Z2 = np.zeros([1, hidden_nodes])

        # 입력층
        self.__A1 = np.zeros([1, input_nodes])
        self.__Z1 = np.zeros([1, input_nodes])

        self.loss_val = self.feed_forward

    def feed_forward(self):
        delta = 1e-7

        # 입력층 출력값 계산
        self.__A1 = self.__input_data
        self.__Z1 = self.__input_data

        # 은닉층 출력값 계산
        self.__Z2 = np.dot(self.__A1, self.__W2) + self.__b2
        self.__A2 = sigmoid(self.__Z2)

        # 출력층 출력값 계산
        self.__Z3 = np.dot(self.__A2, self.__W3) + self.__b3
        self.__A3 = sigmoid(self.__Z3)

        # 크로스 엔트로피
        return -np.sum(self.__target_data * np.log(self.__A3 + delta) + (1 - self.__target_data) * np.log((1 - self.__A3) + delta))

    def train(self, input_data, target_data):
        self.__input_data = input_data
        self.__target_data = target_data

        # 층별 출력값 계산
        self.feed_forward()

        # 출력값과 loss 를 이용한 W, b 갱신
        loss3 = (self.__A3 - self.__target_data) * (self.__A3 * (1 - self.__A3))
        self.__W3 = self.__W3 - self.__learning_rate * np.dot(self.__A2.T, loss3)
        self.__b3 = self.__b3 - self.__learning_rate * loss3

        loss2 = np.dot(loss3, self.__W3.T) * (self.__A2 * (1 - self.__A2))
        self.__W2 = self.__W2 - self.__learning_rate * np.dot(self.__A1.T, loss2)
        self.__b2 = self.__b2 - self.__learning_rate * loss2

    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
        A3 = sigmoid(Z3)

        return np.argmax(A3)

    def accuracy(self, test_data):
        count = 0
        for i in range(len(test_data)):
            label = int(test_data[i, 0])
            data = ((test_data[i, 1:] / 255.0) * 0.99) + 0.01
            predicted_data = self.predict(np.array(data, ndmin=2))

            if label == predicted_data:
                count += 1

        print("Accuracy = ", 100 * (count / len(test_data)))


nn = NeuralNetwork(784, 100, 10, 0.3)

# 반복횟수
epoches = 5

for e in range(epoches):
    for step in range(60000):
        label = int(train_data[step, 0])
        
        # Normalization
        data = ((train_data[step, 1:] / 255.0) * 0.99) + 0.01
        target_data = np.zeros(10) + 0.01
        target_data[label] = 0.99

        nn.train(np.array(data, ndmin=2), np.array(target_data, ndmin=2))

        if step % 400 == 0:
            print('step = ', step, ', errorval = ', nn.loss_val())


    nn.accuracy(test_data)

결과

반복(epochs) 1회차

 

반복(epochs) 5회차