Chainerのtrainerを使ってCIFAR-10の分類に挑戦したかった

# はじめに

先日[こちら](http://qiita.com/_329_/items/bcc306194d52f7b81b5a)の記事からChainerがすごく簡潔に書けるようになったと知り、前から試してみたかったCIFAR-10の画像分類に挑戦してみました
...と、書きたかったのですが、貧弱CPU環境しか持っていないので、実行確認までできていません
1日中動かして2epochくらい進んだのでおそらく正しい...はず^^;
実装に関しては[こちら](http://ai-programming.hatenablog.jp/entry/2016/03/04/160243)のブログを参考にさせていただきました

# 実装

## CIFAR-10の画像を読み込んでくる

[ここ](http://www.cs.toronto.edu/~kriz/cifar.html)からCIFAR-10のデータをダウンロードして読み込みます。pickleのようなので下記の関数で読み込みます。

~~~python
def unpickle(file):
    fp = open(file, 'rb')
    if sys.version_info.major == 2:
        data = pickle.load(fp)
    elif sys.version_info.major == 3:
        data = pickle.load(fp, encoding='latin-1')                                                                                    
    fp.close()

    return data
~~~

## ニューラルネットワーク

先ほど紹介したブログを参考にさせていただきました。
この辺に関しては未だにどうやって設計していいかよくわかってないです...

~~~python
class Cifar10Model(chainer.Chain):

    def __init__(self):
        super(Cifar10Model,self).__init__(
                conv1 = F.Convolution2D(3, 32, 3, pad=1),
                conv2 = F.Convolution2D(32, 32, 3, pad=1),
                conv3 = F.Convolution2D(32, 32, 3, pad=1),
                conv4 = F.Convolution2D(32, 32, 3, pad=1),
                conv5 = F.Convolution2D(32, 32, 3, pad=1),
                conv6 = F.Convolution2D(32, 32, 3, pad=1),
                l1 = L.Linear(512, 512),
                l2 = L.Linear(512,10))

    def __call__(self, x, train=True):
        h = F.relu(self.conv1(x))
        h = F.max_pooling_2d(F.relu(self.conv2(h)), 2)
        h = F.relu(self.conv3(h))
        h = F.max_pooling_2d(F.relu(self.conv4(h)), 2)
        h = F.relu(self.conv5(h))
        h = F.max_pooling_2d(F.relu(self.conv6(h)), 2)
        h = F.dropout(F.relu(self.l1(h)), train=train)
        return self.l2(h)
~~~

## データ読み込み

ここで少しつまりました。
Chainerの新機能trainerを使う際に学習したいデータをiteratorに渡すのですが、チュートリアルなどでは

~~~python
train_iter = chainer.iterators.SerialIterator(train, 100)
test_iter = chainer.iterators.SerialIterator(test, 100,repeat=False, shuffle=False)
~~~

のようになっており、ラベルなどはどうやって渡すのかわかりませんでした。
いろいろ調べた結果、Tuple_datasetを使えばよいということがわかりました。

~~~python
train = chainer.tuple_dataset.TupleDataset(train_data, train_label)
~~~

のようにするといいようです。

下記、読み込み部分全コードとなってます。

~~~python
x_train = None
y_train = []
for i in range(1,6):
    data_dic = unpickle("cifar-10-batches-py/data_batch_{}".format(i))
    if i == 1:
        x_train = data_dic['data']
    else:
        x_train = np.vstack((x_train, data_dic['data']))
    y_train += data_dic['labels']

test_data_dic = unpickle("cifar-10-batches-py/test_batch")
x_test = test_data_dic['data']
x_test = x_test.reshape(len(x_test),3,32,32)
y_test = np.array(test_data_dic['labels'])
x_train = x_train.reshape((len(x_train),3, 32, 32))
y_train = np.array(y_train)
x_train = x_train.astype(np.float32)
x_test = x_test.astype(np.float32)
x_train /= 255
x_test/=255                                                                                                                     
y_train = y_train.astype(np.int32)
y_test = y_test.astype(np.int32)

train = tuple_dataset.TupleDataset(x_train, y_train)
test = tuple_dataset.TupleDataset(x_test, y_test)

~~~

## 学習部分

先ほど定義したニューラルネットワークで学習をしています。コードはチュートリアルのMNISTを少しいじっただけです。
めちゃくちゃ簡潔に書けて驚きです。

~~~python

model = L.Classifier(Cifar10Model())
optimizer = chainer.optimizers.Adam()
optimizer.setup(model)

train_iter = chainer.iterators.SerialIterator(train, 100)
test_iter = chainer.iterators.SerialIterator(test, 100,repeat=False, shuffle=False)

updater = training.StandardUpdater(train_iter, optimizer, device=-1)
trainer = training.Trainer(updater, (40, 'epoch'), out="logs")
trainer.extend(extensions.Evaluator(test_iter, model, device=-1))
trainer.extend(extensions.LogReport())
trainer.extend(extensions.PrintReport( ['epoch', 'main/loss', 'validation/main/loss', 'main/accuracy', 'validation/main/accuracy']))
trainer.extend(extensions.ProgressBar())                                                                                          
trainer.run()
~~~

# 結果

実行するとプログレスバーが出てきて、学習の進み具合を教えてくれます。

![Screenshot from 2016-08-06 18:04:00.png](https://qiita-image-store.s3.amazonaws.com/0/91517/9972ee41-1708-9892-d9ec-1f8d8edf2bb5.png)

Estimated time to finish: __6 days__

~~あきらめました~~
(2016.08.15 修正)
がんばりました

出力されたlogをdictionaryに読み込みmatplotlibでグラフ化しました

![figure_1.png](https://qiita-image-store.s3.amazonaws.com/0/91517/2a4d9d7b-e111-0a38-29d9-7b2edd06893e.png)

![figure_2.png](https://qiita-image-store.s3.amazonaws.com/0/91517/68fedc6b-00df-110e-7398-a230cf7f47ac.png)

# おわりに

~~きちんと結果が出たのは確認できませんでしたが、~~trainerの使い方の勉強にはなりました
やはりDeep Learningの勉強をするには___GPUは必須___ですね