Chainerを使ってシンプルなMNISTのためのネットワークを作る勉強を進めている。
参考にしたのは、以下のサイトなど、いくつかのサイトを回って、どうやってネットワークを構築すれば良いのかを調べた。
いくつかのサイトをみながら、いろんなコードを切り貼りして勉強しているのだが、まずはネットワークをどのように構築するのかについて調べた。 ネットワークの基本となるノードの接続を定義し、Forwardでデータを進めていく。また、トレーニングの関数を用意して、ネットワークのノード値をアップデートしていく。
class SmallClassificationModel(chainer.FunctionSet): def __init__(self): super(SmallClassificationModel, self).__init__( fc1=chainer.functions.Linear(784,10) ) def _forward(self, x): h = self.fc1(x) return h def train(self, x_data, y_data): x = chainer.Variable(x_data.astype(np.float32), volatile=False) y = chainer.Variable(y_data.astype(np.int32), volatile=False) h = self._forward(x) optimizer.zero_grads() error = chainer.functions.softmax_cross_entropy(h, y) error.backward() optimizer.update()
そして、トレーニングデータを流し込んで、トレーニングを進めていく。データはMNISTのファイルに格納されている数だけ流していった。
for epoch in six.moves.range(1, n_epoch + 1): print('epoch', epoch) perm = np.random.permutation(N) for i in six.moves.range(0, N, batchsize): x_part = x_train[perm[i:i + batchsize]] y_part = y_train[perm[i:i + batchsize]] model.train (x_part, y_part)
そしてテストだが、テスト結果を評価するために配列を用意し、あらかじめ回答(実際にどの数値に相当するか)に相当するインデックスのみ1となるベクトルを作っておく。 それと回答を比較し、どの程度精度が出ているかチェックするという訳だ。
sum_accuracy = 0 sum_loss = 0 for i in six.moves.range(0, N_test, batchsize): x_batch = x_test[i:i + batchsize] y_batch = y_test[i:i + batchsize] y_array = np.zeros((len(y_batch), 10), dtype=np.float32) for j in six.moves.range(0, y_batch.size): y_array[j][y_batch[j]]=1.0 y = model._forward(x_batch) # x_test = chainer.Variable(np.asarray(x_batch)) loss = F.mean_squared_error(y.data, y_array) print ('loss = {}'.format(loss.data / N_test))
なんとなく動作しているみたいだが、まだ間違っているかも...
loss = 0.00358625297546 loss = 0.00344880523682 loss = 0.00420735664368 loss = 0.00476919555664 loss = 0.0032996635437 loss = 0.00307750492096 loss = 0.00348921127319 loss = 0.00370487632751 loss = 0.0027250743866 loss = 0.0024638835907 loss = 0.00238158721924 loss = 0.00273185806274
いろんなネットワークを構築したり、TensorFlowと比較したりして、もっと勉強しなければ。