Исследуйте сетевые предсказания, используя отображение активации классов

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

Нейронные сети для глубокого обучения часто считаются «черными ящиками», которые не предлагают никакого способа выяснить, чему научилась сеть или какая часть входа сети отвечала за предсказание сети. Когда эти модели терпят неудачу и дают неправильные предсказания, они часто эффектно проваливаются без каких-либо предупреждений или объяснений. Сопоставление активации классов [1] является одним из методов, который можно использовать, чтобы получить визуальные объяснения предсказаний сверточных нейронных сетей. Неправильные , казалось бы , необоснованные предсказания могут часто иметь разумные объяснения. Используя отображение активации класса, можно проверить, «спутала» ли сеть определенная часть входа изображения и привела ее к неправильному предсказанию.

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

Эта карта активации примера класса показов, какие области входа изображения вносят наибольший вклад в предсказанный класс mouse. Красные области вносят наибольший вклад.

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

Загрузите предварительно обученную сверточную нейронную сеть для классификации изображений. SqueezeNet, GoogLeNet, ResNet-18 и MobileNet-v2 являются относительно быстрыми сетями. SqueezeNet является самой быстрой сетью, и его карта активации класса имеет в четыре раза более высокое разрешение, чем карты других сетей. Вы не можете использовать отображение активации классов с сетями, которые имеют несколько полносвязных слоев в конце сети, таких как AlexNet, VGG-16 и VGG-19.

netName = "squeezenet";
net = eval (netName);

Создайте webcam объект и подключение к веб-камере.

camera = webcam;

Извлеките изображение входа размера и выхода классов сети. The activationLayerName helper function, заданная в конце этого примера, возвращает имя слоя, из которого будут извлечены активации. Этот слой является слоем ReLU, который следует за последним сверточным слоем сети.

inputSize = net.Layers(1).InputSize(1:2);
classes = net.Layers(end).Classes;
layerName = activationLayerName(netName);

Отобразите карты активации классов

Создайте рисунок и выполните отображение активации класса в цикле. Чтобы завершить выполнение цикла, закройте рисунок.

h = figure('Units','normalized','Position',[0.05 0.05 0.9 0.8],'Visible','on');

while ishandle(h)

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

Вычислите активации измененного размера изображения на слое ReLU, который следует за последним сверточным слоем сети.

    im = snapshot(camera);
    imResized = imresize(im,[inputSize(1), NaN]);
    imageActivations = activations(net,imResized,layerName);

Карта активации классов для определенного класса является картой активации слоя ReLU, которая следует за конечным сверточным слоем, взвешенной на то, сколько каждая активация способствует окончательному счету этого класса. Эти веса равны весам конечного полносвязного слоя сети для этого класса. SqueezeNet не имеет последнего полносвязного слоя. Вместо этого выход слоя ReLU, который следует за последним сверточным слоем, уже является картой активации класса.

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

    scores = squeeze(mean(imageActivations,[1 2]));
    
    if netName ~= "squeezenet"
        fcWeights = net.Layers(end-2).Weights;
        fcBias = net.Layers(end-2).Bias;
        scores =  fcWeights*scores + fcBias;
        
        [~,classIds] = maxk(scores,3);
        
        weightVector = shiftdim(fcWeights(classIds(1),:),-1);
        classActivationMap = sum(imageActivations.*weightVector,3);
    else
        [~,classIds] = maxk(scores,3);
        classActivationMap = imageActivations(:,:,classIds(1));
    end
    

Вычислите метки верхнего класса и окончательные нормированные счета классов.

    scores = exp(scores)/sum(exp(scores));     
    maxScores = scores(classIds);
    labels = classes(classIds);

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

    subplot(1,2,1)
    imshow(im)
    
    subplot(1,2,2)
    CAMshow(im,classActivationMap)
    title(string(labels) + ", " + string(maxScores));
    
    drawnow
    
end

Очистить объект веб-камеры.

clear camera

Карты примеров

Сеть правильно идентифицирует объект в этом изображении как лоффер (тип обуви). Карта активации классов на изображении справа показывает вклад каждой области входного изображения в предсказанный класс Loafer. Красные области вносят наибольший вклад. Сеть основывает свою классификацию на всей обуви, но самый сильный вход исходит от красных областей - то есть совета и открытия обуви.

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

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

Вспомогательные функции

CAMshow(im,CAM) накладывает карту активации классов CAM на затемненной, полутоновой версии изображения im. Функция изменяет размер карты активации класса на размер im, нормализует его, порождает его снизу и визуализирует его с помощью jet палитра.

function CAMshow(im,CAM)
imSize = size(im);
CAM = imresize(CAM,imSize(1:2));
CAM = normalizeImage(CAM);
CAM(CAM<0.2) = 0;
cmap = jet(255).*linspace(0,1,255)';
CAM = ind2rgb(uint8(CAM*255),cmap)*255;

combinedImage = double(rgb2gray(im))/2 + CAM;
combinedImage = normalizeImage(combinedImage)*255;
imshow(uint8(combinedImage));
end

function N = normalizeImage(I)
minimum = min(I(:));
maximum = max(I(:));
N = (I-minimum)/(maximum-minimum);
end

function layerName = activationLayerName(netName)

if netName == "squeezenet"
    layerName = 'relu_conv10';
elseif netName == "googlenet"
    layerName = 'inception_5b-output';
elseif netName == "resnet18"
    layerName = 'res5b_relu';
elseif netName == "mobilenetv2"
    layerName = 'out_relu';
end

end

Ссылки

[1] Чжоу, Болей, Адитья Хосла, Агата Лапедриза, Оде Олива, и Антонио Торральба. «Изучение глубоких особенностей для дискриминационной локализации». В работе Конференции IEEE по компьютерному зрению и распознаванию шаблона, стр. 2921-2929. 2016.

См. также

| | | |

Похожие темы

Для просмотра документации необходимо авторизоваться на сайте