ディープラーニングの畳み込みニューラルネットワーク(CNN)のフィルタを可視化してみました。可視化に使用したのは、5種類の花の分類に使用したVGG16を転移学習したモデルです。VGG16は、ディープラーニングによる画像応用の代表的なモデルの一つです。
VGG16(転移学習)モデルのフィルタを可視化してみる。
In [1]:
import os
import keras
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential, Model
from keras.layers import Input, Dense, Dropout, Activation, Flatten
from keras import optimizers
from keras.applications.vgg16 import VGG16
In [2]:
keras.__version__
Out[2]:
訓練画像、検証画像、テスト画像のディレクトリ
In [3]:
# 分類クラス
classes = ['daisy', 'dandelion','rose','sunflower','tulip']
nb_classes = len(classes)
batch_size_for_data_generator = 20
base_dir = "."
test_dir = os.path.join(base_dir, 'test_images')
test_daisy_dir = os.path.join(test_dir, 'daisy')
test_dandelion_dir = os.path.join(test_dir, 'dandelion')
test_rose_dir = os.path.join(test_dir, 'rose')
test_sunflower_dir = os.path.join(test_dir, 'sunflower')
test_tulip_dir = os.path.join(test_dir, 'tulip')
# 画像サイズ
img_rows, img_cols = 200, 200
VGG16モデル
In [4]:
input_tensor = Input(shape=(img_rows, img_cols, 3))
vgg16 = VGG16(include_top=False, weights='imagenet', input_tensor=input_tensor)
#vgg16.summary()
VGG16モデルに全結合分類器を追加する
In [5]:
top_model = Sequential()
top_model.add(Flatten(input_shape=vgg16.output_shape[1:]))
top_model.add(Dense(256, activation='relu'))
top_model.add(Dropout(0.5))
top_model.add(Dense(nb_classes, activation='softmax'))
model = Model(inputs=vgg16.input, outputs=top_model(vgg16.output))
model.summary()
In [6]:
model.compile(loss='categorical_crossentropy',optimizer=optimizers.RMSprop(lr=1e-5), metrics=['acc'])
学習結果を読み出す
In [7]:
hdf5_file = os.path.join(base_dir, 'flower-model.hdf5')
model.load_weights(hdf5_file)
In [8]:
import matplotlib.pyplot as plt
In [9]:
%matplotlib inline
フィルタを出力する中間層を選択する
In [10]:
import numpy as np
from keras import backend as K
In [11]:
layer_output = model.get_layer('block1_conv1').output
layer_output
Out[11]:
損失関数
In [12]:
filter_index = 0
loss = K.mean(layer_output[:,:,:,filter_index])
損失関数の勾配
In [13]:
grads = K.gradients(loss,model.input)[0]
grads /= (K.sqrt(K.mean(K.square(grads))) + 1e-5)
入力画像から損失と勾配を計算する関数
In [14]:
iterate = K.function([model.input],[loss,grads])
勾配上昇法
In [15]:
input_img_data = np.random.random((1,img_rows,img_cols,3))*20+128.
In [16]:
step = 1.
for i in range(40):
loss_value, grads_value = iterate([input_img_data])
input_img_data += grads_value * step
テンソルを画像に変換する関数定義
In [17]:
def depross_image(x):
x -= x.mean()
x /= (x.std() + 1e-5)
x *= 0.1
x += 0.5
x = np.clip(x, 0, 1)
x *= 255
x = np.clip(x, 0, 255).astype('uint8')
return x
フィルタを可視化する
In [18]:
print(input_img_data.shape)
In [19]:
plt.imshow(depross_image(input_img_data[0]))
Out[19]:
別の中間層のフィルタを表示する
In [20]:
layer_output = model.get_layer('block5_conv3').output
layer_output
Out[20]:
In [21]:
filter_index = 0
loss = K.mean(layer_output[:,:,:,filter_index])
In [22]:
grads = K.gradients(loss,model.input)[0]
grads /= (K.sqrt(K.mean(K.square(grads))) + 1e-5)
In [23]:
iterate = K.function([model.input],[loss,grads])
In [24]:
step = 1.
for i in range(40):
loss_value, grads_value = iterate([input_img_data])
input_img_data += grads_value * step
In [25]:
plt.imshow(depross_image(input_img_data[0]))
Out[25]:
<参考>
Francois Chollet 著、株式会社クイープ 翻訳、巣籠悠輔 監訳、「PythonとKerasによるディープラーニング」、マイナビ出版