RのWeb制作

Webサービス制作のための技術情報を。データ分析(Python、機械学習コンペ他)や自作野球ゲームMeisyoのこと中心。

Web制作 Python

[Python] ディープラーニングのモデル「VGG16」を使って画像認識をし、判断した理由の可視化をする。

投稿日:

今日はデータ分析から趣向を変えて画像認識を行います。

やることは簡単。

1.撮った写真を使って画像認識させ、何が写っているか判断させる。
2.何が写っているかを判断した理由(位置)を可視化する。

以上です。

今回使う画像はこちら↓

うちの犬です。
トイプードルですが、トイプードルと判定されない子です。

KerasとOpenCVを使っています。
OpenCVのインストールはターミナルから以下のコマンドを~。

pip install opencv-python

では始めます。
まず手始めに、VGG16という学習済みのディープラーニングのモデルをインポートします。
学習が不要なのでノートPCでも簡単に予測ができます。

最新ではないですが、かなり簡単な構造をしているので理解しやすいモデルです。
構造はmodel.summary()で出力できます。

コーディングに使うのでおすすめはJupyter NotebookかGoogle colab.です。
ミスってもやり直しが効くのでとてもやりやすいです。

# VGG1616を読み込み
from keras.applications.vgg16 import VGG16
model = VGG16(weights = 'imagenet')

# 必要なモノをインポート
from keras.preprocessing import image
from keras.applications.vgg16 import preprocess_input, decode_predictions
import numpy as np

次に画像を読み込みます。
224×224にサイズを変更するのは、VGG16の受け入れ可能な画像サイズが224×224だからです。
縦長や横長の画像はちょっと伸び縮みさせて無理やり突っ込まれます

# 画像パス(必要に応じて変更してください)
img_path = '/Users/saito/Desktop/dog190720_1.jpeg'
# 画像を読み込む
img = image.load_img(img_path, target_size=(224, 224))
# 画像の確認
img

あとはVGG16に合わせて前処理を行います。
写真はRGBで読み込まれるので(224, 224, 3)の形式になりますが、
VGG16は(写真No., X, Y, 次元数)の形式で読み込まれるのでそれに合わせます。

# np配列に変換
x = image.img_to_array(img)
# VGG16に合わせるため次元追加
x = np.expand_dims(x, axis=0)
# バッチの前処理
x = preprocess_input(x)

予測させます。

preds = model.predict(x)
print('Predicted:', decode_predictions(preds, top=3)[0])
# miniature_poodleの番号を取得
np.argmax(preds[0])
preds[0][266]

↑の写真を使っていると、miniature_poodleの予測値が最大になります。
miniature_poodleの番号は266なので、それを下記で使います。

写真にどこで判定をしたのか書き込みます。

from keras import backend as K

# 最後の畳み込み層の出力マップを出力
last_conv_layer = model.get_layer('block5_conv3')

# その層でプードルのクラスの勾配を確認
poodle_output = model.output[:, 266]
grads = K.gradients(poodle_output, last_conv_layer.output)[0]

# 平均勾配
pooled_grads = K.mean(grads, axis=(0, 1, 2))

# 出力関数を規定
iterate = K.function([model.input], [pooled_grads, last_conv_layer.output[0]])

# 2つの値をnumpy配列として取得
pooled_grads_value, conv_layer_output_value = iterate([x])

# 重要度を記入する
for i in range(512):
    conv_layer_output_value[:, :, i] *= pooled_grads_value[i]

# ヒートマップ化する
heatmap = np.mean(conv_layer_output_value, axis=-1)

# ヒートマップの後処理(正規化0~1)
heatmap = np.maximum(heatmap, 0)
heatmap /= np.max(heatmap)
plt.matshow(heatmap)

OpenCVの登場です。
今回は写真の上から重要だった部分を書くことに使います。

# OpenCVスーパーインポーズ用
import cv2

# cv2で画像を読み込む
img = cv2.imread(img_path)
# サイズを戻す
heatmap = cv2.resize(heatmap, (img.shape[1], img.shape[0]))
# RGBに変換
heatmap = np.uint8(255 * heatmap)
# 元の画像に適用
heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)

superimposed_img = heatmap * 0.4 + img

# 保存先を指定
img_path2 = '/Users/saito/Desktop/dog190720_1H.jpeg'
cv2.imwrite(img_path2, superimposed_img)

# 画像を読み込む
img2 = image.load_img(img_path2, target_size=(224, 224))
img2

非常に簡単に処理が終わりました。
出来た画像は以下の通りです。

miniature_poodleと判定したのは、耳や胴体が特徴的であったことがわかります。
このようにディープラーニングも判断内容が可視化でき、完全にブラックボックスではないことがわかります。

ちなみに、自分で撮ったどんな写真でも判定可能です。
img_pathとimg_path2の設定フォルダ(デスクトップ)を間違えなければ誰でも可能!

ちょっとやってみたいなーと思ったら、Google colab.へ。
ファイルの読み込み方法が少し違い、下記のコードを使う必要があります。

from google.colab import files
uploaded = files.upload()
uploaded_file_name = next(iter(uploaded_file))
img_path = uploaded_file_name

非常に簡単ですね~(^^)。

-Web制作, Python

執筆者:


  1. […] 前回、[Python] ディープラーニングのモデル「VGG16」を使って画像認識をし、判断した理由の可視化をする。を行っていた際もその疑問がつきませんでした。 […]

comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

関連記事

[Python:Predict Gollira]2枚の画像でどちらがゴリラっぽいかを人間が予想する。

「あーこの人ゴリラっぽい。」と思うことはありませんか? ゴリラっぽさってどこから来るんだろうかと悩んでいました。 前回、[Python] ディープラーニングのモデル「VGG16」を使って画像認識をし、 …

「名将と呼ばれた者達」目標

目標 ・アクティブプレイヤー100人以上(2018年12月末) ・登録人数100人(2018年9月)→達成し次第サーバー変更(AWS?)#試合クソ重くてすみません!弱さーばなんです ・2018年8月公 …

駆け出しエンジニアは本当にフロントエンドエンジニアを目指すべきなのか

最近、駆け出しエンジニアをTwitter上で数多く見るようになりました。 ただ、揃いも揃って「フロントエンドエンジニア」になりたい(意訳)とプロフィールに書いてあります。 なぜでしょうか。 それは何が …

no image

[PHP]まとめ読みをPSRで改良する(1)

今回の改良対象 → ミニ四駆まとめサイト なぜやるのか? PHPのバージョンアップによる速度の向上 一番はこれでしょう。 今のはPHP5.2で動いています。 1割から5割の速度向上が見込まれます。 1 …

no image

PHPのコーディング規則、PSRを学ぶ(5)

PHPのコーディング規則、PSRを学ぶ(4)の続きです。 この記事では、PHPのコーディング規則PSRの規則をまとめます。 1.規則概要 文字コードはUTF-8(BOM無し) 改行コードはLF PHP …