Category Archives: 学習・テストデータ

(13) cuda-convnet用MNISTデータを作る(その3)

(12) cuda-convnet用MNISTデータを作る(その2) ではMNIST学習データファイルから cuda-convnet入力用の学習データ情報ファイル batches.meta を作成してみた。
今回は学習データ、テストデータそのものを格納する data_batch_n を作成してみる。

cifar10の data_batche_1 の中身はこんな感じ。

>>> import cPickle as cp
>>> d = cp.load(open('data_batch_1'))
>>> d.keys()
['batch_label', 'labels', 'data', 'filenames']
>>> d['batch_label']
'training batch 1 of 5'
>>> d['labels']
[6, 9, 9, 4, 1, 1, 2, 7, 8, 3, 4, 
 ...,
 9, 2, 2, 1, 6, 3, 9, 1, 1, 5]
>>> d['data']
array([[ 59, 154, 255, ...,  71, 250,  62],
       [ 43, 126, 253, ...,  60, 254,  61],
       ...,
       [ 84, 142,  83, ...,  69, 255, 130],
       [ 72, 144,  84, ...,  68, 254, 131]], dtype=uint8)
>>> d['filenames']
['leptodactylus_pentadactylus_s_000004.png', 'camion_s_000148.png', 'tipper_truck_s_001250.png', 'american_elk_s_001521.png',
 ...,
 , 'car_s_002296.png', 'estate_car_s_001433.png', 'cur_s_000170.png']

data_batche_n の中に格納されているデータは4種類ある。
1) batch_label : データファイルの説明
2) labels : 正解ラベル
3) data : 画像データ
4) filenames : 元の画像ファイル名

作成した data_batche_n作成関数はこちら。
拙いPythonスキルで試行錯誤しながら書いたので無駄がいっぱいあるかも…

import cPickle as cp
import numpy as np
import Image
import struct

def make_data_batch_all( train_img, train_lbl, test_img, test_lbl, nDataPerBatch ):
    iBatch = 1
    iBatch = make_data_batch( train_img, train_lbl, nDataPerBatch, iBatch, 'training' )
    iBatch = make_data_batch( test_img,  test_lbl,  nDataPerBatch, iBatch, 'testing' )

def make_data_batch( img, lbl, nDataPerBatch, iBatch, batchLabel ):
    fpImg = open( img, 'rb' )
    fpLbl = open( lbl, 'rb' )
    headerImg = fpImg.read( 4 * 4 )
    headerLbl = fpLbl.read( 4 * 2 )

    headerImg_up = struct.unpack('>4i', headerImg)
    headerLbl_up = struct.unpack('>2i', headerLbl)

    nImg  = headerImg_up[1]
    img_w = headerImg_up[2]
    img_h = headerImg_up[3]
    nPixelsOf1img = img_w * img_h

    print 'img : # of image             : %d' % nImg
    print 'img : image width            : %d' % img_w
    print 'img : image height           : %d' % img_h
    print 'img : # of pixels in a image : %d' % nPixelsOf1img

    nBatchMax = np.ceil(np.float32(nImg) / np.float32(nDataPerBatch))
    fmtImg  = '%dB' % nPixelsOf1img
    save_data = []
    save_filenames = []
    save_labels = []
    nOutData = 0

    for iImg in range(0,nImg):
    #for iImg in range(0,1):
        if (iImg % 1000 == 0) or (iImg == nImg-1):
            print 'now processing image #%d' % iImg
        # append data
        data = fpImg.read( nPixelsOf1img )
        data = struct.unpack(fmtImg, data)
        data = np.asarray( data ).astype('uint8')
        save_data.append(data.T.flatten('C'))
        nOutData = nOutData + 1
        # append filenames
        save_filenames.append('')
        # append labels
        data = fpLbl.read(1)
        data = struct.unpack('B', data)
        #save_labels.append((list(data))[0])
        save_labels.append(data[0])
        # save data_batch_n file
        if ((iImg > 0) and (iImg % nDataPerBatch == nDataPerBatch-1)) or (iImg == nImg-1):
           fname = 'data_batch_%d' % iBatch
           fpOut = open( fname, 'w+' )
           label = '%s batch %d of %d' % (batchLabel, iBatch, nBatchMax)
           save_data = np.reshape(save_data, (nOutData, img_w, img_h))
           save_data = np.uint8(save_data)
           save_data = save_data.swapaxes(0,2)
           #save_data = save_data.swapaxes(0,1)
           save_data = np.reshape(save_data, (img_w * img_h, nOutData))
           #save_labels = save_labels.T.flatten('C')
           dic = {'batch_label':label, 'data':save_data, 'labels':save_labels, 'filenames':save_filenames}
           cp.dump( dic, fpOut )
           fpOut.close()
           iBatch = iBatch + 1
           # clear data
           save_data = []
           save_filenames = []
           save_labels = []
           nOutData = 0
    fpImg.close()
    fpLbl.close()
    return iBatch

作成した data_batch_n を確認してみる。
元画像ファイル名は存在しないので空文字としている。

>>> import cPickle as cp
>>> d = cp.load(open('data_batch_1'))
>>> d.keys()
['batch_label', 'labels', 'data', 'filenames']
>>> d['batch_label']
'training batch 1 of 6'
>>> d['labels']
[5, 0, 4, 1, 9, 2, 1, 3, 1, 4, 3, 5,
 ...,
 7, 2, 7, 3, 7, 4, 0, 5, 8, 6, 9, 7]
>>> d['data']
array([[0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       ...,
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0]], dtype=uint8)
>>> d['filenames']
['', '', '', '', '', '', '', '', '',
 '', '', '', '', '', '', '', '', '']

OKそうだ!
次回は作成済みの batches.meta data_batch_n を使用してcuda-convnet を動かしてみる予定。

(12) cuda-convnet用MNISTデータを作る(その2)

(11) cuda-convnet用MNISTデータを作る(その1) ではMNISTデータファイルを pythonでロードする手順を確認した。今回はロードしたデータから cuda-convnet用 batches.meta ファイルを作成してみる。

cifar10のbatches.meta の中身はこんな感じ。

>>> import cPickle as cp
>>> meta = cp.load(open('batches.meta'))
>>> meta.keys()
['num_cases_per_batch', 'label_names', 'num_vis', 'data_mean']
>>> meta['num_cases_per_batch']
10000
>>> meta['label_names']
['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']
>>> meta['num_vis']
3072
>>> meta['data_mean']
array([[ 134.45458984],
       [ 134.22865295],
       [ 134.84976196],
       ...,
       [ 115.09417725],
       [ 115.32595062],
       [ 115.7903595 ]], dtype=float32)
>>> meta['data_mean'].size
3072
>>> im['data_mean'].ndim
2

batches.metaの中に格納されているデータは4種類ある。
1) num_cases_per_batch : 1バッチの画像データ数
2) label_names : ラベル文字列のリスト
3) num_vis : 1画像のデータ数(=ピクセル数×チャネル数)
4) data_mean : 全画像のピクセル×チャネルごとの平均値

作成した batches.meta作成関数はこちら。
拙いPythonスキルで試行錯誤しながら書いたので無駄がいっぱいあるかも…

def make_batches_meta( trainDataFilePath, nDataPerBatch ):
    infile = open( trainDataFilePath, 'rb' )
    header = infile.read( 4 * 4 )
    header_up = struct.unpack('>4i', header)   # > : big endian, 4i: 4 x int(32bit)
    nImg  = header_up[1]
    img_w = header_up[2]
    img_h = header_up[3]
    nPixelsOf1img = img_w * img_h

    print '# of image             : %d' % nImg
    print 'image width            : %d' % img_w
    print 'image height           : %d' % img_h
    print '# of pixels in a image : %d' % nPixelsOf1img

    # calculate average
    meanData = np.zeros(nPixelsOf1img, dtype=np.float32)
    for i in range(0,nImg):
        data = infile.read( nPixelsOf1img )
        fmt  = '%dB' % nPixelsOf1img
        data_up = struct.unpack(fmt, data)
        meanData = meanData + data_up
    meanData = meanData / nImg
    meanData = np.float32(meanData.reshape((nPixelsOf1img,1)))
    infile.close()

    # save batches.meta
    label_names = ['0','1','2','3','4','5','6','7','8','9']
    num_vis     = img_w * img_h
    meanData = np.reshape(meanData, (img_w, img_h))
    #meanData = meanData.swapaxes(0,1)
    meanData = meanData.T.flatten('C')
    meanData = np.reshape(meanData,(nPixelsOf1img,1))
    dic = {'num_cases_per_batch':nDataPerBatch, 'label_names':label_names, 'num_vis':num_vis, 'data_mean':meanData}
    fp = open('./batches.meta','w+')
    cp.dump( dic, fp )
    fp.close()

作成した batches.meta を確認してみる。

