Skip to content

Latest commit

Β 

History

History
168 lines (107 loc) Β· 7.99 KB

File metadata and controls

168 lines (107 loc) Β· 7.99 KB
title C++ Example 3. MNIST dataset (with python)
tags
caffe
keywords start, introduction, begin, install, build, hello world,
last_updated August 12, 2015
summary μ„Έ 번째 μ˜ˆμ œλŠ” MNIST 데이터셋을 μ½μ–΄μ˜€λ„λ‘ ν•˜κ² μŠ΅λ‹ˆλ‹€

By koosy on 2015.12.01

MNIST 데이터셋 및 LMDB μ€€λΉ„

μ΄λ²ˆμ—λŠ” MNIST 데이터셋 및 LMDB에 λŒ€ν•΄μ„œ μ•Œμ•„λ΄…λ‹ˆλ‹€. MNIST λ°μ΄ν„°λŠ” κΈ°κ³„ν•™μŠ΅μ—μ„œ λŒ€ν‘œμ μœΌλ‘œ 많이 μ‚¬μš©λ˜λŠ” λ²€μΉ˜λ§ˆν‚Ή λ°μ΄ν„°μž…λ‹ˆλ‹€. 0μ—μ„œλΆ€ν„° 9κΉŒμ§€ 10κ°€μ§€μ˜ 손글씨 이미지가 μžˆλŠ”λ°μš”. 이미지 ν¬κΈ°λŠ” 28x28, νŠΈλ ˆμ΄λ‹ μ΄λ―Έμ§€λŠ” 60,000μž₯, ν…ŒμŠ€νŠΈ μ΄λ―Έμ§€λŠ” 10,000μž₯으둜 이루어져 μžˆμŠ΅λ‹ˆλ‹€. μžμ„Έν•œ λ‚΄μš©μ€ MNIST 곡식 νŽ˜μ΄μ§€λ₯Ό μ°Έκ³ ν•˜μ„Έμš”.

이번 μ‹œκ°„μ—λŠ” Caffeμ—μ„œ μ‚¬μš©ν•˜λŠ” LMDB포멧을 μ΄μš©ν•˜μ—¬ MNIST 데이터λ₯Ό 읽어보고 python을 μ΄μš©ν•˜μ—¬ μ‹œκ°ν™”λ₯Ό 해보도둝 ν•˜κ² μŠ΅λ‹ˆλ‹€.

MNIST 데이터셋 λ‹€μš΄λ‘œλ“œ

카페 μ†ŒμŠ€μ—λŠ” μ—¬λŸ¬κ°€μ§€ μœ μš©ν•œ νˆ΄λ“€μ„ μ œκ³΅ν•™ μžˆλŠ”λ°μš”. κ·Έ μ€‘μ˜ ν•˜λ‚˜κ°€ 데이터셋을 λ‹€μš΄λ‘œλ“œ λ°›μ•„μ„œ LMDB둜 λ³€ν™˜ν•˜λŠ” μž‘μ—…μž…λ‹ˆλ‹€. λ¨Όμ € μ•„λž˜μ™€ 같이 카페의 ν™ˆν΄λ”(μ—¬κΈ°μ„œλŠ” your_caffe_home 이라 ν•˜κ² μŠ΅λ‹ˆλ‹€.) μ•„λž˜μ— μžˆλŠ” mnist ν΄λ”λ‘œ μ΄λ™ν•΄μ„œ get_mnist ν•©λ‹ˆλ‹€.

cd your_caffe_home/data/mnist
./get_mnist.sh

폴더 μ•ˆμ— 4개 파일 (t10k-images-idx3-ubyte, t10k-labels-idx1-ubyte, train-images- idx3-ubyte, train-labels-idx1-ubyte) 이 λ‹€μš΄λ‘œλ“œ λœκ²ƒμ„ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

LMDB λ³€ν™˜

μ΄λ²ˆμ—λŠ” LMDB 파일둜 λ³€ν™˜ν•΄ 보도둝 ν•˜κ² μŠ΅λ‹ˆλ‹€. λ³€ν™˜ νˆ΄μ€ ν™ˆν΄λ” μ•„λž˜μ— μžˆλŠ” examples/mnist 폴더 μ•ˆμ— μžˆμŠ΅λ‹ˆλ‹€. ν•œλ²ˆ μ‹€ν–‰ν•΄ 보죠.

cd your_caffe_home
sh examples/mnist/create_mnist.sh

