今回は、Keras のVGG16学習済みモデルを使って、一般物体認識をやってみたいと思います。
こんにちは cedro です。
Keras には学習済みモデルがあり、これを使えば膨大な量のデータを収集し、長時間掛けて学習をすることなしに、大規模な学習済みモデルを動かせます。
例えば、2014年の画像認識コンテスト ILSVR で2位になった、あの有名なVGG16の学習済みモデルもあります。このモデルは、畳み込み13層+全結合層3層のニューラルネットワークに、1000カテゴリー、224×224のカラー画像をなんと120万枚学習させた凄いもので、個人で一から学習させるのはまず不可能なものです。
こんなディープラーニングの大規模な学習済みモデルが、誰でもインターネットから手に入れて使える時代になったわけです。なんて、素敵なことでしょう!
というわけで、今回は、Keras のVGG16学習済みモデルを使って、一般物体認識をやってみたいと思います。
VGG16は何を学習しているのか
VGG16学習済みモデルは、一体どんなものを学習しているのでしょうか。これが分からないと物体認識させるためにどういう画像を用意したら適切なのかが分かりません。
実は、これについての情報がWebにはあまりなく、色々探した結果、Github でやっと見つけました。ILSVRC2012_class_name.csv というファイルがそれで、1000カテゴリーの名前が和訳付きでまとめられています。starpentagon さん、感謝です。
ファイルを参考に、Webから、Saint_Bernard(セントバーナード)、Cheetah(チータ)、Flamingo(フラミンゴ)、Grand_Piano(グランドピアノ)、Syringe(注射器)、Space_Shuttle(スペースシャトル)、Brassiere(ブラジャー)の7つをgoogleで画像検索しダウンロードして、data フォルダーに格納しました。セントバーナードからブラジャーまで、多彩でしょう?(笑)。
そして、認識結果と照合するために、00.jpg ~ 06.jpg にリネームしています。
なお、画像は、VGG16で認識するために正方形(224×224)にリサイズしますので、極端に長方形なものは避けるのが無難です。
プログラムを作成します
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
from keras.applications.vgg16 import VGG16, preprocess_input, decode_predictions from keras.preprocessing.image import img_to_array, list_pictures, load_img import numpy as np ### VGG16学習済みモデルの読み込み model = VGG16(include_top=True, weights='imagenet', input_shape=None) model.summary() ### 'data'フォルダーから画像データの読み込み x = [] for picture in list_pictures('./data'): img = img_to_array(load_img(picture, target_size=(224,224))) ### 224*224にリサイズ x.append(img) ary = np.asarray(x) print('ary shape:', ary.shape) ### ary shape チェック ### 上位5位まで認識 (データの個数分) for i in range(len(ary)): preds = model.predict(preprocess_input(ary)) results = decode_predictions(preds, top=5)[i] print(i) for result in results: print(result) |
7行目で、学習済みモデルをダウンロードします。引数については、
・include_top : True で全結合層を含める、False(転移学習などで使う)で含めない。
・weights : ‘imagenet’ で学習した重みを読み込む、None だと読み込まない。
・input_shape : 入力画像のシェイプを指定(転移学習などで使う)。今回は、None。
13行目から、画像をデータを読み込み前処理をします。data フォルダーから1つづつ画像を読み込み、224×224にリサイズし、xにアペンド(付け加え)。その後、numpy配列に変換します。aryのシェイプ は、( 7, 224, 224, 3 )となります。
21行目から、認識する部分です。preprocess_input () は VGG16モデルに合わせて前処理をするところ。そして、decode_prediction () は認識結果を表示するところで、top = 5 としておくと上位5位の予測結果を( WordNet ID, クラス名, 確率 )の形式で表示してくれます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
_________________________________________________________________ Layer (type) Output Shape Param # ================================================================= input_1 (InputLayer) (None, 224, 224, 3) 0 _________________________________________________________________ block1_conv1 (Conv2D) (None, 224, 224, 64) 1792 _________________________________________________________________ block1_conv2 (Conv2D) (None, 224, 224, 64) 36928 _________________________________________________________________ block1_pool (MaxPooling2D) (None, 112, 112, 64) 0 _________________________________________________________________ block2_conv1 (Conv2D) (None, 112, 112, 128) 73856 _________________________________________________________________ block2_conv2 (Conv2D) (None, 112, 112, 128) 147584 _________________________________________________________________ block2_pool (MaxPooling2D) (None, 56, 56, 128) 0 _________________________________________________________________ block3_conv1 (Conv2D) (None, 56, 56, 256) 295168 _________________________________________________________________ block3_conv2 (Conv2D) (None, 56, 56, 256) 590080 _________________________________________________________________ block3_conv3 (Conv2D) (None, 56, 56, 256) 590080 _________________________________________________________________ block3_pool (MaxPooling2D) (None, 28, 28, 256) 0 _________________________________________________________________ block4_conv1 (Conv2D) (None, 28, 28, 512) 1180160 _________________________________________________________________ block4_conv2 (Conv2D) (None, 28, 28, 512) 2359808 _________________________________________________________________ block4_conv3 (Conv2D) (None, 28, 28, 512) 2359808 _________________________________________________________________ block4_pool (MaxPooling2D) (None, 14, 14, 512) 0 _________________________________________________________________ block5_conv1 (Conv2D) (None, 14, 14, 512) 2359808 _________________________________________________________________ block5_conv2 (Conv2D) (None, 14, 14, 512) 2359808 _________________________________________________________________ block5_conv3 (Conv2D) (None, 14, 14, 512) 2359808 _________________________________________________________________ block5_pool (MaxPooling2D) (None, 7, 7, 512) 0 _________________________________________________________________ flatten (Flatten) (None, 25088) 0 _________________________________________________________________ fc1 (Dense) (None, 4096) 102764544 _________________________________________________________________ fc2 (Dense) (None, 4096) 16781312 _________________________________________________________________ predictions (Dense) (None, 1000) 4097000 ================================================================= Total params: 138,357,544 Trainable params: 138,357,544 Non-trainable params: 0 |
VGG16の構成を見てみます。畳み込み層(Conv2D)が13層、全結合層(Dense)が3層あることが分かると思います。層は全部で 13+3=16層ありますので、VGG16って言うんですね。
認識してみます
認識させるだけですので、Macbook Airでも軽快に動きます。但し初回のみ、学習済みモデルをダウンロードするので、少し時間がかかります(私のwifi 環境で3分くらい)。
認識結果は、例えば ( ‘ n02109525 ‘, ‘ Saint_Bernard ‘, 0.9999845 ) という形で表示されます。 ‘ n02109525 ‘ は WordNet ID という Imagenet の分類コード、‘ Saint_Bernard ‘ はクラス名、0.9999845 は確率です。確率の高い順に、上位5つが表示されます。
さて結果ですが、全て99.9%以上の確率で認識が出来ています。ま、結果が良かったものを選んだという感はありますが(笑)。それにしても、セントバーナードからブラジャーまで1000カテゴリーを高い精度で認識するとは、VGG16恐るべしです。
もちろん、この世にある物体は1000カテゴリーどころではないわけですが、既に1000カテゴリーをしっかり学習済みであれば、類似なものであれば新たに学習する場合でも少ないデータで早く学習ができるのです。これを転移学習あるいは、ファインチューニングと言うのですが、これについては次回のブログで。
では、また。
コメントを残す