[user@linux]$ python
>>> import cPickle as cp
>>> im = cp.load(open('batches.meta'))
>>> im
{'num_cases_per_batch': 10000, 'label_names': ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'], 'num_vis': 784, 'data_mean': array([[  0.00000000e+00],
       [  0.00000000e+00],
       [  0.00000000e+00],
       ...,
       [  0.00000000e+00],
       [  0.00000000e+00],
       [  0.00000000e+00]], dtype=float32)}

OKそうだ!
次回は data_batch_n を作成してみる予定です。

(11) cuda-convnet用MNISTデータを作る(その1)

(1) MNIST画像データをダウンロード でダウンロードしたMNISTデータを、cuda-convnetプログラムで入力可能な形式に変換したい。Pythonに不慣れなこともあり、まずはファイルから入力した画像データを表示し、正しく読めていることを確認してみる。

事前にPythonでの画像表示に必要な以下のプログラムをインストールしておく必要がある。
PIL(Python Imaging Library)
ImageMagick

(1) 作業ディレクトリにはMNISTデータファイルが置いてある。

[user@linux]$ ll
-rw-rw-r--. 1 user user  7840016  7\u6708  7 18:08 2014 t10k-images-idx3-ubyte
-rw-rw-r--. 1 user user    10008  7\u6708  7 18:08 2014 t10k-labels-idx1-ubyte
-rw-rw-r--. 1 user user 47040016  7\u6708  7 18:08 2014 train-images-idx3-ubyte
-rw-rw-r--. 1 user user    60008  7\u6708  7 18:08 2014 train-labels-idx1-ubyte

(2) Pythonを起動する。

[user@linux]$ python
Python 2.6.6 (r266:84292, Jan 22 2014, 09:42:36) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 

(3) 使用するモジュールをロードする。

>>> import Image
>>> import numpy as np
>>> import struct

(4) train用データファイルをロードする。

>>> infile = open('./train-images-idx3-ubyte','rb')

(5) ヘッダ部のデータをロードする。
データファイルのフォーマットは (1) MNIST画像データをダウンロード を参照のこと。

>>> header = infile.read( 4 * 4 )
>>> header_up = struct.unpack('>4i', header)   # > : big endian, 4i: 4 x int(32bit) 
>>> numOfPixelsIn1Data = header_up[2] * header_up[3]
>>> print '# of image            : %d' % header_up[1]
# of image            : 60000
>>> print 'image width           : %d' % header_up[2]
image width           : 28
>>> print 'image height          : %d' % header_up[3]
image height          : 28
>>> print '# of pixels in a data : %d' % numOfPixelsIn1Data
# of pixels in a data : 784

(6) 先頭から5個の画像データを読み込み、表示する。

>>> for i in range(0,5):
...     data = infile.read( numOfPixelsIn1Data )
...     fmt  = '%dB' % numOfPixelsIn1Data
...     data_up = struct.unpack(fmt, data)
...     npData = np.asarray( data_up ).astype('uint8')
...     imData = np.reshape(npData, (28,28),order='C')
...     im = Image.fromarray( imData )
...     im.show()
... 

trainデータファイルの先頭にはこんな手書き数字画像が入っているようだ。
20140707_01

(7) 最後は(4)でオープンしたファイルをクローズする。

>>> infile.close()

次回はロードしたMNISTデータから cuda-convnetの batches.metaファイルを作成してみる予定です。

(8) CIFAR10画像セットを見てみる

CIFAR10画像セットを入手

まだMNISTもちゃんと自動認識できていないけれど、他の画像セットにもちょっと興味あり。

そこで CIFAR10 なるカラー画像セットを見てみることにした。提供元はこちら(↓)
https://www.cs.utoronto.ca/~kriz/cifar.html
https://www.dogrow.net/nnet/wp-content/uploads/2013/10/20131011_01.png

ダウンロードできるファイルは以下の3種類(2013年10月11日時点)、最近Octaveがお気に入りの自分はMATLAB用を選択。
https://www.dogrow.net/nnet/wp-content/uploads/2013/10/20131011_02.png

CIFAR10画像セットを解凍

早速Linux上で解凍してみる。

[user@dog-server]$ ls
cifar-10-matlab.tar.gz
[user@dog-server]$ tar zxf cifar-10-matlab.tar.gz
[user@dog-server]$ ls
cifar-10-batches-mat  cifar-10-matlab.tar.gz
[user@dog-server]$

すると、以下のような8個のファイルができた。

