Визуализация активаций сверточной нейронной сети

В этом примере показано, как передать изображение в сверточную нейронную сеть и отобразить активации различных слоев сети. Исследуйте активации и обнаружите, какие функции учит сеть, сравнивая области активации с оригинальным изображением. Узнайте, что каналы в более ранних слоях учатся простым функциям, таким как цвет и ребра, в то время как каналы в более глубоких слоях учатся сложным функциям, таким как глаза. Идентификация функций таким образом может помочь вам понять, чему научилась сеть.

Для примера требуются Deep Learning Toolbox™ и Image Processing Toolbox™.

Загрузка предварительно обученной сети и данных

Загрузите предварительно обученную сеть SqueezeNet.

net = squeezenet;

Чтение и отображение изображения. Сохраните его размер для будущего использования.

im = imread('face.jpg');
imshow(im)

imgSize = size(im);
imgSize = imgSize(1:2);

Просмотр сетевой архитектуры

Проанализируйте сеть, чтобы увидеть, на какие слои можно посмотреть. Сверточные слои выполняют свертки с настраиваемыми параметрами. Сеть учится идентифицировать полезные функции, часто с одной функцией на канал. Заметьте, что первый сверточный слой имеет 64 канала.

analyzeNetwork(net)

Слой Вход задает размер входа. Вы можете изменить размер изображения перед его передачей через сеть, но сеть также может обрабатывать большие изображения. Если вы передаете сети большие изображения, активации также становятся больше. Однако, поскольку сеть обучается на изображениях размера 227 227, она не обучается распознавать объекты или функции, большие, чем этот размер.

Показать активации первого сверточного слоя

Исследуйте функции, наблюдая, какие области в сверточных слоях активируются на изображении и сравнивая с соответствующими областями в оригинальных изображениях. Каждый слой сверточной нейронной сети состоит из многих 2-D массивов, называемых каналами. Передайте изображение через сеть и исследуйте выходные активации conv1 слой.

act1 = activations(net,im,'conv1');

Активации возвращаются как трехмерный массив с третьей размерностью, индексирующим канал на conv1 слой. Чтобы показать эти активации с помощью imtile function, измените форму массива на 4-D. Третья размерность во входе для imtile представляет цвет изображения. Установите третью размерность равным 1, поскольку активация не имеет цвета. Четвертая размерность индексирует канал.

sz = size(act1);
act1 = reshape(act1,[sz(1) sz(2) 1 sz(3)]);

Теперь можно показать активации. Каждая активация может взять любое значение, поэтому нормализуйте выход с помощью mat2gray. Все активации масштабируются так, чтобы минимальная активация была 0, а максимальная - 1. Отобразите 64 изображения на сетке 8 на 8, по одному для каждого канала в слое.

I = imtile(mat2gray(act1),'GridSize',[8 8]);
imshow(I)

Исследуйте активации в конкретных каналах

Каждая плитка в сетке активаций является выходом канала в conv1 слой. Белые пиксели представляют сильные положительные активации, а черные пиксели представляют сильные отрицательные активации. Канал, который в основном серый, не активируется так сильно на вход изображении. Положение пикселя в активации канала соответствует тому же положению в оригинальном изображении. Белый пиксель в некотором местоположении в канале указывает, что канал сильно активирован в этом положении.

Измените размер активаций в канале 22 так, чтобы они имели тот же размер, что и оригинальное изображение, и отобразите активации.

act1ch22 = act1(:,:,:,22);
act1ch22 = mat2gray(act1ch22);
act1ch22 = imresize(act1ch22,imgSize);

I = imtile({im,act1ch22});
imshow(I)

Можно увидеть, что этот канал активируется на красных пикселях, потому что более белые пиксели в канале соответствуют красным областям в оригинальное изображение.

Нахождение самого сильного канала активации

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

[maxValue,maxValueIndex] = max(max(max(act1)));
act1chMax = act1(:,:,:,maxValueIndex);
act1chMax = mat2gray(act1chMax);
act1chMax = imresize(act1chMax,imgSize);

