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

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

関連記事

2022年 プログラミング初心者におすすめのPCと備品

はじめに プログラミング始めてみたい(始めてる)けど、パソコン用意したいなあと思った時、ググってみるといろいろ情報がありすぎて困ったあなた。 PC・プログラミング歴20年以上私が見るに、アフィリエイト …

no image

ミニ四駆ブログまとめ RSS読み込み速度の改善

更新時、非常に重い思いをしていたRSS読み込み速度が改善されました。 読み込み時間が約1/3くらいになったと思います。 わかったブログ – 複数のRSSフィードを高速でまとめる方法を参考に …

(VPSでつくる) Pythonのバージョンを2.7.5から3.6.8にする

連載第四回目です。 CentOS7にインストールされているPythonのバージョンが2.7なので、バージョンアップをします。 そうしないとPythonのアプリが動きません。 なぜなら、Python2と …

[SQL]URLから正規表現でホストの抽出

他のサイトの説明が釈然としなかったので投稿。 以下のref0~2番のホストを抽出したいとする。 ref[0] = "http://www.other.com/path1/index …

Flask-Babelを使って、Pythonアプリで多言語対応を行う

Pythonで多言語対応してみたいなーと思っていました。 思っていましたが、実際になかなか使うタイミングがない・・・。 今回自作ゲームでユーザー数の増加がみられ、かつ海外からのアクセスも複数確認できた …