그럼 두 개의 폴더 (mnist_test_lmdb, mnist_train_lmdb)κ°€ μƒμ„±λœκ±Έ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€. 각 ν΄λ”μ—λŠ” LMDB ν˜•νƒœλ‘œ νŠΈλ ˆμ΄λ‹ 데이터와 ν…ŒμŠ€νŠΈ 데이터가 μƒμ„±λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€. 이런 μ‹μœΌλ‘œ μΉ΄νŽ˜μ—μ„œλŠ” κ³΅μ‹μ μœΌλ‘œ LMDB λ˜λŠ” LevelDB 포멧을 λ°μ΄ν„°λ‘œ μ‚¬μš©ν•©λ‹ˆλ‹€. μž„μ˜μ˜ λ°μ΄ν„°λŠ” λ‘˜ 쀑 ν•˜λ‚˜μ˜ 포멧으둜 λ³€ν™˜ν•œ 후에 μ‚¬μš©ν•΄μ•Ό ν•˜λŠ”λ°μš”. λ³€ν™˜ν•˜λŠ” C++ μ½”λ“œλŠ” λ‹€μŒλ²ˆμ— ν•œλ²ˆ μ•Œμ•„λ³΄λ„λ‘ ν•˜κ² μŠ΅λ‹ˆλ‹€.

Python code

μ΄λ²ˆμ—λŠ” νŒŒμ΄μ¬μ„ μ΄μš©ν•˜μ—¬ LMDB둜 λ³€ν™˜λœ MNIST 데이터셋을 μ½μ–΄μ˜€κ³  μ‹œκ°ν™”ν•˜μ—¬ 데이터λ₯Ό 직접 μ‚΄νŽ΄λ³΄λ„λ‘ ν•˜κ² μŠ΅λ‹ˆλ‹€. 이 κ°•μ˜λŠ” C++을 기반으둜 λ˜μ–΄ μžˆμ§€λ§Œ, κ°„κ°„νžˆ νŒŒμ΄μ¬μ„ μœ μš©ν•˜κ²Œ μ‚¬μš©ν•˜λ €κ³  ν•©λ‹ˆλ‹€. 처음 μ ‘ν•˜μ‹œλŠ” 뢄은 μœ μš©ν•œ 툴이 λ§ŽμœΌλ‹ˆ 이번 κΈ°νšŒμ— νŒŒμ΄μ¬μ„ ν•œλ²ˆ μ ‘ν•΄λ³΄μ„Έμš”.

LMDB 라이브러리 μ„€μΉ˜

λ¨Όμ € lmdbλ₯Ό μ„€μΉ˜ν•©λ‹ˆλ‹€. μžμ„Έν•œ μ„€μΉ˜λ²•μ€ κ³΅μ‹μ‚¬μ΄νŠΈλ₯Ό μ°Έμ‘°ν•˜μ‹œκ³ , μ—¬κΈ°μ„œλŠ” μš°λΆ„νˆ¬λ₯Ό 기반으둜 μ½”λ“œ λͺ‡ μ€„λ§Œ μ μŠ΅λ‹ˆλ‹€. Python Package 관리 ν”„λ‘œκ·Έλž¨ pip이 μ—†μœΌμ‹  뢄듀은 λ¨Όμ € μ„€μΉ˜ν•˜μ‹œκΈ° λ°”λžλ‹ˆλ‹€.

apt-get install libffi-dev python-dev build-essential
pip install lmdb

Python code

μ΄μ œλΆ€ν„° 본격적인 파이썬 코딩을 ν•©λ‹ˆλ‹€. μ„ ν˜Έν•˜μ‹œλŠ” 파이썬 에디터λ₯Ό μ—΄μ–΄μ„œ μ•„λž˜ μ½”λ“œλ“€μ„ μ°¨λ‘€λ‘œ μ‹€ν–‰ν•΄λ³΄μ„Έμš”. μ €λŠ” 개인적으둜 ipython notebook을 μ„ ν˜Έν•©λ‹ˆλ‹€. 이 κ°•μ’Œλ„ IP notebook을 μ΄μš©ν•˜μ—¬ μž‘μ„±ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

LMDB 및 카페 파이썬 라이브러리 import

import numpy as np
import matplotlib.pyplot as plt
import lmdb
import sys
sys.path.insert(0, your_caffe_home + 'python')
import caffe

LMDB 데이터 μ…‹ μ—΄κΈ°

