첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
유용한 소스 코드가 있으면 icodebroker@naver.com으로 보내주시면 감사합니다.
블로그 자료는 자유롭게 사용하세요.

■ 다층 퍼셉트론 신경망 만들기 (MNIST)

----------------------------------------------------------------------------------------------------


NeuralNetwork.ipynb


NeuralNetwork.py

 

 

import numpy

import scipy.special

 

##################################################

# 신경망 클래스

##################################################

class NeuralNetwork:

 

    ##################################################

    # 생성자

    # inputNodeCount  : 입력 노드 수

    # hiddenNodeCount : 은닉 노드 수

    # outputNodeCount : 출력 노드 수

    # learningRate    : 학습률

    ##################################################

    def __init__(self, inputNodeCount, hiddenNodeCount, outputNodeCount, learningRate):

 

        self.inputNodeCount  = inputNodeCount

        self.hiddenNodeCount = hiddenNodeCount

        self.outputNodeCount = outputNodeCount

 

        self.inputHiddenWeightArray  = numpy.random.normal(0.0, pow(self.inputNodeCount , -0.5), \

                                           (self.hiddenNodeCount, self.inputNodeCount ))

        self.hiddenOutputWeightArray = numpy.random.normal(0.0, pow(self.hiddenNodeCount, -0.5), \

                                           (self.outputNodeCount, self.hiddenNodeCount))

 

        self.learningRate = learningRate

 

        self.activationFunction = lambda x: scipy.special.expit(x)

 

        pass

 

    ##################################################

    # 학습하기

    # sourceInputValueArray  : 소스 입력 값 리스트

    # sourceTargetValueArray : 소스 목표 값 리스트

    ##################################################

    def train(self, sourceInputValueArray, sourceTargetValueArray):

 

        inputValueArray  = numpy.array(sourceInputValueArray , ndmin = 2).T

        targetValueArray = numpy.array(sourceTargetValueArray, ndmin = 2).T

 

        # 은닉 계층으로 들어오는 신호를 계산한다.

        hiddenNodeInputValueArray = numpy.dot(self.inputHiddenWeightArray, inputValueArray)

 

        # 은닉 계층에서 나가는 신호를 계산한다.

        hiddenNodeOutputValueArray = self.activationFunction(hiddenNodeInputValueArray)

 

        # 출력 계층으로 들어오는 신호를 계산한다.

        outputNodeInputValueArray = numpy.dot(self.hiddenOutputWeightArray, hiddenNodeOutputValueArray)

 

        # 출력 계층에서 나가는 신호를 계산한다.

        outputNodeOutputValueArray = self.activationFunction(outputNodeInputValueArray)

 

        # 출력 계층의 오차를 계산한다. (실제 값 - 계산 값)

        outputNodeErrorArray = targetValueArray - outputNodeOutputValueArray

 

        # 은닉 계층의 오차는 가중치에 의해 나뉜 출력 계층의 오차들을 재조합해 계산한다.

        hiddenNodeErrorArray = numpy.dot(self.hiddenOutputWeightArray.T, outputNodeErrorArray)

 

        # 은닉 계층과 출력 계층 간의 가중치 오차를 업데이트 한다.

        self.hiddenOutputWeightArray += self.learningRate * \

            numpy.dot((outputNodeErrorArray * outputNodeOutputValueArray * (1.0 - outputNodeOutputValueArray)), \

                numpy.transpose(hiddenNodeOutputValueArray))

 

        # 입력 계층과 은닉 계층 간의 가중치 오차를 업데이트 한다.

        self.inputHiddenWeightArray += self.learningRate * \

            numpy.dot((hiddenNodeErrorArray * hiddenNodeOutputValueArray * (1.0 - hiddenNodeOutputValueArray)), \

                numpy.transpose(inputValueArray))

 

        pass

 

    ##################################################

    # 질의하기

    # sourceInputValueArray : 소스 입력 값 리스트

    ##################################################

    def query(self, sourceInputValueArray):

 

        inputValueArray = numpy.array(sourceInputValueArray, ndmin = 2).T

 

        # 은닉 계층으로 들어오는 신호를 계산한다.

        hiddenNodeInputValueArray = numpy.dot(self.inputHiddenWeightArray, inputValueArray)

 

        # 은닉 계층에서 나가는 신호를 계산한다.

        hiddenNodeOutputValueArray = self.activationFunction(hiddenNodeInputValueArray)

 

        # 출력 계층으로 들어오는 신호를 계산한다.

        outputNodeInputValueArray = numpy.dot(self.hiddenOutputWeightArray, hiddenNodeOutputValueArray)

 

        # 출력 계층에서 나가는 신호를 계산한다.

        outputNodeOutputValueArray = self.activationFunction(outputNodeInputValueArray)

 

        return outputNodeOutputValueArray

 

        pass

 

