ChainerのMNISTをConvolution2Dに改造する
Convolution2Dの使い方がよくわかんない。
よくわかんないのでとりあえず動作しているサンプルを改造して動きを見てみることにした。
#!/usr/bin/env python """Chainer example: train a multi-layer perceptron on MNIST This is a minimal example to write a feed-forward net. It requires scikit-learn to load MNIST dataset. """ import argparse import numpy as np import six import chainer from chainer import computational_graph as c from chainer import cuda import chainer.functions as F from chainer import optimizers import data parser = argparse.ArgumentParser(description='Chainer example: MNIST') parser.add_argument('--gpu', '-g', default=-1, type=int, help='GPU ID (negative value indicates CPU)') args = parser.parse_args() if args.gpu >= 0: cuda.check_cuda_available() xp = cuda.cupy if args.gpu >= 0 else np batchsize = 100 n_epoch = 20 # Prepare dataset print('load MNIST dataset') mnist = data.load_mnist_data() mnist['data'] = mnist['data'].astype(np.float32) mnist['data'] /= 255 mnist['data'] = mnist['data'].reshape(70000, 1,28,28) mnist['target'] = mnist['target'].astype(np.int32) N = 60000 x_train, x_test = np.split(mnist['data'], [N]) y_train, y_test = np.split(mnist['target'], [N]) N_test = y_test.size # Prepare multi-layer perceptron model model = chainer.FunctionSet(cv1=F.Convolution2D(1,30, 3), bn2 = F.BatchNormalization( 30), ln3=F.Linear(5070, 1000), ln4=F.Linear(1000, 10)) if args.gpu >= 0: cuda.get_device(args.gpu).use() model.to_gpu() def forward(x_data, y_data, train=True): # Neural net architecture x, t = chainer.Variable(x_data), chainer.Variable(y_data) h = F.max_pooling_2d(F.dropout(F.relu(model.bn2(model.cv1(x))), train=train),2) h = F.dropout(F.relu(model.ln3(h)), train=train) y = model.ln4(h) return F.softmax_cross_entropy(y, t), F.accuracy(y, t) # Setup optimizer optimizer = optimizers.Adam() optimizer.setup(model) # Learning loop for epoch in six.moves.range(1, n_epoch + 1): print('epoch', epoch) # training perm = np.random.permutation(N) sum_accuracy = 0 sum_loss = 0 for i in six.moves.range(0, N, batchsize): x_batch = xp.asarray(x_train[perm[i:i + batchsize]]) y_batch = xp.asarray(y_train[perm[i:i + batchsize]]) optimizer.zero_grads() loss, acc = forward(x_batch, y_batch) loss.backward() optimizer.update() if epoch == 1 and i == 0: with open("graph.dot", "w") as o: o.write(c.build_computational_graph((loss, )).dump()) with open("graph.wo_split.dot", "w") as o: g = c.build_computational_graph((loss, ), remove_split=True) o.write(g.dump()) print('graph generated') sum_loss += float(loss.data) * len(y_batch) sum_accuracy += float(acc.data) * len(y_batch) print('train mean loss={}, accuracy={}'.format( sum_loss / N, sum_accuracy / N)) # evaluation sum_accuracy = 0 sum_loss = 0 for i in six.moves.range(0, N_test, batchsize): x_batch = xp.asarray(x_test[i:i + batchsize]) y_batch = xp.asarray(y_test[i:i + batchsize]) loss, acc = forward(x_batch, y_batch, train=False) sum_loss += float(loss.data) * len(y_batch) sum_accuracy += float(acc.data) * len(y_batch) print('test mean loss={}, accuracy={}'.format( sum_loss / N_test, sum_accuracy / N_test))
解説
Convolution2Dに渡せるように配列、行列の形を変えます。
サンプル数70000個、チャンネル数1、縦横28*28
mnist['data'] = mnist['data'].reshape(70000, 1,28,28)
ニューラルネットワークに使う部品
# Prepare multi-layer perceptron model model = chainer.FunctionSet(cv1=F.Convolution2D(1,30, 3), bn2 = F.BatchNormalization( 30), ln3=F.Linear(5070, 1000), ln4=F.Linear(1000, 10))
ニューラルネットワークの定義
def forward(x_data, y_data, train=True): # Neural net architecture x, t = chainer.Variable(x_data), chainer.Variable(y_data) h = F.max_pooling_2d(F.dropout(F.relu(model.bn2(model.cv1(x))), train=train),2) h = F.dropout(F.relu(model.ln3(h)), train=train) y = model.ln4(h) return F.softmax_cross_entropy(y, t), F.accuracy(y, t)
変わっているのはこの辺だけです。
Convolution2DからLinearにつなげる時にサイズがわからないけど、とりあえず実行してみて
chainer.utils.type_check.InvalidType: Expect: prod(in_types[0].shape[1:]) == W.shape[1] Actual: 1690 != 6760
エラーを見て数値を変更すればおk。