19
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

CNNの学習結果を可視化する

Last updated at Posted at 2018-10-13

※△1 2019.02.01 動かない環境があった為修正
※△2 2019.02.03 文章を各所修正

CNNの任意の特長マップを使用して可視化をするスクリプトです

下記にある通りGrad-CAMで表示がおかしくなる学習結果に対しても
そこそこ良好な可視化結果を得られています。

ただし問題がありまして、識別率が低い画像を可視化すると
判別に使用していない特長フィルターも可視化されてしまうので
関係ないところまで反応してしまうという問題があります

この辺はGrad-CAMの手法で解決できるので
両方を使い分けるのがいいと思います

#確認環境
 python3.6.6 , 3.6.7 , 3.6.8
 Tensorflow:1.10.0
 Keras:2.2.2 , 2.2.4

#やり始めたきっかけ
Grad-CAMを使って作成したモデルの評価を行っていました
いつものデータセットを使いVGG16のファインチューニングでval_acc「0.967」くらいの結果なので
まぁまぁ識別できているモデルかと思われます
image.png
image.png

キャラ識別は顔(髪、目)をきちんとみているんだなぁ・・・
Grad-CAMすご・・・
image.png
???
image.png

????
どこを注視しているんですかね?(笑

識別の結果はラベル通り(正解)ですし
若干の変態感が気になりますが、とりあえず識別結果は出ているのと
Grad-CAMは動いたということで放置していました。

ただ、他のデータセットでも同じような現象が発生したことと
画像にコンターっぽい色がつくと業務で~~だまし~~
説得力が増すので違う方法を考えておりました

#暫定の対応策

とりあえず下記のように、全結合層前の**「block5_conv3」**の
特長マップを見てなんとかならないかと作業しておりました

※△12019.02.01修正
新しくインストールした環境で動かなかったので
特長マップを抜きだすところを修正

get_layer_output = K.function([model.layers[0].input],[model.layers[17].output])
print(model.layers[17])
layer_output = get_layer_output([img_nad])[0]

ただVGG16ですと、この位置の特長マップ512もあるし
どうやって表示するか・・・
縦横に並べてもすごい数だし、めんどくさいなぁ・・・と・・・

修正前

get_layer_output = K.function([model.layers[0].input,
                               K.learning_phase()],
                               [model.layers[17].output])
print(model.layers[17])
layer_output = get_layer_output([img_nad, 0])[0]

#バカの考え休むになんとか
反応していないチャンネルもあるし
大体似たような位置に反応があるので・・・

「全部足して割ればいいんじゃない?」

とりあえずやってみます

G, R ch = layer_output.shape[1:]
res = np.zeros((G,R))
    
for i in range(ch):
    img_res = layer_output[0,:,:,i]
    res = res + img_res 

res = res/ch
plt.imshow(res)
plt.show() 

それっぽいのが出力されました!!
image.png

#それっぽく見せる
詳細は別途解説しますが
 1.特長量マップを平坦化
 2.モノクロにコンターっぽい色を付ける
 3.14x14を入力画像サイズに
 4.合成
を追加しまして
image.png
image.png

わりと見れる感じに塗り絵できました
素人にならGrad-CAM(のようなもの)で押し切れる!?!?

#スクリプト全体
ファイル名とかフォルダ名は適時適当に変換してください

from keras.models import load_model
import numpy as np
from keras import backend as K
from keras.preprocessing.image import array_to_img, img_to_array, load_img, save_img
import cv2
from IPython.display import display_png

#モデルの読込み
file_name='vgg16_madomagi_SGD0.001_G_D4096_D512'
model=load_model('./result/' + file_name+'.h5')
model.summary()

#対象イメージの読込み
jpg_name = 'madoka0137'
img_path = ('./madoka_magica_images/display/' + jpg_name + '.jpg')
img = img_to_array(load_img(img_path, target_size=(224,224)))
H,W =img.shape[:2]
img_nad = img_to_array(img)/255
img_nad = img_nad[None, ...]

#特長マップを抜き出すレイヤー指定
get_layer_output = K.function([model.layers[0].input],[model.layers[17].output])
print(model.layers[17])
layer_output = get_layer_output([img_nad])[0]

#特長マップ合成
G, R, ch = layer_output.shape[1:]
res = np.zeros((G,R))
    
for i in range(ch):
    img_res = layer_output[0,:,:,i]
    res = res + img_res       

res = res/ch

#特長マップ平均の平坦化
res_flatte = np.ma.masked_equal(res,0)
res_flatte = (res_flatte - res_flatte.min())*255/(res_flatte.max()-res_flatte.min())
res_flatte = np.ma.filled(res_flatte,0)

#色付け
acm_img = cv2.applyColorMap(np.uint8(res_flatte), cv2.COLORMAP_JET)
acm_img = cv2.cvtColor(acm_img, cv2.COLOR_BGR2RGB)
acm_img = cv2.resize(acm_img,(H,W))

#元絵と合成
mixed_img = (np.float32(acm_img)*0.6 + img *0.4)

#表示
out_img = np.concatenate((img, acm_img, mixed_img), axis=1)
display_png(array_to_img(out_img))
19
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?