##################################################

# 신경망 객체를 생성한다.

##################################################

print("신경망 객체를 생성한다.")

 

inputNodeCount  = 784

hiddenNodeCount = 100

outputNodeCount = 10

 

learningRate = 0.1

 

neuralNetwork = NeuralNetwork(inputNodeCount, hiddenNodeCount, outputNodeCount, learningRate)

 

##################################################

# MNIST 학습 데이터를 로드한다.

##################################################

print("MNIST 학습 데이터를 로드한다.")

 

trainingDataFile = open("c:\\mnist_train.csv", 'r')

 

trainingDataList = trainingDataFile.readlines()

 

trainingDataFile.close()

 

print("학습 데이터 : %s건" % len(trainingDataList))

 

##################################################

# MNIST 학습 데이터를 사용해 신경망을 학습시킨다.

##################################################

print("MNIST 학습 데이터를 사용해 신경망을 학습시킨다.")

 

epochCount = 5

 

for epoch in range(epochCount):

 

    print("학습 주기 = ", epoch)

 

    for trainingData in trainingDataList:

 

        trainigDataArray = trainingData.split(',')

 

        # 학습에 사용되는 MNIST 숫자 이미지는 28×28 픽셀 = 784개 데이터를 갖으며 훈련 데이터 배열에서 두번째 컬럼 이후 부터 저장된다.

        testInputValueArray = (numpy.asfarray(trainigDataArray[1:]) / 255.0 * 0.99) + 0.01

 

        trainingTargetValueArray = numpy.zeros(outputNodeCount) + 0.01

 

        trainingTargetValueArray[int(trainigDataArray[0])] = 0.99

 

        neuralNetwork.train(testInputValueArray, trainingTargetValueArray)

 

        pass

 

    pass

 

print("학습 완료")

 

##################################################

# MNIST 테스트 데이터를 로드한다.

##################################################

print("MNIST 테스트 데이터를 로드한다.")

 

testDataFile = open("c:\\mnist_test.csv", 'r')

 

testDataList = testDataFile.readlines()

 

testDataFile.close()

 

print("테스트 데이터 : %s건" % len(testDataList))

 

##################################################

# MNIST 테스트 데이터를 사용해 신경망을 테스트한다.

##################################################

print("MNIST 테스트 데이터를 사용해 신경망을 테스트한다.")

 

scoreCardList = []

 

for testData in testDataList:

 

    testDataArray = testData.split(',')

 

    correctLabel = int(testDataArray[0])

 

    testInputValueArray = (numpy.asfarray(testDataArray[1:]) / 255.0 * 0.99) + 0.01

 

    testOutputValueArray = neuralNetwork.query(testInputValueArray)

 

    answerLabel = numpy.argmax(testOutputValueArray)

 

    if(answerLabel == correctLabel):

 

        scoreCardList.append(1)

 

        pass

 

    else:

 

        scoreCardList.append(0)

 

        pass

 

    pass

 

scoreCardArray = numpy.asarray(scoreCardList)

 

print("정확도 = ", scoreCardArray.sum() / scoreCardArray.size)

 

##################################################

# MNIST 테스트 데이터 1건을 사용해 신경망을 테스트한다.

# ※ 아나콘다에서만 실행한다.

##################################################

 

import matplotlib

%matplotlib inline

 

testDataArray = testDataList[200].split(',')

 

print("테스트 데이터 정답 : ", testDataArray[0])

 

testInputValueArray = (numpy.asfarray(testDataArray[1:]) / 255.0 * 0.99) + 0.01

 

testOutputValueArray = neuralNetwork.query(testInputValueArray)

 

print("테스트 결과 값 : ", numpy.argmax(testOutputValueArray))

print()

print(testOutputValueArray)

 

testDataImageArray = numpy.asfarray(testDataArray[1:]).reshape((28,28))

 

matplotlib.pyplot.imshow(testDataImageArray, cmap='Greys', interpolation='None')

 

----------------------------------------------------------------------------------------------------

※ 학습/훈련 데이터 파일은 아래 URL을 참조한다.


http://www.pjreddie.com/media/files/mnist_train.csv
http://www.pjreddie.com/media/files/mnist_test.csv

Posted by 사용자 icodebroker

댓글을 달아 주세요