[user@dog-server]$ ls -l
合計 179148
-rw-r--r--. 1 user user      299  4月 23 05:57 2010 batches.meta.mat
-rw-r--r--. 1 user user 30568167  4月 23 05:50 2010 data_batch_1.mat
-rw-r--r--. 1 user user 30576389  4月 23 05:50 2010 data_batch_2.mat
-rw-r--r--. 1 user user 30572622  4月 23 05:50 2010 data_batch_3.mat
-rw-r--r--. 1 user user 30565850  4月 23 05:50 2010 data_batch_4.mat
-rw-r--r--. 1 user user 30572760  4月 23 05:50 2010 data_batch_5.mat
-rw-r--r--. 1 user user       88  4月 23 05:50 2010 readme.html
-rw-r--r--. 1 user user 30570596  4月 23 05:50 2010 test_batch.mat
[user@dog-server]$

とりあえず.matファイルをOctaveでロードして、中身を順番に眺めてみる。

(1) batches.meta.mat
画像のラベル名称が書かれている。ラベル1は飛行機、ラベル2は自動車、ラベル10はトラックとのこと。

octave:1> whos -file batches.meta.mat
Variables in the file batches.meta.mat:
   Attr Name             Size                     Bytes  Class
   ==== ====             ====                     =====  =====
        label_names     10x1                         50  cell
Total is 10 elements using 50 bytes
octave:2> load('batches.meta.mat')
octave:3> label_names
label_names =
{
  [1,1] = airplane
  [2,1] = automobile
  [3,1] = bird
  [4,1] = cat
  [5,1] = deer
  [6,1] = dog
  [7,1] = frog
  [8,1] = horse
  [9,1] = ship
  [10,1] = truck
}

(2) data_batch_1.mat ~ data_batch_5.mat
学習用の画像+ラベルのセットが10,000個×5ファイルの全60,000個が格納されている。
「3072」は1画像のバイトサイズで、内訳は 32pixel x 32pixel x RGB3色 x uint8 = 3,072[bytes] で計算できる。

octave:5> whos -file data_batch_1.mat
Variables in the file data_batch_1.mat:
   Attr Name             Size                     Bytes  Class
   ==== ====             ====                     =====  =====
        batch_label      1x21                        21  char
        data         10000x3072                30720000  uint8
        labels       10000x1                      10000  uint8
Total is 30730021 elements using 30730021 bytes
octave:6> load('data_batch_1.mat')
octave:7> batch_label
batch_label = training batch 1 of 5

(3) test_batch.mat
テスト用の画像+ラベルのセットが10,000個格納されている。

octave:10> whos -file test_batch.mat
Variables in the file test_batch.mat:
   Attr Name             Size                     Bytes  Class
   ==== ====             ====                     =====  =====
        batch_label      1x20                        20  char
        data         10000x3072                30720000  uint8
        labels       10000x1                      10000  uint8
Total is 30730020 elements using 30730020 bytes
octave:11> load('test_batch.mat')
octave:12> batch_label
batch_label = testing batch 1 of 1

CIFAR10画像セットを見てみる

どんな画像が入っているのか?実際に画像表示してみる。

画像化して眺める手順は (2)MNIST学習画像を見てみる と同じだ。
試しに学習画像の最初の1個をOctave上で画像化してみる。

octave:1> load('data_batch_1.mat')
octave:2> img = data(1,:);
octave:3> size(img)
ans =
      1   3072
octave:4> img=reshape(img(:),32,32,3);
octave:5> size(img)
ans =
   32   32    3
octave:6> imshow(uint8(permute(img,[2 1 3])))

https://www.dogrow.net/nnet/wp-content/uploads/2013/10/20131011_03.png

なんだ???

よくわからないので先頭データのラベルを見てみる。

octave:8> labels(1)
ans = 6

ラベル番号が6番なので「[6,1] = dog」のようだ。
この画像が犬なのか?

CIFAR10のホームページを見ると、ラベル番号は0~9を付与すると書かれている。

先ほど見た label_names変数の値は 1始まりだった。ラベル番号は 0始まりの6なので、1始まりに直せば 7だから「[7,1] = frog」が正しいラベルだ。
ややこしい…

続けていくつか見てみる。