lmdb_train = lmdb.open(your_caffe_home + '/examples/mnist/mnist_train_lmdb', readonly=True)
lmdb_test = lmdb.open(your_caffe_home + '/examples/mnist/mnist_test_lmdb', readonly=True)

이제, lmdb_trainκ³Ό lmdb_testμ•ˆμ— 데이터셋이 듀어와 μžˆμŠ΅λ‹ˆλ‹€. νŠΈλ ˆμ΄λ‹ λ°μ΄ν„°μ—λŠ” 60,000μž₯의 이미지와 라벨이, ν…ŒμŠ€νŠΈ λ°μ΄ν„°μ—λŠ” 10,000μž₯의 이미지와 라벨이 λ“€μ–΄ μžˆμ„ν…λ°μš”. 예제둜 각 λ°μ΄ν„°μ…‹μ˜ 첫번째 그리고 λ§ˆμ§€λ§‰ 데이터λ₯Ό μ ‘κ·Όν•΄μ„œ 읽어보도둝 ν•˜κ² μŠ΅λ‹ˆλ‹€. 접근을 μœ„ν•΄ 8λ°”μ΄νŠΈμ˜ 인덱슀 ν‚€λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.

start_train = lmdb_train.begin().get('00000000')
end_train = lmdb_train.begin().get('00059999')
start_test = lmdb_test.begin().get('00000000')
end_test = lmdb_test.begin().get('00009999')

이제 start_train λΆ€ν„° end_test κΉŒμ§€λŠ” 이미지 및 라벨 정보가 λ“€μ–΄κ°€ μžˆλŠ”λ°μš”. 데이터듀이 LMDB에 μ €μž₯될 λ•Œ μ‚¬μš©λœ κ·œμΉ™μ— 따라 μΌλ ¬ν™”λœ λ¬Έμžμ—΄λ‘œ μ €μž₯이 λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€. 각 λ¬Έμžμ—΄λ§Œ λ΄μ„œλŠ” 무슨 정보가 λ“€μ–΄μžˆλŠ”μ§€ μ•Œ 수 μ—†κ² μ£ ? μΉ΄νŽ˜μ—μ„œλŠ” Datum μ΄λΌλŠ” 데이터 ꡬ쑰λ₯Ό κ°€μ§€κ³  MNIST 데이터λ₯Ό μ½μ–΄μ„œ LMDB에 μ €μž₯ν–ˆλŠ”λ°μš”, μΉ΄νŽ˜μ—μ„œ μ •μ˜ν•œ 데이터 ꡬ쑰λ₯Ό μžμ„Ένžˆ μ•Œκ³  μ‹ΆμœΌμ‹œλ©΄ caffe.pro toλ₯Ό μ‚΄νŽ΄λ³΄μ„Έμš”. Datum 외에도 μΉ΄νŽ˜μ—μ„œ μ‚¬μš©ν•˜λŠ” λ‹€λ₯Έ λ³€μˆ˜ νƒ€μž…μ˜ μ •μ˜λ₯Ό ν•œ λˆˆμ— 보싀 수 μžˆμŠ΅λ‹ˆλ‹€.

그럼 μ΄λ²ˆμ—λŠ” Datum을 μ΄μš©ν•˜μ—¬ 데이터λ₯Ό μ €μž₯ν•΄ 보도둝 ν•˜κ² μŠ΅λ‹ˆλ‹€. ParseFromString μ΄λΌλŠ” ν•¨μˆ˜λ‘œ LMDB의 λ¬Έμžμ—΄ 데이터λ₯Ό ν•΄μ„ν•˜κ³  Datum에 μ €μž₯ν•©λ‹ˆλ‹€.

datum_train_start = caffe.proto.caffe_pb2.Datum()
datum_train_start.ParseFromString(start_train)

λ¨Όμ € datum_train_start μ•ˆμ— ꡬ쑰가 μ–΄λ–»κ²Œ λ˜μ–΄ μžˆλŠ”μ§€ ν•œλ²ˆ μ‚΄νŽ΄λ³ΌκΉŒμš”? ipythonμ—μ„œλŠ” datum_train_start? 라고 치면 데이터 μ•ˆμ˜ κ°’ 및 μ„€λͺ…을 λ³Ό μˆ˜κ°€ μžˆμŠ΅λ‹ˆλ‹€.

datum_train_start?

channels: 1 height: 28 width: 28 data: "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ <...> 00\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" label: 5

