2017년 6월 17일 토요일

딥러닝 Hello World - MNIST, CIFAR-10, COCO, VOC 학습 데이터 구조와 이미지넷

이 글은 딥러닝계의 Hello World 인 MNIST, CIFAR, COCO, VOC 데이터베이스 구조와 덥러닝 기술을 크게 발전시킨 세계 최대 이미지 학습 데이터 사이트 이미지넷을 소개한다.

MNIST 데이터베이스 구조
이 글은 yann.lecun.com/exdb/mnist (Yann LeCun. NYU, Director of AI Research at Facebook, Silver Professor of Computer Science at the Courant Institute of Mathematical Sciences) 를 참고하였다. 이외에 많이 사용되고 있는 테스트 데이터셋은 다음과 같다.
  • MNIST
  • PTB(Penn Tree Bank)
  • CIFAR-10, CIFAR-100
MNIST는 NYU의 Yann LeCun 사이트에서 다운로드 할 수 있다.
  train-images-idx3-ubyte.gz:  training set images (9912422 bytes) 
  train-labels-idx1-ubyte.gz:  training set labels (28881 bytes) 
  t10k-images-idx3-ubyte.gz:   test set images (1648877 bytes) 
  t10k-labels-idx1-ubyte.gz:   test set labels (4542 bytes)

이 사이트에서는 딥러닝 신경망 학습에 필요한 필기체 숫자 이미지 60,000 훈련 집합, 10,000개 테스트 집합을 제공한다. 이를 이용해, 패턴 인식 연구에 필요한 데이터 수집 노력을 줄일 수 있다.

이 이미지는 원래 흑백이었지만, 20 x 20 픽셀 크기에 맞춰 정규화된 그레이 이미지로 처리되었다. 이를 위해, 안티 앤리어싱 기술을 적용하여, 이미지 펙셀 중심을 계산하여, 28x28 크기로 변환하였다.

MNIST 데이터는 SD-3와 SD-1이 있으며, SD3가 노이즈가 별로 없고 쉽게 인식할 수 있다.
참고로, SD-1은 500명의 사람이 쓴 58,527 이미지가 포함되어 있다.

MNIST 파일 형식은 MSB(Most Significatn Bit. 가장 큰 숫자를 왼쪽에 기록하는 자리 표기법) 방식으로 저장된다. 각 파일의 형식은 다음과 같다.

TRAINING SET LABEL FILE (train-labels-idx1-ubyte):
[offset] [type]          [value]          [description] 
0000     32 bit integer  0x00000801(2049) magic number (MSB first) 
0004     32 bit integer  60000            number of items 
0008     unsigned byte   ??               label 
0009     unsigned byte   ??               label 
........ 
xxxx     unsigned byte   ??               label

라벨값은 0에서 9까지이다.

TRAINING SET IMAGE FILE (train-images-idx3-ubyte):
[offset] [type]          [value]          [description] 
0000     32 bit integer  0x00000803(2051) magic number 
0004     32 bit integer  60000            number of images 
0008     32 bit integer  28               number of rows 
0012     32 bit integer  28               number of columns 
0016     unsigned byte   ??               pixel 
0017     unsigned byte   ??               pixel 
........ 
xxxx     unsigned byte   ??               pixel
픽셀들은 row-wise로 구성되어 있다. 픽셀 값은 0에서 255이다. 0은 배경(흰색), 255는 전경색(검정색)을 의미한다.

TEST SET LABEL FILE (t10k-labels-idx1-ubyte):
[offset] [type]          [value]          [description] 
0000     32 bit integer  0x00000801(2049) magic number (MSB first) 
0004     32 bit integer  10000            number of items 
0008     unsigned byte   ??               label 
0009     unsigned byte   ??               label 
........ 
xxxx     unsigned byte   ??               label
라벨값은 0에서 9까지이다.

TEST SET IMAGE FILE (t10k-images-idx3-ubyte):
[offset] [type]          [value]          [description] 
0000     32 bit integer  0x00000803(2051) magic number 
0004     32 bit integer  10000            number of images 
0008     32 bit integer  28               number of rows 
0012     32 bit integer  28               number of columns 
0016     unsigned byte   ??               pixel 
0017     unsigned byte   ??               pixel 
........ 
xxxx     unsigned byte   ??               pixel
픽셀들은 row-wise로 구성되어 있다. 픽셀 값은 0에서 255이다. 0은 배경(흰색), 255는 전경색(검정색)을 의미한다.