(2)#10 truck
https://www.dogrow.net/nnet/wp-content/uploads/2013/10/20131011_04.png
(3)#10 truck
https://www.dogrow.net/nnet/wp-content/uploads/2013/10/20131011_05.png
(4)#5 deer
https://www.dogrow.net/nnet/wp-content/uploads/2013/10/20131011_06.png
(5)#2 automobile
https://www.dogrow.net/nnet/wp-content/uploads/2013/10/20131011_07.png
(6)#2 automobile
https://www.dogrow.net/nnet/wp-content/uploads/2013/10/20131011_08.png
(7)#3 bird
https://www.dogrow.net/nnet/wp-content/uploads/2013/10/20131011_09.png
(8)#8 horse
https://www.dogrow.net/nnet/wp-content/uploads/2013/10/20131011_10.png
(9)#9 ship
https://www.dogrow.net/nnet/wp-content/uploads/2013/10/20131011_11.png
(10)#4 cat
https://www.dogrow.net/nnet/wp-content/uploads/2013/10/20131011_12.png

(6) 自分の手書き文字を認識させてみる

プログラム変更仕様

MNISTで提供されるテスト画像だけでなく、自作の手書き文字画像を自動認識させてみたい。
シンプル構成初期版に追加する機能は以下の通り。
(1)学習機能の仕様追加: 1EPOCH完了ごとに学習済みパラメーターをファイル出力する。
(2)テスト機能の仕様追加: 学習済みパラメーターファイルと単一画像を入力としたテスト機能を新規作成する。


識別結果

意地悪なテスト画像を作ったつもりはないが、結構はずれている… 考察はまた後日にしよう。

No. 自作画像 識別結果 出力層出力値
1 OK
2 OK
3 OK
4 OK
5 OK
6 OK
7 OK
8 OK
9 NOK
10 OK
11 OK
12 OK
13 NOK
14 NOK
15 NOK
16 OK
17 OK
18 NOK
19 NOK
20 NOK

プログラムのソースコード

exec_1test.m

function result = exec_1test( gprmMatFile, testImgFile )

  % パラメーターファイルをロード
  load(gprmMatFile);

  % 画像データをロード
  img = single(imread(testImgFile)) / 255;

  % 画像データが2バンド以上の場合
  if numel(size(img)) > 3
    % グレースケール画像を作成
    img = mean(img,3);
  end

  % 順伝播
  nn = NNET_propagation_forward( gprm.nn, img );

  % 判定結果を出力
  result.out         = nn.layer{numel(nn.layer)}.out;
  [~, result.maxIdx] = max(result.out);

  % 棒グラフ表示
  bar([0:9], result.out);
  xlim([-0.5 9.5]);
  ylim([0 1]);
end

00003_simpleNN_03

(3) MNIST画像をPNG画像で出力する

MNIST画像データファイルをダウンロードした。
https://www.dogrow.net/nnet/?p=23

MNIST画像データのいくつかをOctaveで画像化して眺めてみた。
https://www.dogrow.net/nnet/?p=31

今回は、MNIST画像データファイルに含まれる全画像をPNG画像にして眺めてみたい。
今回も GNU-Octaveを使用する。Octaveは少ないコード量で高機能なプログラムを書けるので重宝している。

作成する関数は cre_MNIST_PNG とする。
第1引数は、MNIST画像データファイルのパス。学習用 or テスト用のどちらか一方を指定する。
第2引数は、PNG化したMNIST画像の出力先ディレクトリのパス。

function cre_MNIST_PNG( image_file, output_dir )
  % 画像をロード
  fid = fopen(image_file,'r','b');
  magic_number      = fread(fid, 1, 'int32');
  number_of_items   = fread(fid, 1, 'int32');
  number_of_rows    = fread(fid, 1, 'int32');
  number_of_columns = fread(fid, 1, 'int32');
  img               = fread(fid, [number_of_rows*number_of_columns number_of_items],'uint8');
  image = permute(reshape(img, number_of_rows, number_of_columns,number_of_items),[2 1 3]);
  fclose(fid);

  % 画像をPNGファイル出力
  if exist(output_dir)==0
    mkdir(output_dir);
  end
  for i=1 : number_of_items
    pngfile = sprintf('%s/img%05d.png', output_dir, i);
    imwrite(uint8(image(:,:,i)), pngfile);
  end
end

まずはテスト用画像 t10k-images-idx3-ubyte をPNG画像化してみる。

octave:1> cre_MNIST_PNG('t10k-images-idx3-ubyte','./img');
octave:2>

以下のようなPNG画像ファイルが出力された。(全10,000個の内の先頭から105個を表示)
https://www.dogrow.net/nnet/wp-content/uploads/2013/10/20131005_04.png

