【画像認識】Deep Learningフレームワーク「Chainer」で自前データで学習する方法
はじめに
前回は「Chainer」で学習するための下準備として、
学習データのリストファイルを作成する方法について紹介させていただきました。
ということで、準備は完了したのでいよいよ今回は学習について紹介します。
ソースコード
学習に必要なソースコードとして
学習モデルと学習処理を載せています。
学習モデルが精度の肝になっていて、
数値や処理を変えることで結果が変わってきます。
※GPUを使用することを前提としています。
GPUを使用しない場合は、ソースコード内の「cuda」、「gpu」を削除すれば動くはずです。
- 学習モデル
※14行目の「784」は入力画像サイズによって変わってきます。今後計算方法を紹介できればと思います。
# -*- coding:utf-8 -*- from chainer import cuda, Function, FunctionSet, gradient_check, Variable, optimizers, serializers from chainer.training import extensions import chainer.functions as F class CNN(): cuda.get_device(0).use() # GPUを使用することを前提とする def __init__(self): self.model = FunctionSet( conv1 = F.Convolution2D(1,32,3,pad=1), conv2 = F.Convolution2D(32,32,3,pad=1), conv3 = F.Convolution2D(32,16,3,pad=1), conv4 = F.Convolution2D(16,16,3,pad=1), l1 = F.Linear(784,50), l2 = F.Linear(50,3), ).to_gpu() def forward(self, x_data, y_data, train=True): x, t = Variable(x_data), Variable(y_data) c = F.max_pooling_2d(F.relu(self.model.conv1(x)), 2) c = F.max_pooling_2d(F.relu(self.model.conv2(c)), 2) c = F.max_pooling_2d(F.relu(self.model.conv3(c)), 2) c = F.max_pooling_2d(F.relu(self.model.conv4(c)), 2) h = F.dropout(F.relu(self.model.l1(c)), train=train) y = self.model.l2(h) if train: # 学習時 return F.softmax_cross_entropy(y, t) else: return y # 評価時
- 学習処理
※46行目あたりの画像サイズは用意した画像のサイズに合わせてください。
# -*- coding:utf-8 -*- import numpy as np import chainer from chainer import cuda, Function, FunctionSet, gradient_check, Variable, optimizers, serializers from chainer.training import extensions import argparse import random import chainer.functions as F import cv2 import CNN_model as cnn import time cuda.get_device(0).use() # GPUを使用することを前提とする # 引数指定 parser = argparse.ArgumentParser(description='Train Sample') parser.add_argument('--train_list', '-train', default='train.txt', type=str, help='Train data list') parser.add_argument('--test_list', '-test', default='test.txt', type=str, help='Test data list') parser.add_argument('--epoch', '-e', type=int, default=100, help='Number of epochs to train') args = parser.parse_args() # 学習モデル設定 model = cnn.CNN() optimizer = optimizers.Adam() optimizer.setup(model.model) # 学習データリストファイルから一行ずつ読み込む train_list = [] for line in open(args.train_list): pair = line.strip().split() train_list.append((pair[0], np.float32(pair[1]))) # 画像データとラベルデータを取得する x_train = [] # 画像データ格納 y_train = [] # ラベルデータ格納 for filepath, label in train_list: img = cv2.imread(filepath, 0) # グレースケールで読み込む x_train.append(img) y_train.append(label) # 学習で使用するsoftmax_cross_entropyは # 学習データはfloat32,ラベルはint32にする必要がある。 x_train = np.array(x_train).astype(np.float32) y_train = np.array(y_train).astype(np.int32) # 画像を(学習枚数、チャンネル数、高さ、幅)の4次元に変換する x_train = x_train.reshape(len(x_train), 1, 100, 100) / 255 N = len(y_train) batchsize = 100 datasize = len(x_train) n_epoch = args.epoch # 繰り返し学習回数 # 学習開始 train_start = time.time() for epoch in range(1, n_epoch+1): sum_loss = 0 perm = np.random.permutation(N) # データセットの順番をシャッフル train_start_one = time.time() for i in range(0,datasize, batchsize): x_batch = cuda.to_gpu(x_train[perm[i:i+batchsize]]) # バッチサイズ分のデータを取り出す y_batch = cuda.to_gpu(y_train[perm[i:i+batchsize]]) # 初期化 optimizer.zero_grads() # 誤差伝播 loss = model.forward(x_batch, y_batch, train=True) # 誤差逆伝播 loss.backward() # ネットワークパラメータ更新 optimizer.update() sum_loss += loss.data print "epoch:{} loss={} time:{}".format(epoch, sum_loss / (datasize/batchsize), time.time()-train_start_one) print "train time:{}".format(time.time()-train_start) # 学習したモデルを出力する serializers.save_npz("model_{}".format(n_epoch), model.model) serializers.save_npz("state_{}".format(n_epoch), optimizer)
実行結果
上記のソースコードを使用し、
自前で用意した以下のような図形データ(円、三角、四角)を学習しました。
データ数はそれぞれ10,000枚用意しています。
~\chainer>python train.py -train .\chainer_data\train.txt epoch:1 loss=0.234141930938 time:47.6890001297 epoch:2 loss=0.0120183927938 time:44.8639998436 epoch:3 loss=0.00538328383118 time:45.0660002232 epoch:4 loss=0.00240588164888 time:44.8359999657 epoch:5 loss=0.00354681606404 time:44.9549999237 epoch:6 loss=0.00137812725734 time:44.9100000858 epoch:7 loss=0.0240326672792 time:45.123000145 epoch:8 loss=0.0008278505411 time:44.8499999046 epoch:9 loss=0.00111551373266 time:44.9399998188 epoch:10 loss=0.000555399165023 time:44.9600000381 ~略~ epoch:90 loss=0.000580499123316 time:44.5870001316 epoch:91 loss=2.5021530746e-05 time:44.6370000839 epoch:92 loss=5.85371271882e-05 time:44.6289999485 epoch:93 loss=6.34381358395e-05 time:44.7200000286 epoch:94 loss=7.72891962697e-06 time:44.9309999943 epoch:95 loss=0.000185455748579 time:44.9500000477 epoch:96 loss=0.00284633412957 time:44.7589998245 epoch:97 loss=6.4926345658e-05 time:44.8150000572 epoch:98 loss=2.26454394578e-05 time:44.7060000896 epoch:99 loss=0.000476426939713 time:44.9259998798 epoch:100 loss=0.00179152819328 time:44.8580000401 train time:4524.86300015
最後に
今回は学習方法について紹介しました。
次回は学習したモデルを使用して識別する方法を紹介します。
P.S.
実は今日からなんと10連休!
だが、予定はないという...(-_-;
こうなったらDeep Learningとアプリ開発とことんやってやります!
【関連記事】
- 「Chainer」の構築
- 「Chainer」での学習の下準備
- 「Chainer」での自前データによる識別