IDX 파일 포맷은 간략한 벡터 형식으로 되어 있다.
magic number
size in dimension 0
size in dimension 1
size in dimension 2
.....
size in dimension N
data

매직 넘버는 정수형(MSB)이다. 첫번째 2바이트는 항상 0이고, 세번째 바이트 코드는 다음을 의미한다.
0x08: unsigned byte 
0x09: signed byte
0x0B: short (2 bytes)
0x0C: int (4 bytes)
0x0D: float (4 bytes)
0x0E: double (8 bytes)



CIFAR 데이터베이스 구조
CIFAR-10과 CIFAR-100은 80 백만개의 소형 이미지 데이터셋이다. 이 데이터는 Alex Krizhevsky, Vinod Nair, Geoffrey Hinton이 모았다. 이 글은 Krizhevsky 홈페이지를 참고하였다. 이 이미지를 이용해, 다양한 머신러닝 기법이 테스트되고 있다(예. 텐서플로우 기반 CNN 이미지 훈련)

CIFAR-10은 60000 32x32 컬러 이미지로 10개 클래스로 구성된다. 50000개의 훈련 이미지와 10000개의 테스트 이미지가 있다.

데이터셋은 5개 훈련 배치 셋과 한개 테스트 배치 셋으로 구분되며, 각 셋은 10000 개 이미지이다. 테스트 배치 셋은 1000 개 선택된 임의 이미지가 포함되어 있다. 훈련 배치 셋은 각 클래스별로 5000개 이미지로 구성된다.

이미지넷 폴더 구조는 다음과 같다.
|-- annotation.txt
|-- 0001.jpg
|-- 0002.jpg
|... 
|-- n.jpg

라벨 정보가 포함된 annotation 파일 구조는 다음과 같다.
0001.jpg <label ID>
0002.jpg <label ID>
...
n.jpg <label ID>

다음은 다운로드 링크이다.
VersionSizemd5sum
CIFAR-10 python version163 MBc58f30108f718f92721af3b95e74349a
CIFAR-10 Matlab version175 MB70270af85842c9e89bb428ec9976c926
CIFAR-10 binary version (suitable for C programs)162 MBc32a1d4

COCO 학습 데이터셋 구조
COCO는 Common Objects in Context 의 약자로, 대규모 객체 인식, 세그먼테이션, 데이터셋 캡션을 위해 고려된 학습 데이터셋이다. COCO는 330,000 개 이미지와 200,000개 라벨링된 객체 정보를 제공하고, 80개 객체 카테고리를 제공한다. 이런 이유로, 객체 탐지 및 세그먼테이션 딥러닝 모델 학습 기본 데이터셋으로 널리 활용되고 있다.
 
참고로, 이 데이터셋은 Google Brain, Microsoft, Caltech, Chicago, Cornell Tech, FAIR, Georgia Tech, CMU 등의 연구진 간 협업으로 개발된 것이다.


코코는 5개 annotation 유형을 사용한다. 이는 객체 검출, 키포인트 검출, stuff segmentation, panoptic segmentation, 이미지 캡셔닝에 사용된다.


코코는 JSON파일 포맷이며, 경계 박스 등 정보를 포함한다.
  • info: dataset information
  • license: image license
  • categories: image category list
  • images: image information
  • annotations: 각 image의 개별 객체 annotation 정보 
다음 그림은 각 요소의 예시이다. 
Annotation은 이미지 별 개별 객체정보를 담는다.
  • segmentation: segmentation masks 객체 정의를 위한 다각형 정점 x, y 좌표
  • area: bounding box area (pixel)
  • iscrowd: 만약 단일 객체 세그먼트이면 이 값은 0이다. 한 이미지에 여러 객체들이 있다면, 이 값은 1로 설정된다. 이 경우, RLE(run length encoding) 이 사용된다. 이를 통해, 세그먼트 다각형 정보를 압축해 처리 속도를 개선하고 용량을 줄일 수 있다.
  • imageid: image ID.  ID는 image section에서 정의된다.
  • bbox: 경계 박스 정의. top left x top left y, width, height. 
  • category: category 정의.
  • id: annotation ID