I = imtile({im,act1chMax});
imshow(I)

Сравните с оригинальным изображением и заметьте, что этот канал активируется на ребра. Он активируется положительно на светлых левых / правых ребрах отрицательно на тёмных левых / светлых правых ребрах.

Исследование более глубокого слоя

Большинство сверточных нейронных сетей учатся обнаруживать функции, как цвет и ребра в своем первом сверточном слое. В более глубоких сверточных слоях сеть учится обнаруживать более сложные функции. Более поздние слои наращивают свои функции путем объединения функций более ранних слоев. Исследуйте fire6-squeeze1x1 слой так же, как и conv1 слой. Вычислите, измените форму и отобразите активации в сетке.

act6 = activations(net,im,'fire6-squeeze1x1');
sz = size(act6);
act6 = reshape(act6,[sz(1) sz(2) 1 sz(3)]);

I = imtile(imresize(mat2gray(act6),[64 64]),'GridSize',[6 8]);
imshow(I)

Изображений слишком много, чтобы детально исследовать, поэтому сосредоточьтесь на некоторых из более интересных таковых. Отобразите самую сильную активацию в fire6-squeeze1x1 слой.

[maxValue6,maxValueIndex6] = max(max(max(act6)));
act6chMax = act6(:,:,:,maxValueIndex6);
imshow(imresize(mat2gray(act6chMax),imgSize))

В этом случае максимальный канал активации не так интересен для подробных функций, как некоторые другие, и показывает сильную отрицательную (темную), а также положительную (световую) активацию. Этот канал, возможно, фокусируется на лицах.

В сетке всех каналов есть каналы, которые могут активироваться на глазах. Исследуйте каналы 14 и 47 дополнительно.

I = imtile(imresize(mat2gray(act6(:,:,:,[14 47])),imgSize));
imshow(I)

Многие каналы содержат области активации, которые являются как светлыми, так и темными. Это положительная и отрицательная активация, соответственно. Однако используются только положительные активации из-за выпрямленного линейного модуля (ReLU), который следует за fire6-squeeze1x1 слой. Чтобы исследовать только положительные активации, повторите анализ, чтобы визуализировать активации fire6-relu_squeeze1x1 слой.

act6relu = activations(net,im,'fire6-relu_squeeze1x1');
sz = size(act6relu);
act6relu = reshape(act6relu,[sz(1) sz(2) 1 sz(3)]);

I = imtile(imresize(mat2gray(act6relu(:,:,:,[14 47])),imgSize));
imshow(I)

По сравнению с активациями fire6-squeeze1x1 слой, активации fire6-relu_squeeze1x1 слой четко выявляет области изображения, которые имеют сильные лицевые функции.

Тест, распознает ли канал глаза

Проверяйте, являются ли каналы 14 и 47 fire6-relu_squeeze1x1 активизируется слой на глазах. Введите новое изображение с одним закрытым глазом в сеть и сравните получившиеся активации с активациями оригинального изображения.

Прочтите и покажите изображение одним закрытым глазом и вычислите активации fire6-relu_squeeze1x1 слой.

imClosed = imread('face-eye-closed.jpg');
imshow(imClosed)

act6Closed = activations(net,imClosed,'fire6-relu_squeeze1x1');
sz = size(act6Closed);
act6Closed = reshape(act6Closed,[sz(1),sz(2),1,sz(3)]);

Постройте график изображений и активаций на одном рисунке.

channelsClosed = repmat(imresize(mat2gray(act6Closed(:,:,:,[14 47])),imgSize),[1 1 3]);
channelsOpen = repmat(imresize(mat2gray(act6relu(:,:,:,[14 47])),imgSize),[1 1 3]);
I = imtile(cat(4,im,channelsOpen*255,imClosed,channelsClosed*255));
imshow(I)
title('Input Image, Channel 14, Channel 47');

По активациям видно, что оба канала 14 и 47 активируются на отдельных глазах, а в некоторой степени и на участке вокруг рта.

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

См. также

| |

Похожие темы