강몬드의 프로그래밍 이야기

신경망과 딥러닝 6.Network to Classify Digits 본문

학습/딥러닝

신경망과 딥러닝 6.Network to Classify Digits

강몬드 2016. 3. 20. 16:50

Network to Classify Digits

   이번엔 stochastic gradient descent알고리즘과 MNIST학습 데이터를 사용하여 손글씨 문자를 인식할 수 있는 학습 프로그램을 작성해보자. Python 2.7 version을 사용하여 짧은 프로그램만으로 구현할 수 있다. 코드로만 74줄이다! 먼저 MNIST데이터가 필요하다. 너가 git를 사용한다면 딥러닝 자료들에 대한 코드들을 다음의 명령어로 clone할 수 있다.


git clone https://github.com/mnielsen/neural-networks-and-deep-learning.


   git를 사용하지 않는다면 data와 code를 다음 링크에서 다운 받자. 요오기


   이전에 MNIST data에 대해서 설명했을 때, 그것들이 60,000개의 training images와 10,000개의 test images로 나뉜다고 했었다. 공식적인 MNIST의 설명이다. 사실 우리는 더 작게 나눈다. test images는 그대로 두고, 60,000개의 MNIST training set을 50,000개의 신경망 학습에 사용될 데이터와 10,000개의 validation set으로 두 부류로 나눈다. 이번 내용에선 validation set을 사용하진 않지만 추후에 내용에서 신경망의 learning rate와 등등의 hyper parameters를 어떻게 설정해야하는지 설명하는 내용과 함께 사용할 예정이다. validation set이 MNIST데이터 구조에서 구체적으로 정의되어 나오진 않았지만 대부분의 사람들은 이 방식으로 데이터를 나눠 신경망에 validation set을 사용한다. 여기서도 마찬가지로 60,000개의 training images가 아닌 50,000개 images로만 데이터 셋을 가진다. 

 

   MNIST 데이터를 구했으면 Python library에서 선형대수를 구현하는 Numpy가 필요하다. Numpy가 설치되지 않았다면 여기서 설치할 수 있다. 요오기 


   먼저 신경망 코드의 핵심 특징들을 살펴보자. 그 중심은 신경망을 가르키는 Network class이다. 아래에서 간단한 Network 객체의 초기화 코드를 살펴보자. 


class Network(object):

    def __init__(self, sizes):
        self.num_layers = len(sizes)
        self.sizes = sizes
        self.biases = [np.random.randn(y, 1) for y in sizes[1:]]
        self.weights = [np.random.randn(y, x) 
                        for x, y in zip(sizes[:-1], sizes[1:])]

   이 코드에서 리스트 구조 sizes는 각각 레이어들의 뉴런 개수를 갖고 있다. 예를 들어서 첫 번째 레이어에서 2개 뉴런, 

두 번째 레이어 3개 뉴런, 마지막 레이어는 1개의 뉴런을 갖고 있다면 다음과 같이 초기화할 수 있다. net = Network([2, 3, 1])


Network 객체의 biases와 weights는 평균 0, 표준편차 1을 갖는 가우시안 분포 생성하는 Numpy np.random.randn함수로 

랜덤하게 초기화된다. 뒤 내용에서 weights와 biases 초기값 지정하는 방법에 대한 내용도 정리할 예정이고 여기서는 

랜덤한 초기에서 학습을 시작한다.



biases와 weights의 값들은 Numpy matrices의 리스트로 저장된다. 예를 들어, net.weights[1]은 두 번째 레이어와 

세번 째 레이어의 뉴런들이 연결된 weights값이 저장된 Numpy matrix이다. net.weights[1]를 여기서 matrix w라고 표시하자.

는 두 번째 레이어 뉴런과 세 번째 레이어 뉴런사이에 연결된 가중치이다. 


위 식에서 a는 두 번째 레이어의 뉴런들의 활성 벡터이다. 구하기 위해 weight 매트릭스 w와 a를 곱한 뒤, biases

b 벡터를 더한다. 그리고 시그마 함수를 wa + b 벡터 모든 요소에다가 적용한다.


이 모든 내용들은 코드로 쉽게 작성할 수 있다. 시그모이드 함수를 먼저 정의를 내리면,


def sigmoid(z):
    return 1.0/(1.0+np.exp(-z))

 

입력 z는 벡터 또는 Numpy array일 때, Numpy는 자동적으로 시그모이드 함수를 요소 단위로 적용한다.


이번엔 입력 a가 주어졌을 때 ouput*을 반환하는 Network클래스의 feed forward 함수를 정의하자.

   
 def feedforward(self, a):
        """Return the output of the network if "a" is input."""
        for b, w in zip(self.biases, self.weights):
            a = sigmoid(np.dot(w, a)+b)
        return a

 

우리가 원하는 목표는 Network객체가 학습하기를 원한다. 이를 구현하기 위해 stochastic gradient descent를 구하는

SGD method를 작성하자. 아래 코드를 살펴보자.

    
def SGD(self, training_data, epochs, mini_batch_size, eta,
            test_data=None):
        """Train the neural network using mini-batch stochastic
        gradient descent.  The "training_data" is a list of tuples
        "(x, y)" representing the training inputs and the desired
        outputs.  The other non-optional parameters are
        self-explanatory.  If "test_data" is provided then the
        network will be evaluated against the test data after each
        epoch, and partial progress printed out.  This is useful for
        tracking progress, but slows things down substantially."""
        if test_data: n_test = len(test_data)
        n = len(training_data)
        for j in xrange(epochs):
            random.shuffle(training_data)
            mini_batches = [
                training_data[k:k+mini_batch_size]
                for k in xrange(0, n, mini_batch_size)]
            for mini_batch in mini_batches:
                self.update_mini_batch(mini_batch, eta)
            if test_data:
                print "Epoch {0}: {1} / {2}".format(
                    j, self.evaluate(test_data), n_test)
            else:
                print "Epoch {0} complete".format(j)


training_data는 training 입력과 목표 출력을 가르키는 (x,y) 튜플 리스트 구조로 되어있다. 변수 epochs와

mini_batch_size는 예상했던 것처럼 학습할 세대의 수와, 샘플링할 때 사용할 mini-batches의 크기이다. eta는

learning rate, (eta)를 말한다. 만약 옵션으로 test_data가 주어진다면 프로그램을 Network를 학습을 하는 각각의

세대를 마치고 평가하여 보여준다. 이는 학습과정을 따라가며 보기 좋지만 학습이 느려질 수 있다.




출처 : http://neuralnetworksanddeeplearning.com/index.html











Comments