이렇게 정의된 데이터 파일은 다음 폴더 구조로 정의된다.
|-- val
      |-- 0001.jpg
      |-- 0002.jpg
      ... 
      |-- n.jpg
|-- annotations 
      |-- instances_val.json


데이터셋은 다음 링크에서 다운로드 받을 수 있다.
Pascal VOC 학습 데이터셋 구조
Pascal(Pattern Analysis, Statistical Modeling and Computational Learning) VOC(Visual Object Classes)는 객체 탐지를 위한 표준 이미지 데이터셋을 제공한다. 이 학습 데이터셋은 파스칼 VOC 챌린지 대회에서 개발된 것으로 객체 인식 기술을 겨루는 국제 대회에서 주어진 것이다.이 대회는 2005년부터 2012년까지 진행되었고, 총 20가치 객체에 대해 우승자를 가리는 대회였다. 이 대회를 통해 비전 분야에 여러 here와 혁신적인 기술이 탄생했다.

코코와 다른 점은 VOC는 XML을 사용하고, 개별 이미지별로 라벨 정보 파일이 존재하며, 경계 박스가 최상단 좌표, 최하단 좌표란 점이다.
데이터 형식

VOC는 폴더별로 이미지가 저장된다. 크기는 이미지 폭, 높이, 깊이(컬러의 경우 3)를 정의한다. 객체는 name, pose, truncated, difficult, bndbox를 포함하고 있다. 이 중에 truncated는 이미지에 포함된 일부 짤려진 객체인 경우 1로 설정되며, 그렇지 않으면 0이다. difficult는 인식이 어려운 객체인 경우 1, 아니면 0을 설정한다.

VOC 데이터 폴더 구조는 다음과 같다.
|-- VOCdevkit
    |-- VOC
        |-- Annotations
              |-- 0001.xml
              |-- 0002.xml 
              ... 
              |-- n.xml 
        |-- ImageSets
              |-- Layout
                  |-- test.txt
              |-- Main
                  |-- 0001_test.txt
                  |-- 0002_test.txt 
                  ... 
                  |-- n_test.txt 
              |-- Segmentation
                  |-- test.txt 
        |-- Images
              |-- 0001.jpg
              |-- 0002.jpg 
              ... 
              |-- n.jpg 
        |-- SegmentationClass
              |-- 0001.png
              |-- 0002.png
              ... 
              |-- n.png
        |-- SegmentationObject
              |-- 0001.png
              |-- 0002.png
              ... 
              |-- n.png


데이터셋은 다음에서 다운로드 가능하다.
참고로, 아래 스크립트는 라벨링에 많이 사용하는 BBox-Label-Tool 에서 생성된 데이터 파일들을 VOC 포맷으로 변환해 주는 스크립트이다. 필요하다면, 목적에 맞게 수정해 사용하길 바란다.
# Programming by KTW# email. laputa99999@gmail.com# Note. You are responsible for any problems caused by use this program.import os
import glob
from os import listdir, getcwd
from tokenize import tokenize, untokenize, NUMBER, STRING, NAME, OP

# Modify the below parametercategoryCount = 2 
names = ['none', 'con_eq', 'worker', 'none']
width = 500height = 500
# Programroot = ''def createVOCfolders(root):
    try:
        os.mkdir(root)
        os.mkdir(root + 'Annotations')
        os.mkdir(root + 'ImageSets')
        os.mkdir(root + 'JPEGImages')
    except:
        return    return
def saveVOC(folder, filename, imageName, category, object, w, h, BBoxList):
    try:
        file = open(folder + filename, "w")

        file.write('<annotation>\n')
        file.write('<folder>' + folder + '</folder>\n')
        file.write('<owner><name>ktw</name></owner>\n')
        file.write('<size><width>' + str(w) + '</width>' + '<height>' + str(h) + '</height>' + '<depth>3</depth></size>\n')
        file.write('<segmented>1</segmented>\n')
        for BBox in BBoxList:  # type: object            file.write('<object>\n')
            file.write('<name>' + object + '</name>\n')
            file.write('<pose>Unspecified</pose>\n')
            file.write('<truncated>0</truncated>\n')
            file.write('<difficult>0</difficult>\n')
            file.write('<bndbox>\n')
            file.write('<xmin>' + str(BBox[0]) + '</xmin>\n')
            file.write('<ymin>' + str(BBox[1]) + '</ymin>\n')
            file.write('<xmax>' + str(BBox[2]) + '</xmax>\n')
            file.write('<ymax>' + str(BBox[3]) + '</ymax>\n')
            file.write('</bndbox>\n')
            file.write('</object>\n')
        file.write('</annotation>\n')
    except:
        return    return