(2) MNIST学習画像を見てみる

ダウンロードしたMNIST画像は、一般的な画像ビューアで見ることができない。
ここではフリーの数値計算ソフト GNU-Octave を使ってMNIST画像データを可視化してみる。

学習用画像データファイルをオープンする。

octave:2> fid=fopen('train-images-idx3-ubyte','r','b')
fid =  3

学習用画像データファイルのフォーマットは以下の通り。
https://www.dogrow.net/nnet/wp-content/uploads/2013/10/20131005_03.png
ファイル先頭のヘッダ部分には、画像データに関する情報が4項目格納されている。

octave:3> magic_number = fread(fid,1,'int32')
magic_number =  2051
octave:4> number_of_items = fread(fid, 1, 'int32')
number_of_items =  60000
octave:5> number_of_rows = fread(fid,1,'int32')
number_of_rows =  28
octave:6> number_of_columns = fread(fid,1,'int32')
number_of_columns =  28

縦横28×28ピクセルの画像が60,000枚入っていることが確認できた。

次に画像を読み出してみる。
GNU-Octaveでは、fread関数で取得したデータの出力を2次元配列にすることができる。

octave:7> img = fread(fid, [28*28 60000],'uint8');
octave:8> size(img)
ans =
     784   60000
octave:9> img = reshape(img,28,28,60000);
octave:10> size(img)
ans =
      28      28   60000

先頭から一つずつ画像を表示してみる。
GNU-Octaveでは、imshowコマンドで2次元配列データを簡単に画像表示できる。

octave:11> v = uint8(img(:,:,1)');
octave:12> imshow(v)

これは「5」だろうか?
https://www.dogrow.net/nnet/wp-content/uploads/2013/10/20131005_M01.png

2番目に格納されている学習画像も見てみる。

octave:13> v = uint8(img(:,:,2)');
octave:14> imshow(v)

これは「0」に間違いない。
https://www.dogrow.net/nnet/wp-content/uploads/2013/10/20131005_M02.png

60000個目に格納されている学習画像も見てみる。

octave:15> v = uint8(img(:,:,60000)');
octave:16> imshow(v)

これは「8」に間違いない。
https://www.dogrow.net/nnet/wp-content/uploads/2013/10/20131005_M03.png

(1) MNIST画像データをダウンロード

MNISTファイルの入手

MNIST手書き文字画像データはこちらのサイトから入手できます。
http://yann.lecun.com/exdb/mnist/

https://www.dogrow.net/nnet/wp-content/uploads/2013/10/20131005_01.png

提供されるデータは以下の4種類
(1)学習用画像
(2)学習用画像のラベル(=識別番号)
(3)テスト用画像
(4)テスト用画像のラベル(=識別番号)
https://www.dogrow.net/nnet/wp-content/uploads/2013/10/20131005_02.png

ファイルの形式

ファイルの形式は上記ページの下の方の FILE FORMATS FOR THE MNIST DATABASE に書かれている。
仕様はとってもシンプル。例えば、学習用画像データは以下のような決まりでファイルに格納されている。
https://www.dogrow.net/nnet/wp-content/uploads/2013/10/20131005_03.png

なお、ダウンロードしたファイルはgzip型式で圧縮されており、gunzipコマンドで解凍できる。

[user@dog-server]$ ls -l
合計 11336
-rw-rw-r--. 1 user user 1648877 10月  5 01:51 2013 t10k-images-idx3-ubyte.gz
-rw-rw-r--. 1 user user    4542 10月  5 01:51 2013 t10k-labels-idx1-ubyte.gz
-rw-rw-r--. 1 user user 9912422 10月  5 01:51 2013 train-images-idx3-ubyte.gz
-rw-rw-r--. 1 user user   28881 10月  5 01:51 2013 train-labels-idx1-ubyte.gz
[user@dog-server]$ gunzip *.gz
[user@dog-server]$ ls -l
合計 53672
-rw-rw-r--. 1 user user  7840016 10月  5 01:51 2013 t10k-images-idx3-ubyte
-rw-rw-r--. 1 user user    10008 10月  5 01:51 2013 t10k-labels-idx1-ubyte
-rw-rw-r--. 1 user user 47040016 10月  5 01:51 2013 train-images-idx3-ubyte
-rw-rw-r--. 1 user user    60008 10月  5 01:51 2013 train-labels-idx1-ubyte
[user@dog-server]$

次回はダウンロードしたデータの中身を実際に見てみる。