モデルの保存処理等に問題があったため、修正しました。2016/10/25
前回CIFAR-10で学習したモデルデータを使って、任意の画像ファイルをカテゴリ分類してみます。ネットでよく見かけるのは学習して終わり、というも内容ですが、ここでは学習後のモデルデータを使った分類の方法です。
ひとまず、CIFAR-10のテストデータを使ってカテゴリ分類する方法を整理します。事前に必要なライブラリはインポートしておいてください。基本的に前回と同様にインポートすれば問題と思います。
前回記事はこちらです。
hellkite.hatenablog.com
モデルデータのロード
Chainerの学習済みモデルをロードします。pickleを使います。pickleは事前に定義が必要なので、以下のようにロードします。
# 保存したモデル定義 class Model(Chain): def __init__(self): super(Model, 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=F.Linear(512, 512), l2=F.Linear(512, 10) ) def __call__(self, x): h1 = F.relu(self.conv1(x)) h2 = F.max_pooling_2d(F.relu(self.conv2(h1)), 2) h3 = F.relu(self.conv3(h2)) h4 = F.max_pooling_2d(F.relu(self.conv4(h3)), 2) h5 = F.relu(self.conv5(h4)) h6 = F.max_pooling_2d(F.relu(self.conv6(h5)), 2) h7 = F.dropout(F.relu(self.l1(h6)), train=False) y = self.l2(h7) return y model = L.Classifier(Model()) optimizer = optimizers.Adam() optimizer.setup(model) # 保存したモデルを読み込み(2016/10/26更新!) serializers.load_npz('model_cifar10.model', model) serializers.load_npz('model_cifar10.state', optimizer)
pickleの使い方が良くわらからず、ハマりました・・・。ちゃんと調べればすぐ情報があるのに・・・。
serializersを使うとCPU/GPUを意識せずにセーブ/ロードできるそうです。便利。
CIFAR-10のテストデータを準備
モデルに入力するためのテストデータを準備します。画像ファイルを入れる前にCIFAR-10のテストデータを入れてみます。前回のコードを流用します。
import sys def unpickle(file): fp = open(file, 'rb') data = pickle.load(fp, encoding='latin-1') fp.close() return data # テスト画像を準備 test_data_dic = unpickle(os.getcwd()+"\\cifar-10\\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']) # 結果表示用のラベルを準備 batch_meta = unpickle(os.getcwd()+"\\cifar-10\\batches.meta") label_names = batch_meta['label_names']
CIFAR-10のテストデータでの予測
predictorメソッドを使って結果を取得できます。X_testから1枚選んで予測します。
# 選ぶ画像のインデックス index = 1 # 予測 test_data = test_data_dic['data'][index] test_data = test_data.reshape(3, 32, 32) test_data = test_data.astype(np.float32) test_data /= 255 result = model.predictor(Variable(np.array([test_data]))) # 予測出力 for i in range(10): print (label_names[i] + " : " + str(result.data[0,i]))
出力結果がこんな感じ。とても船。
airplane : 4.58905 automobile : -2.67672 bird : -8.51865 cat : -9.40089 deer : -14.1304 dog : -9.87916 frog : -5.56871 horse : -9.97257 ship : 14.8575 truck : -12.6762
前回のコードを使って表示させてみると、確かに船。
渡し方が分かったので任意の画像を渡してみる
ようやく本題です。model.predictor()に渡す形式が分かったので読み込んだ画像ファイルを使って評価してみます。
形式の変換部分は怪しいです・・・。結果が出ているのでいいことにしましたが・・・。
# 画像ファイルのインポート import cv2 img_cv = cv2.imread(os.getcwd()+"\\data\\test.jpg") img = img_cv[:,:,::-1].copy() # 32×32にリサイズする img_32 = cv2.resize(img, (32, 32)) # 形式を変換 (32, 32, 3)から(3, 32, 32)に変更してfloat32に変換 X = img_32.transpose(2, 0, 1) x = X.astype(np.float32) x /= 255 result = model.predictor(Variable(np.array([x]))) # 予測出力 for i in range(10): print (label_names[i] + " : " + str(result.data[0,i]))
テスト画像はGoogle画像検索で持ってきた画像なので載せませんが車の画像です。結果はこんな感じに。
airplane : -19.2472 automobile : 17.372 bird : -16.9361 cat : -11.5837 deer : -34.1684 dog : -14.336 frog : -6.05738 horse : -23.5941 ship : 6.34067 truck : 10.9464
人工物である車、トラック、船が大きな値になっていますね。今回一番高い数値は車なので合格ですね。
今回はCIFAR-10を利用しましたが、画像を使ったカテゴリ分類を一通り体験することができました。色々試せる下地になるかなと思います。