def convertBBoxToVOC(root, labelDir, category, w, h):
    labelList = glob.glob(os.path.join(labelDir, '*.*'))
    for filename in labelList:
        BBoxList = []
        try:
            file = open(filename, "r")
            count = file.readline()
            count = count.rstrip('\n')
            num = int(count)
            for line in range(num):
                BBox = file.readline()
                BB = BBox.split()
                points = []
                for pt in BB:
                    points.append(int(pt))
                BBoxList.append(points)
        except:
            continue
        object = names[category]

        name = os.path.basename(filename)
        name, extension = os.path.splitext(name)
        vocfile = name + '.xml'        saveVOC(root + 'Annotations/', vocfile, name, category, object, w, h, BBoxList)
    return
wd = getcwd()
root = wd + '/VOC_data/'createVOCfolders(root)

for index in range(categoryCount):
    index = index + 1    imageDir = getcwd() + '/'    imageDir = imageDir + os.path.join(r'BBox/Images/', '%03d' % (index))
    imageList = glob.glob(os.path.join(imageDir, '*.*'))

    if len(imageList) == 0:
        print('No images found in the specified dir!')

    labelDir = getcwd() + '/'    labelDir = labelDir + os.path.join(r'BBox/Labels/', '%03d' % (index))

    convertBBoxToVOC(root, labelDir, index, width, height)

이미지 넷
이미지넷은 Fei-Fei Li 교수가 2007년 제안한 학습용 이미지 데이터베이스 구축 아이디어에서 시작된 프로젝트이다. 비전 기술 개발 시 필요한 세계 최대 학습용 이미지 데이터베이스가 무료로 제공된다.

이미지넷은 무료로 학습용 데이터베이스를 제공하고 있다. 이미지넷 초창기 Fei-Fei Li 와 주변 동료들은 약 15,000,000 이미지에 대한 라벨링 작업을 큰 R&D펀드 없이 진행하였으며, 이후 도움을 준 세계 각국의 연구자들도 그녀의 아이디어에 영감을 받아, 개인의 시간과 자원을 공헌하였다.

이미지넷은 매년 비전 기술의 사물 인식 정확도를 기준으로 평가하는 대회를 열고 있다. 대회에서 우수한 알고리즘을 평가된 기술은 큰 주목을 받고, 오픈소스로 공개되어, 많은 사람들에게 도움을 주고 있다. 2012년 캐나다 토론토 대학의 알렉스 크리제스브키는 GPU 기반 CNN 딥러닝 모델(ImageNet Classification with Deep Convolutional Neural Networks, 2012)을 이용해, 80% 이상 정확도를 보여주어, 사람들을 놀라게 했다. 그는 이 기술을 오픈소스로 공개하였으며, 마이크로소프트는 이 기술을 기반으로 정확도를 96%까지 끌어올렸다(관련 기사).

이미지넷은 비전 분야에서 오픈소스를 기반으로 공유하고 발전하는 문화를 만들게 된 큰 계기가 되었다. 이와 관련된 자세한 내용은 다음 Fei-Fei Li 교수의 TED 강연을 통해 확인할 수 있다.
ImageNet (Fei-Fei Li 교수. TED)

최근 스탠포드대학에서 구글로 자리를 옮긴 Fei-Fei Li 교수에 대한 좀 더 자세한 내용은 다음 링크에서 살펴볼 수 있다.
마무리
이 글에서 머신러닝 훈련에 필요한 데이터를 제공하는 레퍼런스를 간략히 살펴보았다. 이외에, 이분야에서 공헌한 연구자 중 한명인 Fei-Fei Li 교수의 ImageNet에 대해서도 간단히 소개해 보았다. 이외에 데이터셋이 필요한 경우, Kaggle 등을 방문해 학습에 필요한 데이터를 얻을 수 있다.

레퍼런스

댓글 없음:

댓글 쓰기