[내 신경망 만들기/2부] 3. 손글씨 인식 신경망(MNIST 데이터 셋)
1. 개요
2. 파이썬 신경망 기본틀
2-1. 크래스 초기화 함수, __init__()
2-2. 초기 가중치
2-3. 조회 함수 , query()
2-4. 훈련 함수, train()
3. 신경망
----------------------------------------------------------------------------------------------
[참고서] Make Your Own Neural Networks, Tariq Rashid [book][검색링크]
----------------------------------------------------------------------------------------------
1. 개요
MNIST(Modified National Institute of Standards and Technology) 데이터 셋은 손글씨 이미지를 모아놓은 자료로서 다양하게 구현한 신경망의 성능을 평가할 때 널리 활용된다. 신경망을 처음 공부하면서 만든 "내 신경망"의 시험 대상으로 활용되어 딥러닝 분야의 'Hello World'라고 할 수 있다[링크]. 신경망의 기본 틀은 앞서 만들어 놓은 단순 신경망[링크]을 그대로 사용한다. 다만 각 층을 구성하는 노드(또는 신경 세포)의 갯수만 늘렸을 뿐이다. 개별 신경세포는 아주 단순하지만 수없이 많은 세포들이 모여 구성한 망은 놀라운 결과를 보여준다. 복잡계를 단순화시켜 그로부터 규칙을 찾아내오던 전통적인 지적 활동에 비하면 신경망은 '단순 무식'하게 보인다.
2. 이미지 시현
MNIST 데이터 셋의 규모는 학습용으로 6만개의 손글씨 이미지, 시험용으로 1만개의 손글씨 이미지로 구성되었다. 각 이미지는 256단계의 단색 화소가 가로 28 세로 28개로 구성된다. 데이터 셋은 LeCunn의 웹사이트[링크]에서 배포되었으나 워낙 다양한 형식으로 널리 퍼져 있어서 지금은 해당 자료가 보이지 않는다.
내 신경망에서 사용할 MNIST 데이터 셋의 형식은 CSV(Comma Separated Values)로서 다음과 같다.
2,0,0,0,0,,......,0,116,125,171,255,255,150,93,0,0,.....,0,0,0,0
첫번째 값은 해당 이미지의 숫자이며 이어 784(=28x28)개의 화소값이다.
2-1. 이미지 시현(파이썬)
이미지 시현하는 파이썬 코드plot_data.py 는 다음과 같다.
# Plot hand written image with CSV(Comma Separated Value)
data_file = open("mnist_dataset/mnist_train_100.csv", 'r')
data_list = data_file.readlines()
data_file.close()
print(F"There's {len(data_list)} Data lists.")
print(F"0-th Data List: \n{data_list[0]}")
읽을 CSV 파일을 열어 한줄을 읽어 문자열 변수 data_list에 저장한다.
import matplotlib.pyplot
배열로 쉽세 다루기 위한 numpy 모듈과 데이터 가시롸 모듈 matplotlib를 들여왔다.
all_values = data_list[1].split(',')
긴 문자열에서 콤마(,) 기호로 분리된 값들을 1차원 배열로 변환한다.
# values and turn them into an array which has a shape of
image_array = numpy.asfarray(all_values[1:]).reshape((28,28))
리스트 all_values 에서 첫번째 값을 제외한 나머지를 28x28의 행렬로 재구성하여 부동 소수점 2차원 배열로 변환한다.
matplotlib.pyplot.imshow(image_array,cmap='Greys',interpolation='None')
matplotlib.pyplot.show()
파이썬 모듈 matplotlib에 행렬 데이터를 시각화 해주는 방법들을 갖추고 있다. 이를 이용하면 단숨에 데이터를 시각화 할 수 있다.
$ python3 plot_data.py
파이썬은 자료형 선언을 해줄 필요 없이 할당되는 객체에 의해 결정된다. 문자열로부터 숫자 배열로 변환하는 소속함수를 갖추고 있다. 매우 높은 추상성을 추구하는 파이썬의 자료형은 자료 처리를 위해 많은 사람들이 요구하는 기능들은 갖추고 있어서 코딩의 수고를 덜어준다. 이는 파이썬에 열광하는 이유이기도 하다.
2-2. 이미지 시현 (C++)
C++ 역시 상당히 높은 수준의 프로그래밍 언어다. 각종 자료처리와 시각화를 위해 헤아릴 수 없을 만큼 다양한 라이브러리가 제공되고 있지만 C++ 언어 학습을 위해 고도의 라이브러리를 배제하고 MNIST 데이터 시연 프로그램을 작성하면 다음과 같다.
// Plot hand written image with CSV(Comma Separated Value)
// Filename: plot_data.cpp
//
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <SDL2/SDL.h>
#include <unistd.h> // sleep()
#include <string.h>
#define SIZE_OF_BOX 10
CSV 형식을 다루는 공개 라이브러리가 있지만 그리 복잡하지 않으므로 직접 작성하기로 한다. 파일을 다루고(stdlib.h) 문자열 변수를 처리하는 함수들(string.h)이 기본적으로 제공 된다.
{
FILE *fp;
char *line = NULL;
size_t len = 0;
ssize_t read;
if (fp == NULL) {
printf("Error Opening CSV file\n");
return false;
}
do {
printf("Line NOT found\n");
return false;
}
콤마(,)기호로 분리된 문자열을 다루는 표준 함수는 없으므로 목적에 맞게 처리해 주어야 한다.
if (line[i]>=0x30 && line[i]<= 0x39)
buff[j++] = line[i];
else if (line[i]==',' || line[i]=='\n')
buff[j] = 0x00;
image[k++] = (uint8_t)atoi(buff);
j = 0;
if (k>(28*28+1)) break;
}
}
앞서 열었던 파일을 닫고,
fclose(fp);
읽은 데이터가 목적에 맞는지 확인한다.
else return true;
}
파일에서 읽은 이미지를 시현해보자. C++ 프로그래밍에서 그래픽을 다루는 다양한 방법과 라이브러리가 있지만 SDL이 그중 쉽게 사용할 수 있다. SDL(https://www.libsdl.org/)은 게임 제작용으로 배포되는 오픈-소스 라이브러리다. 그래픽 뿐만 아니라 키보드, 마우스 등 주변장치의 제어와 쓰레드 프로그래밍을 포함하여 다양한 API들을 구비하고 있어서 시스템 모델링에 매우 유용하다. 손글씨 문자 이미지를 시현하는 함수를 작성하면 다음과 같다.
CSV 파일을 열어 해당 nImage 번째 이미지 자료 읽어온다. CSV에서 읽은 이미지를 저장할 변수는 용도에 맞게 미리 선언되어 있어야 한다. 손글씨 이미지의 각 화소는 256단계 값이므로 부호없는 8비트 uint8_t 형으로 선언되었다.
return false;
SDL 창에 모양을 내보기로 한다. 몇번째 이미지 인지 창의 타이틀에 표시하였다.
char szTitle[32];
화소점을 확대하여 시현하기 위해 상자를 그린 후 밝기 단계에 맞춰 채운다.
rect.y = 0; // Y position
rect.w = SIZE_OF_BOX; // Width
rect.h = SIZE_OF_BOX; // Height
{
for (int col=0; col<28; col++)
{
SDL_SetRenderDrawColor(renderer,
SDL_RenderFillRect(renderer, &rect);
rect.x += SIZE_OF_BOX; // X position
n++;
}
rect.x = 0;
rect.y = SIZE_OF_BOX*(n/28); // Y position
}
SDL_RenderPresent(renderer);
return true;
}
{
// SDL2-----------------------------------------------------------------
SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;
SDL_Event event;
fprintf(stderr, "Plottig MNIST dataset. Use Arrow keys.....");
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
fprintf(stderr, "SDL Initialization Fail: %s\n", SDL_GetError());
return -1;
}
window = SDL_CreateWindow("Plotting Data",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
28*SIZE_OF_BOX, 28*SIZE_OF_BOX,
SDL_WINDOW_SHOWN);
if (!window)
{
fprintf(stderr, "SDL Initialization Fail: %s\n", SDL_GetError());
SDL_Quit();
return -1;
}
SDL_SetWindowResizable(window, SDL_FALSE);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
// Event Loop --------------------------------------------------------------
uint8_t image[28*28+1];
int nImage = 1;
bool quit = false;
while(!quit)
{
if(SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
quit = true;
break;
case SDL_KEYDOWN:
switch( event.key.keysym.sym )
{
case SDLK_ESCAPE:
quit = true;
break;
case SDLK_UP:
case SDLK_LEFT:
//nImage--;
break;
case SDLK_DOWN:
case SDLK_RIGHT:
//nImage++;
break;
default:
break;
}
break;
case SDL_KEYUP:
switch( event.key.keysym.sym )
{
case SDLK_UP:
case SDLK_LEFT:
if (Draw_Charater( CSV_FILENAME, renderer, window, nImage))
nImage--;
else
quit = true;
break;
case SDLK_DOWN:
case SDLK_RIGHT:
if (Draw_Charater( CSV_FILENAME, renderer, window, nImage))
nImage++;
else
quit = true;
break;
default:
break;
}
break;
default:
break;
}
}
else
usleep(100);
}
EXIT:
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
}
해 보자.
https://github.com/GoodKook/ETRI-0.5um-CMOS-MPW-Std-Cell-DK/blob/main/Projects/MYONN/3_Plotting_MNIST_Dataset_C%2B%2B/plot_data.cpp
3Blue1Brown-neural networks
https://www.3blue1brown.com/?topic=neural-networks
https://www.youtube.com/playlist?list=PLZHQObOWTQDNU6R1_67000Dx_ZCJB-3pi
3Blue1Brown 한국어 - ML/DL
https://www.youtube.com/playlist?list=PLkoaXOTFHiqhM4MeCMrS016jOWKfIXTjK
이미지 분류: 다층 퍼셉트론(MLP)으로 손글씨 숫자(MNIST) 인식
https://youtu.be/gh8UR3nw2uk
딥러닝의 핵심 활성화 함수(1): Sigmoid의 특징과 한계
딥러닝의 핵심 활성화 함수(2):Tanh, ReLU, Leaky ReLU
예제로 배우는 역전파(backpropagation)
https://youtu.be/Ku1xUFK9I3Y
합성곱 신경망(CNN) (기초이론)
https://youtu.be/h1Io450Igrg
합성곱 신경망(CNN) (MNIST 실습)
https://youtu.be/IHbsSmRbcrw
https://en.wikipedia.org/wiki/Edge_detection
https://en.wikipedia.org/wiki/Canny_edge_detector
댓글 없음:
댓글 쓰기