Зачем вам визуализация активаций модели TensorFlow

автор рубрика ,
Зачем вам визуализация активаций модели TensorFlow

Продолжаем говорить о сверточных нейронных сетях (CNN) с использованием Python-фреймворка TensorFlow в рамках задач Computer Vision. Для понимания работы глубоких сверточных сетей может пригодиться визуализация. В этой статье мы расскажем, как посмотреть результаты промежуточных активаций TensorFlow модели с помощью визуализации данных; и узнаем, как сверточные сети фильтруют изображения.

Инициализация модели TensorFlow

Воспользуемся моделью Machine Learning, которая была обучена в Python-фреймворке TensorFlow для распознавании кошек и собак из прошлой статьи. Вот так она выглядит:

>>> model.summary()
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 148, 148, 32)      896       
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 74, 74, 32)        0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 72, 72, 64)        18496     
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 36, 36, 64)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 34, 34, 128)       73856     
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 17, 17, 128)       0         
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 15, 15, 128)       147584    
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 7, 7, 128)         0         
_________________________________________________________________
dropout (Dropout)            (None, 7, 7, 128)         0         
_________________________________________________________________
flatten (Flatten)            (None, 6272)              0         
_________________________________________________________________
dense (Dense)                (None, 512)               3211776   
_________________________________________________________________
dense_1 (Dense)              (None, 1)                 513       
=================================================================
Total params: 3,453,121
Trainable params: 3,453,121
Non-trainable params: 0

На валидационной выборке эта модель машинного обучения показывала точность около 90%. На основе этой модели покажем результаты функций активации всех фильтров в ответ на входное изображение. Так, для первого сверточного слоя (conv2d) будет 32 результата функции активации, а для второго (conv2d_1) — 64.

Преобразование входного изображения

Изображение нужно получить в виде тензора, а форма тензора должна совпадать с формой входного сигнала.

Первый сверточный слой принимает на вход цветное изображение (150,150). Причём 1-е измерение соответствует размеру пакета, но поскольку мы хотим посмотреть только на одной, то оно должно быть равно 1. Для обработки изображения в Keras есть специальный модуль image. Так подготовка изображения в Python выглядит следующим образом:

from keras.preprocessing import image
import numpy as np

img_path = test_cats_dir / 'cat.1016.jpg'

img = image.load_img(img_path, target_size=(150, 150))
img_tensor = image.img_to_array(img)
img_tensor = np.expand_dims(img_tensor, axis=0)
# Изображение нужно приводить к диапазону [0,1]
img_tensor /= 255.

print(img_tensor.shape)
#
(1, 150, 150, 3)

Можем взглянуть на это изображение с помощью Python-библиотеки Matplotlib. Именно на этой картинке будем проводить визуализацию промежуточных активаций TensorFlow.

import matplotlib.pyplot as plt

plt.imshow(img_tensor[0])
plt.show()
Визуализация кошки TensorFlow
Входное изображение с котом

Извлечение карт признаков

Теперь нужно получить результаты активаций от фильтров в каждом сверточном слое. Для этого нам понадобится класс Model, который принимает входной тензор и тензоры слоев. Нам нужны только сверточные слои, т.е. первые 8 слоев. Вот так выглядит получение результатов активации TensorFlow-модели в Python:

from tensorflow.keras import models

layer_outputs = [layer.output for layer in model.layers[:8]]
activation_model = models.Model(inputs=model.input, outputs=layer_outputs)
acts = activation_model.predict(img_tensor)

Мы можем посмотреть на результаты активации в первом сверточном слое нашей нейронной сети. Этот слой содержит 32 фильтра (conv2d). Например, вот так это выглядит для 1-го фильтра:

first_layer_activation = acts[0]
plt.matshow(first_layer_activation[0, :, :, 1], cmap='viridis')
Визуализация ответов от третьего фильтра модели TensorFlow
Результат активации от 1-го фильтра

Ниже пример Python для визуализация результата функции активации для 30-фильтра. Скорее всего, первый сверточный слой ответственен за контур животных.

plt.matshow(first_layer_activation[0, :, :, 30], cmap='viridis')
Визуализация ответов от тридцатого фильтра модели TensorFlow
Результат активации от 30-го фильтра

Визуализация активаций для всех фильтров

Перебирать по одному фильтру и слою дело затруднительное, поэтому лучшего всего автоматизировать этот процесс. Ниже функция на Python для визуализации результатов активации модели TensorFlow. Мы создаём сетку, содержащую 16 колонок. В каждой ячейке результат активации

images_per_row = 16

for layer_output, layer_activation in zip(layer_outputs, acts):
    if not layer_output.name.startswith('max'):
        # Количество фильтров в карте признаков
        n_features = layer_activation.shape[-1]

        # Признак имеет форму: (1, высота, ширина, n_features)
        size = layer_activation.shape[1]

        # Разместим результаты активации в виде сетки.
        # На каждой строке будет по images_per_row (16)
        n_cols = n_features // images_per_row
        display_grid = np.zeros((size * n_cols, images_per_row * size))

        for col in range(n_cols):
            for row in range(images_per_row):
                # Фильтр:
                channel_image = layer_activation[0,
                                                :, :,
                                                col * images_per_row + row]
                # Постобработка, чтобы получить приемлимую визуализацию
                channel_image -= channel_image.mean()
                channel_image /= channel_image.std()
                channel_image *= 64
                channel_image += 128
                channel_image = np.clip(channel_image, 0, 255).astype('uint8')
                display_grid[col * size : (col + 1) * size,
                             row * size : (row + 1) * size] = channel_image

        # Визуализация результатов активации модели TensorFlow
        scale = 1. / size
        plt.figure(figsize=(scale * display_grid.shape[1],
                            scale * display_grid.shape[0]))
        plt.title(layer_output.name)
        plt.grid(False)
        plt.imshow(display_grid, aspect='auto', cmap='viridis')
plt.show()
Все фильтры сверточной нейронной сети TensorFlow
Результаты активаций первого слоя

Нажмите, чтобы посмотреть результаты визуалзиации всех слоев.

Итоги визуализации

Можем увидеть, что с переходом к новому слою результат активаций становится более специфичным и абстрактным. Например, последний слой (conv2d_3) для человека уже становится непонятен. Но для нейронной сети это может значить «ухо», «ус», «родинка». Именно так и работают глубокие нейронные сети (Deep Learning) — углубляются и специализируются с увеличением уровня слоя.

К тому же от слоя к слою увеличивается количество пустых фильтров. Это значит, что слой не видит специфичных признаков, которые принадлежат этому изображению. Таким образом, с увеличением глубины ещё и фильтруется входящая информация. Похожим образом работает мозг человека. Например, если его попросить нарисовать кошку, то он отфильтрует все детали, изобразив только специфичные для кошки признаки.

 

Ещё больше подробностей о работе сверточных нейронных сетей на реальных примерах Data Science с использованием Python-фреймворка TensorFlow, вы узнаете на нашем специализированном курсе «VISI: Computer Vision» в лицензированном учебном центре обучения и повышения квалификации Data Scientist’ов и IT-специалистов в Москве.

Источники
  1. https://distill.pub/2019/activation-atlas/
Комментировать

Ваш адрес email не будет опубликован. Обязательные поля помечены *