CIFAR-10の取得と整理

MNISTの識別モデルをDeep Learningで上手く学習できたので、次の対象としてCIFAR-10を選んだ。 TensorFlowを使うと、学習が上手くいくように加工してくれるみたいだが、今回は一次ソースからデータを取得する。

CIFAR-10の取得

まず、CIFAR-10 and CIFAR-100 datasetsの “CIFAR-10 python version” をクリックしてデータをダウンロードする。 解凍するとcifar-10-batches-pyというフォルダーができるので適当な場所に置く。

CIFAR-10の内容

cifar-10-batches-pyの中身は以下の通り。 data_batchは10000x5レコード、test_batchは10000レコードある。 各々データとラベルに別れる。 データは1レコードあたり3072個(=1024x3, RGB)ある。 ラベルは1レコードあたり1個(0〜9のいずれか)なので、onehotにする必要がある。

cifar-10-batches-py
├── batches.meta  
├── data_batch_1  // training data 1
├── data_batch_2  // training data 2
├── data_batch_3  // training data 3
├── data_batch_4  // training data 4
├── data_batch_5  // training data 5
├── readme.html
└── test_batch    // testing data

batches.metaは以下の通り。

{
    'num_cases_per_batch': 10000,
    'label_names': ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck'],
    'num_vis': 3072
}

各ファイルは、以下のメソッドで可読できるようになる。

    import cPickle
    def unpickle(self, f):
        fo = open(f, 'rb')
        d = cPickle.load(fo)
        fo.close()

        return d

CIFAR-10の整理

Deep Learningで学習させるため、訓練データ、訓練ラベル、テストデータ、テストラベルに分ける。 さらに、ラベルはonehotにする。まずは、必要なライブラリーをインポート。

# coding: utf-8

import cPickle
import numpy as np
from sklearn.preprocessing import OneHotEncoder

ダウンロードしたCIFAR-10はDIRに置くことにする。 なお、データ整理の実行ファイルをsrc/data_cifar10.pyとする。 datasrcは同じ階層にある。

DIR = '../data/cifar10/cifar-10-batches-py/'
FILE_TRAIN = 'data_batch_%s'
FILE_TEST = 'test_batch'

訓練用のdata_batchは、5分割されているので全て結合する。 ラベルについては、onehot()によりonehotに変換する。 テスト用のtest_batchの結合する以外は、data_batchと同じ処理を行う。 結果して、訓練データ、訓練ラベル、テストデータ、テストラベルを格納したdataを返す。

注意!: np.empty()はランダムな数値で初期化するので、以下は間違ってるので使わないでください。暇ができたら修正します。

   def main(self):        
        # Training
        train_data = np.empty((0,3072))
        train_label = np.empty((0,10))
        for i in range(1, 6):
            print('read %s' % FILE_TRAIN%i)
            # data
            train_data_1 = self.unpickle(DIR+FILE_TRAIN%i)['data']
            train_data = np.concatenate((train_data, train_data_1), axis=0)
            # labels
            train_label_1 = self.unpickle(DIR+FILE_TRAIN%i)['labels']
            train_label_1 = self.onehot(train_label_1)
            train_label = np.concatenate((train_label, train_label_1), axis=0)

        # Testing
        print('read %s' % FILE_TEST)
        # data
        test_data = self.unpickle(DIR+FILE_TEST)['data']
        # labels
        test_label = self.unpickle(DIR+FILE_TEST)['labels']
        test_label = self.onehot(test_label)

        # Collect
        data = [train_data, train_label, test_data, test_label]

        return data

onehot()の各行の処理内容については、こちらが詳しい。

   def onehot(self, X):
        X = np.array(X).reshape(1, -1)
        X = X.transpose()
        encoder = OneHotEncoder(n_values=max(X)+1)
        X = encoder.fit_transform(X).toarray()

        return X

test()でmain()を実行して、結果を標準出力して内容を確認する。

   def test(self):
        data = self.main()
        
        print('')
        print('Training Data: %s columns, %s records' % (data[0].shape[1], data[0].shape[0]))
        print(data[0])
        print('')
        print('Training Labels: %s columns, %s records' % (data[1].shape[1], data[1].shape[0]))
        print(data[1])
        print('')

        print('Test Data: %s columns, %s records' % (data[2].shape[1], data[2].shape[0]))
        print(data[2])
        print('')
        print('Test Labels: %s columns, %s records' % (data[3].shape[1], data[3].shape[0]))
        print(data[3])      
        print('')

ファイル名を指定するだけで実行できるように以下を記述する。

if __name__ == "__main__":
    DataCifar10().test()

実行結果は以下の通り。 目的のデータが取得できていることが確認できる。

$ python data_cifar10.py
read data_batch_1
read data_batch_2
read data_batch_3
read data_batch_4
read data_batch_5
read test_batch

Training Data: 3072 columns, 50000 records
[[  59.   43.   50. ...,  140.   84.   72.]
 [ 154.  126.  105. ...,  139.  142.  144.]
 [ 255.  253.  253. ...,   83.   83.   84.]
 ...,
 [  35.   40.   42. ...,   77.   66.   50.]
 [ 189.  186.  185. ...,  169.  171.  171.]
 [ 229.  236.  234. ...,  173.  162.  161.]]

Training Labels: 10 columns, 50000 records
[[ 0.  0.  0. ...,  0.  0.  0.]
 [ 0.  0.  0. ...,  0.  0.  1.]
 [ 0.  0.  0. ...,  0.  0.  1.]
 ...,
 [ 0.  0.  0. ...,  0.  0.  1.]
 [ 0.  1.  0. ...,  0.  0.  0.]
 [ 0.  1.  0. ...,  0.  0.  0.]]

Test Data: 3072 columns, 10000 records
[[158 159 165 ..., 124 129 110]
 [235 231 232 ..., 178 191 199]
 [158 158 139 ...,   8   3   7]
 ...,
 [ 20  19  15 ...,  50  53  47]
 [ 25  15  23 ...,  80  81  80]
 [ 73  98  99 ...,  94  58  26]]

Test Labels: 10 columns, 10000 records
[[ 0.  0.  0. ...,  0.  0.  0.]
 [ 0.  0.  0. ...,  0.  1.  0.]
 [ 0.  0.  0. ...,  0.  1.  0.]
 ...,
 [ 0.  0.  0. ...,  0.  0.  0.]
 [ 0.  1.  0. ...,  0.  0.  0.]
 [ 0.  0.  0. ...,  1.  0.  0.]]

最後に全ソースを載せておく。

# coding: utf-8

import cPickle
import numpy as np
from sklearn.preprocessing import OneHotEncoder

DIR = '../data/cifar10/cifar-10-batches-py/'
FILE_TRAIN = 'data_batch_%s'
FILE_TEST = 'test_batch'

class DataCifar10:
    def __init__(self):
        pass


    def main(self):        
        # Training
        train_data = np.empty((0,3072))
        train_label = np.empty((0,10))
        for i in range(1, 6):
            print('read %s' % FILE_TRAIN%i)
            # data
            train_data_1 = self.unpickle(DIR+FILE_TRAIN%i)['data']
            train_data = np.concatenate((train_data, train_data_1), axis=0)
            # labels
            train_label_1 = self.unpickle(DIR+FILE_TRAIN%i)['labels']
            train_label_1 = self.onehot(train_label_1)
            train_label = np.concatenate((train_label, train_label_1), axis=0)

        # Testing
        print('read %s' % FILE_TEST)
        # data
        test_data = self.unpickle(DIR+FILE_TEST)['data']
        # labels
        test_label = self.unpickle(DIR+FILE_TEST)['labels']
        test_label = self.onehot(test_label)
        
        # Collect
        data = [train_data, train_label, test_data, test_label]

        return data


    def unpickle(self, f):
        fo = open(f, 'rb')
        d = cPickle.load(fo)
        fo.close()

        return d


    def onehot(self, X):
        X = np.array(X).reshape(1, -1)
        X = X.transpose()
        encoder = OneHotEncoder(n_values=max(X)+1)
        X = encoder.fit_transform(X).toarray()

        return X


    def test(self):
        data = self.main()
        
        print('')
        print('Training Data: %s columns, %s records' % (data[0].shape[1], data[0].shape[0]))
        print(data[0])
        print('')
        print('Training Labels: %s columns, %s records' % (data[1].shape[1], data[1].shape[0]))
        print(data[1])
        print('')

        print('Test Data: %s columns, %s records' % (data[2].shape[1], data[2].shape[0]))
        print(data[2])
        print('')
        print('Test Labels: %s columns, %s records' % (data[3].shape[1], data[3].shape[0]))
        print(data[3])      
        print('')


if __name__ == "__main__":
    DataCifar10().test()

参考文献