λ³΄μ‹œλ‹€μ‹œν”Ό ν•˜λ‚˜μ˜ Datum은 channels, height, width, data, label 으둜 이루어져 μžˆμŠ΅λ‹ˆλ‹€. 즉 μ•žμ˜ μ˜ˆμ œμ—μ„œ μ‚΄νŽ΄λ³Έ blob의 ꡬ쑰 μ€‘μ—μ„œ 첫번째 차원인 numbers λ₯Ό μ œμ™Έν•œ 3차원 ꡬ쑰 + label 데이터λ₯Ό 담을 수 μžˆλŠ”λ°μš”, μ‹€μ œ λ°μ΄ν„°λŠ” 1차원 슀트링으둜 λ˜μ–΄μžˆκ³ , 차원 μ •λ³΄λ§Œ μžˆμŒμ„ μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€.

μ΄λ²ˆμ—λŠ” Datum에 λͺ…μ‹œλœλ°λ‘œ(1 x 28 x 28) 데이터λ₯Ό 닀차원 λ°°μ—΄λ‘œ 볡ꡬ해 λ³΄κ² μŠ΅λ‹ˆλ‹€. numpyλ₯Ό μ΄μš©ν•˜μ—¬ unsigned int νƒ€μž…μœΌλ‘œ λ³€ν™˜ν•˜κ³ , reshape() λͺ…령을 μ‚¬μš©ν•΄μ„œ 차원 λ³€ν™˜μ„ ν•©λ‹ˆλ‹€.

flat_x = np.fromstring(datum_train_start.data, dtype=np.uint8)
x = flat_x.reshape(datum_train_start.height, datum_train_start.width)

xκ°€ 2차원 λ°°μ—΄λ‘œ 잘 λ³€ν™˜μ΄ λ˜μ—ˆλ‚˜ 확인해 λ΄…μ‹œλ‹€.

x.shape

(28, 28)

μ΄λ²ˆμ—λŠ” matplotlib.pyplot의 imshow λͺ…령을 μ‚¬μš©ν•΄μ„œ 이차원 이미지 데이터λ₯Ό μ‹œκ°ν™”ν•΄ λ΄…μ‹œλ‹€. νŠΈλ ˆμ΄λ‹ λ°μ΄ν„°μ…‹μ˜ 첫 번째 μ΄λ―Έμ§€λŠ” μ•„λž˜ λ³΄λŠ”κ²ƒκ³Ό 같이 숫자 5μ΄κ΅°μš”.

plt.rcParams['image.interpolation'] = 'none'
plt.rcParams['image.cmap'] = 'gray'
plt.imshow(x)

png

datum_train_start에 μ €μž₯된 라벨값도 같은지 확인해 λ΄…μ‹œλ‹€.

datum_train_start.label

5

맺음말

이번 κ°•μ’Œμ—μ„œλŠ” LMDB둜 λ³€ν™˜ν•œ MNIST 데이터셋을 파이썬으둜 μ½μ–΄μ˜€κ³ , 카페 파이썬 라이브러리λ₯Ό μ΄μš©ν•˜μ—¬ 각 데이터와 라벨을 읽고 μ‹œκ°ν™” ν•΄μ„œ 확인해 λ³΄μ•˜μŠ΅λ‹ˆλ‹€. Datum μ΄λΌλŠ” μΉ΄νŽ˜μ—μ„œ μ‚¬μš©ν•˜λŠ” 데이터ꡬ쑰가 데이터λ₯Ό λ°μ΄ν„°λ² μ΄μŠ€μ— μ €μž₯ν•˜κ±°λ‚˜ μ½μ–΄μ˜€λŠ” μΈν„°νŽ˜μ΄μŠ€ 역할을 ν•˜λŠ”κ²ƒλ„ μ•Œμ•„λ³΄μ•˜μŠ΅λ‹ˆλ‹€. λ‹€μŒλ²ˆμ—λŠ” C++ μ½”λ“œμ—μ„œ 각 Datum을 μ–΄λ–»κ²Œ Blob으둜 λ§Œλ“œλŠ”μ§€, 그리고 μ΄λ ‡κ²Œ 읽은 MNIST 데이터λ₯Ό μ‹€μ œλ‘œ ν™œμš©ν•˜μ—¬ λ¨Έμ‹ λŸ¬λ‹ μ•Œκ³ λ¦¬μ¦˜λ“€μ„ κ΅¬ν˜„ν•΄ 보도둝 ν•˜κ² μŠ΅λ‹ˆλ‹€.