【Python】KerasでVGG16を使って画像認識をしてみよう!

機械学習
この記事は約13分で読めます。

みなさん,こんにちは.
シンノユウキ(shinno1993)です.

今回は学習済みCNNモデル:VGG16を用いて,一般的な画像の分類を行ってみたいと思います.理論などの説明は割愛し,道具としてこれを使えるようになることを目指します.では行きましょう!

 

VGG16とは?

VGG16というのは,「ImageNet」と呼ばれる大規模画像データセットで学習された,16層からなるCNNモデルのことです.2014年に発表されました.様々な研究で利用されている,有名な学習済みモデルの1つです.ImageNetで学習されたモデルには他にAlexNet,GoogLeNet,ResNetがあります.

このVGG16に関する論文は以下で公開されています.

Very Deep Convolutional Networks for Large-Scale Image Recognition
In this work we investigate the effect of the convolutional network depth on its accuracy in the large-scale image recognition setting. Our main contribution is...

VGG16では,出力層(最終的に分類される層)が1000あるため,入力された画像などを1000のクラスに分類することができます.

 

Kerasで使ってみる

ではさっそく,KerasでVGG16を使ってみましょう.

以下のコードを実行してください.

import numpy as np
from keras.applications.vgg16 import VGG16, preprocess_input, decode_predictions
model = VGG16(include_top=True, weights='imagenet', input_tensor=None, input_shape=None)

1-2行目では必要なライブラリなどをインポートしています.VGG16はKerasにすでに実装されているため,それを呼び出すことで簡単に使用できます.

3行目で実際にVGG16の学習済みモデルを取り込んでいます.引数の意味は以下の通りです.

引数説明
include_top1000クラスに分類するフル結合層を含むかどうか.
True:含む(元の1000分類に使う場合はこちら)
False:含まない(カスタマイズする場合はこちら)
weights重みの種類
imagenet:ImageNetを使って学習した重み
None:ランダム
input_tensorモデル画像を入力する場合に使用
任意の画像データ:それを使用
None:使用しない
input_shape入力画像の形状を指定
任意の形状:それを使用
None:(224, 224, 3)が使用される

ではせっかくなのでモデルの中身をみてみましょう.以下のコードでその中身を見ることができます.

model.summary()

以下のようなモデルの構造が表示されるかと思います.

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

畳み込み層(convolution2dの部分)が13層,全結合層(fc1, fc2, predictions)が3層で全部で16層であることがわかります.畳み込み層やそれを集約するプーリング層で画像の特徴を見出し,それを全結合層で分類するという構造をしています.

 

画像を認識してみよう!

では早速,VGG16を用いて画像認識をしてみましょう.

なお,今回の使用しているコードは以下の記事を参考にしました.
分かりやすい記事で,私の記事でいまいち?な場合はぜひご参照ください!

KerasでVGG16を使う - 人工知能に関する断創録
今回は、Deep Learningの画像応用において代表的なモデルであるVGG16をKerasから使ってみた。この学習済みのVGG16モデルは画像に関するいろいろな面白い実験をする際の基礎になるためKerasで取り扱う方法をちゃんと理解しておきたい。 ソースコード: test_vgg16 VGG16の概要 VGG16*...

 

from keras.applications.vgg16 import VGG16, preprocess_input, decode_predictions
from keras.preprocessing import image
import requests
import numpy as np
model = VGG16(include_top=True, weights='imagenet', input_tensor=None, input_shape=None)


#画像をダンロードするための関数
def download_img(url, file_name):
    r = requests.get(url, stream=True)
    if r.status_code == 200:
        with open(file_name, 'wb') as f:
            f.write(r.content)


if __name__ == '__main__':
    #画像のダウンロード
    url = 'https://cdn.pixabay.com/photo/2016/03/05/19/02/hamburger-1238246_1280.jpg'
    file_name = 'hamburger.jpg'
    download_img(url, file_name)
    img = image.load_img(file_name, target_size=(224, 224))
    
    # 読み込んだPIL形式の画像をarrayに変換
    ary = image.img_to_array(img)

    #サンプル数の次元を1つ増やし四次元テンソルに
    ary = np.expand_dims(ary, axis=0)

    #上位5を出力
    preds = model.predict(preprocess_input(ary))
    results = decode_predictions(preds, top=5)[0]
    for result in results:
        print(result)

では,コードを解説していきます.

1-5行目では必要なライブラリをインポートし,5行目で先述したVGG16を学習済みモデルとしてインポートしています.

9-13行目では画像を今回画像認識に使用する画像をダウンロードするための関数を定義しています.画像をダウンロードするためのURLと,保存するためのファイル名を引数とした関数です.ちなみに,今回選択した画像は以下のハンバーガーの画像です!(かなりわかりやすい,ノイズのない良い画像ですね)

https://cdn.pixabay.com/photo/2017/02/20/18/03/cat-2083492_1280.jpg

 

16-33行目が今回の画像認識のメインの部分です.

18-21行目で画像のダウンロードを行っています.URLと保存するファイル名を指定し,先ほど定義したdownload_img関数を実行しています.そして保存されたファイルをimage.load_img関数でロードしています.画像サイズはVGG16のデフォルサイズである224×224を指定します.

24行目では読み込んだ画像を配列形式に変換しています.このように配列形式に変換することで機械学習に画像を投入することができるようになります.

27行目では4次元テンソルに変換しています.VGG16で画像を入力する際には以下の4つの次元をもったテンソルに変換する必要があります:
(samples, rows, cols, channels)
元のaryはsamplesの次元を持っていないので,その次元を追加しています.今回は画像を1枚しか使わないので,これで問題ありません.

30-33行目ではモデルに画像を入力し,予測させ,その結果を出力しています.30行目ではモデルに画像を入力しています.そして,decode_predictionで予測結果を文字列に変換しています.top=5とすること予測された上位5つを返してくれます.そして32行目で上位5つを1つずつ出力しています.結果,以下の5つが出力されるかと思います.

('n07697313', 'cheeseburger', 0.99998677)
('n07693725', 'bagel', 1.2767959e-05)
('n02776631', 'bakery', 3.881851e-07)
('n07697537', 'hotdog', 9.392271e-08)
('n07613480', 'trifle', 7.705837e-09)

1位がチーズバーガーになっています.99.9%の確率となっていますので,かなり強く区別していることがわかりました!

 

まとめ

今回は学習済みモデルのVGG16を持ちいて画像認識をしてみました.面倒な学習が不要ということで,この程度の精度でよければ非エンジニアでも簡単に使用できるのではないでしょうか.近々,このVGG16をFine-tuningする方法をアップしてみたいと思います.ご期待ください!

 

 

 

 

タイトルとURLをコピーしました