In [1]:
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "1"
Подключим Keras и все необходимые нам модули
In [1]:
import keras
from keras import applications
from keras.applications import imagenet_utils
from keras import backend as K
import numpy as np
import tensorflow as tf
In [2]:
from scipy.misc import imresize
In [3]:
from imageio import imread, imwrite
In [4]:
sess = K.get_session()
sess.as_default()
Out[4]:
In [5]:
import matplotlib.pyplot as plt
# plt.style.use('ggplot')
%matplotlib inline
plt.rcParams['figure.figsize'] = (20,10) # set default size of plots
В модуле applications вы сможете найти большое количество предтренированных моделей. Загрузим уже знакомый нам VGG16, обученный на Imagenet
In [6]:
# build the VGG16 network
K.clear_session()
model = applications.VGG16(include_top=True,
weights='imagenet')
В Keras существуют удобные средства для визуализации моделей.
In [7]:
model.summary()
Так же мы можем вывести на экран граф модели:
In [9]:
from IPython.display import SVG
SVG(model_to_dot(model, show_shapes=True).create(prog='dot', format='svg'))
Out[9]:
Загрузим произвольную фотографию. Можно из http://image-net.org/, а можно и просто произвольную.
In [10]:
image = imread('image_1.jpg')
In [11]:
plt.imshow(image)
Out[11]:
Обратите внимание, что изображения должнв иметь разрешение 224х224
In [12]:
resized_image = imresize(image, (224, 224))
In [13]:
plt.imshow(resized_image)
Out[13]:
Проверим может ли модель определить, к какому классу относится объект на изображении
In [16]:
y = model.predict(np.expand_dims(resized_image, 0))
В Keras есть специальная функция, которая достаёт лейблы классов из Imagenet
In [18]:
imagenet_utils.decode_predictions(y)
Out[18]:
Теперь определим функцию, считающую градиент от выходов модели
In [8]:
# Получаем тензор, отвечающий за вход модели
input_img = model.input
# Получаем тензор, отвечающий за выход
output = model.output
# Вызываем метод бэкенда, рассчитывающий градиент
grads = K.gradients(output, input_img)[0]
# Оборачиваем всё это в специальную абстракцию,
# которая скрывает вызов сессии TF
get_gradient = K.function([input_img], [grads])
Теперь мы можем рассчитать градиент
In [13]:
grad_val = get_gradient([np.expand_dims(resized_image, 0)])[0]
Как видим, shape градиента совпадает с shape изображения
In [14]:
grad_val.shape
Out[14]:
In [15]:
grad_val = np.squeeze(grad_val)
Для того, чтобы "посветить" значимые области найдём максимум поканально
In [16]:
mask = np.max(np.abs(grad_val), axis=-1)
In [17]:
plt.imshow(mask, cmap='gray')
Out[17]:
In [25]:
fig = plt.figure()
a=fig.add_subplot(1,2,1)
imgplot = plt.imshow(mask, cmap='gray')
a.set_title('Saliency Map')
a=fig.add_subplot(1,2,2)
imgplot = plt.imshow(resized_image)
a.set_title('Image')
plt.show()
In [ ]: