tsneВ этом примере показано, как использовать tsne функция для просмотра активизаций в обученной сети. Это представление поможет понять, как работает сеть.
tsne Функция (Statistics and Machine Learning Toolbox) в Statistics and Machine Learning Toolbox™ реализует t-распределенное стохастическое встраивание соседей (t-SNE) [1]. Этот метод сопоставляет высокоразмерные данные (например, активации сети в слое) двум измерениям. Метод использует нелинейную карту, которая пытается сохранить расстояния. Используя t-SNE для визуализации активизаций сети, можно получить представление о реакции сети.
Можно использовать t-SNE для визуализации того, как сети глубокого обучения изменяют представление входных данных при их прохождении через сетевые уровни. Можно также использовать t-SNE для поиска проблем с входными данными и определения того, какие наблюдения в сети классифицируются неправильно.
Например, t-SNE может уменьшить многомерные активации слоя softmax до 2-D представления с подобной структурой. Жесткие кластеры на результирующем графике t-SNE соответствуют классам, которые сеть обычно правильно классифицирует. Визуализация позволяет находить точки, появляющиеся не в том кластере, указывая на наблюдение, которое сеть классифицирует неправильно. Наблюдение может быть помечено неправильно, или сеть может предсказать, что наблюдение является экземпляром другого класса, поскольку оно похоже на другие наблюдения из этого класса. Следует отметить, что при уменьшении t-SNE активаций softmax используются только эти активации, а не основные наблюдения.
В этом примере используется набор данных Example Food Images, который содержит 978 фотографий продуктов питания девяти классов и имеет размер приблизительно 77 МБ. Загрузите набор данных во временный каталог, вызвав downloadExampleFoodImagesData функция помощника; код для этой вспомогательной функции появляется в конце этого примера.
dataDir = fullfile(tempdir, "ExampleFoodImageDataset"); url = "https://www.mathworks.com/supportfiles/nnet/data/ExampleFoodImageDataset.zip"; if ~exist(dataDir, "dir") mkdir(dataDir); end downloadExampleFoodImagesData(url,dataDir);
Downloading MathWorks Example Food Image dataset... This can take several minutes to download... Download finished... Unzipping file... Unzipping finished... Done.
Измените предварительно обученную сеть SqueeEjNet для классификации изображений продуктов питания из набора данных. Замените конечный сверточный слой, имеющий 1000 фильтров для 1000 классов ImageNet, на новый сверточный слой, имеющий только девять фильтров. Каждый фильтр соответствует одному типу пищи.
lgraph = layerGraph(squeezenet()); lgraph = lgraph.replaceLayer("ClassificationLayer_predictions",... classificationLayer("Name", "ClassificationLayer_predictions")); newConv = convolution2dLayer([14 14], 9, "Name", "conv", "Padding", "same"); lgraph = lgraph.replaceLayer("conv10", newConv);
Создание imageDatastore содержит пути к данным изображения. Разбейте хранилище данных на наборы обучения и проверки, используя 65% данных для обучения и остальные для проверки. Поскольку набор данных довольно мал, переоборудование является серьезной проблемой. Чтобы минимизировать переоборудование, дополните обучающий набор случайными откидками и масштабированием.
imds = imageDatastore(dataDir, ... "IncludeSubfolders", true, "LabelSource", "foldernames"); aug = imageDataAugmenter("RandXReflection", true, ... "RandYReflection", true, ... "RandXScale", [0.8 1.2], ... "RandYScale", [0.8 1.2]); trainingFraction = 0.65; [trainImds,valImds] = splitEachLabel(imds, trainingFraction); augImdsTrain = augmentedImageDatastore([227 227], trainImds, ... 'DataAugmentation', aug); augImdsVal = augmentedImageDatastore([227 227], valImds);
Создайте варианты обучения и обучите сеть. SqueeeNet - это небольшая сеть, которая быстро тренируется. Вы можете обучаться на GPU или CPU; в этом примере выполняется обучение на CPU.
opts = trainingOptions("adam", ... "InitialLearnRate", 1e-4, ... "MaxEpochs", 30, ... "ValidationData", augImdsVal, ... "Verbose", false,... "Plots", "training-progress", ... "ExecutionEnvironment","cpu",... "MiniBatchSize",128); rng default net = trainNetwork(augImdsTrain, lgraph, opts);

Используйте сеть для классификации изображений в наборе проверки. Чтобы убедиться, что сеть достаточно точна при классификации новых данных, постройте график матрицы путаницы истинных и прогнозируемых меток.
figure(); YPred = classify(net,augImdsVal); confusionchart(valImds.Labels,YPred,'ColumnSummary',"column-normalized")

Сеть хорошо классифицирует несколько образов. В сети, похоже, есть проблемы с изображениями суши, классифицируя многих как суши, но некоторые как пицца или гамбургер. Сеть не классифицирует изображения в класс хот-догов.
Чтобы продолжить анализ производительности сети, вычислите активизации для каждого наблюдения в наборе данных на уровне раннего максимального объединения, конечном сверточном уровне и конечном уровне softmax. Выведите активации в виде матрицы NxM, где N - количество наблюдений, а M - количество измерений активации. М - произведение пространственных и канальных размеров. Каждая строка представляет собой наблюдение, а каждый столбец - измерение. На уровне softmax М = 9, поскольку набор данных питания имеет девять классов. Каждая строка в матрице содержит девять элементов, соответствующих вероятностям того, что наблюдение принадлежит каждому из девяти классов пищи.
earlyLayerName = "pool1"; finalConvLayerName = "conv"; softmaxLayerName = "prob"; pool1Activations = activations(net,... augImdsVal,earlyLayerName,"OutputAs","rows"); finalConvActivations = activations(net,... augImdsVal,finalConvLayerName,"OutputAs","rows"); softmaxActivations = activations(net,... augImdsVal,softmaxLayerName,"OutputAs","rows");
Для вычисления наиболее вероятных неправильных классификаций изображений можно использовать активации softmax. Определите неоднозначность классификации как отношение второй наибольшей вероятности к наибольшей вероятности. Неоднозначность классификации находится между нулем (почти определенная классификация) и 1 (почти так же вероятно классифицируется для наиболее вероятного класса, как и для второго класса). Неоднозначность около 1 означает, что сеть не уверена в классе, в котором принадлежит конкретное изображение. Эта неопределенность может быть вызвана двумя классами, наблюдения которых выглядят настолько похожими на сеть, что они не могут узнать различия между ними. Или может возникнуть высокая неоднозначность, поскольку конкретное наблюдение содержит элементы более одного класса, поэтому сеть не может решить, какая классификация верна. Следует отметить, что низкая неоднозначность необязательно подразумевает правильную классификацию; даже если сеть имеет высокую вероятность для класса, классификация все равно может быть неправильной.
[R,RI] = maxk(softmaxActivations,2,2); ambiguity = R(:,2)./R(:,1);
Найдите наиболее неоднозначные изображения.
[ambiguity,ambiguityIdx] = sort(ambiguity,"descend");Просмотр наиболее вероятных классов неоднозначных изображений и истинных классов.
classList = unique(valImds.Labels); top10Idx = ambiguityIdx(1:10); top10Ambiguity = ambiguity(1:10); mostLikely = classList(RI(ambiguityIdx,1)); secondLikely = classList(RI(ambiguityIdx,2)); table(top10Idx,top10Ambiguity,mostLikely(1:10),secondLikely(1:10),valImds.Labels(ambiguityIdx(1:10)),... 'VariableNames',["Image #","Ambiguity","Likeliest","Second","True Class"])
ans=10×5 table
Image # Ambiguity Likeliest Second True Class
_______ _________ _________ ____________ ____________
94 0.9879 hamburger pizza hamburger
175 0.96311 hamburger french_fries hot_dog
179 0.94939 pizza hamburger hot_dog
337 0.93426 sushi sashimi sushi
256 0.92972 sushi pizza pizza
297 0.91776 sushi sashimi sashimi
283 0.80407 pizza sushi pizza
27 0.80278 hamburger pizza french_fries
302 0.79283 sashimi sushi sushi
201 0.76034 pizza greek_salad pizza
Сеть предсказывает, что изображение 27, скорее всего, является гамбургером или пиццей. Однако это изображение на самом деле картофеля фри. Просмотрите изображение, чтобы узнать, почему произошла ошибка классификации.
v = 27;
figure();
imshow(valImds.Files{v});
title(sprintf("Observation: %i\n" + ...
"Actual: %s. Predicted: %s", v, ...
string(valImds.Labels(v)), string(YPred(v))), ...
'Interpreter', 'none');
Изображение содержит несколько различных областей, некоторые из которых могут запутать сеть.
Вычислите низкоразмерное представление сетевых данных для уровня раннего максимального объединения, конечного сверточного уровня и конечного уровня softmax. Используйте tsne функция для уменьшения размерности данных активации от М до 2. Чем больше размерность активизаций, тем дольше занимает вычисление t-SNE. Поэтому вычисление для уровня раннего максимального объединения, где активизации имеют 200 704 размера, занимает больше времени, чем для конечного уровня softmax. Задайте случайное начальное число для воспроизводимости результата t-SNE.
rng default
pool1tsne = tsne(pool1Activations);
finalConvtsne = tsne(finalConvActivations);
softmaxtsne = tsne(softmaxActivations);Метод t-SNE пытается сохранить расстояния, так что точки вблизи друг друга в высокомерном представлении также находятся вблизи друг друга в низкомерном представлении. Как показано в матрице путаницы, сеть эффективна при классификации по различным классам. Поэтому изображения, которые семантически похожи (или одного типа), такие как салат цезаря и салат капрезе, находятся рядом друг с другом в пространстве активации softmax. t-SNE фиксирует эту близость в 2-D представлении, которое легче понять и построить график, чем девятимерные оценки softmax.
Ранние слои имеют тенденцию работать с низкоуровневыми элементами, такими как кромки и цвета. Более глубокие слои научились высокоуровневым особенностям с более семантическим значением, таким как разница между пиццей и хот-догом. Поэтому активации с ранних слоев не показывают никакой кластеризации по классам. Два изображения, которые схожи по пикселям (например, они оба содержат много зелёных пикселей), находятся рядом друг с другом в высокомерном пространстве активаций, независимо от их семантического содержания. Активации из более поздних слоев имеют тенденцию объединять точки из одного класса. Такое поведение наиболее ярко проявляется на уровне softmax и сохраняется в двумерном представлении t-SNE.
Постройте график данных t-SNE для уровня раннего максимального объединения, конечного сверточного уровня и конечного уровня softmax с помощью gscatter функция. Обратите внимание на то, что при ранних активациях максимального пула не происходит кластеризации между изображениями одного класса. Активации конечного сверточного слоя кластеризованы по классам в некоторой степени, но в меньшей степени, чем активации softmax. Разным цветам соответствуют наблюдения разных классов.
doLegend = 'off'; markerSize = 7; figure; subplot(1,3,1); gscatter(pool1tsne(:,1),pool1tsne(:,2),valImds.Labels, ... [],'.',markerSize,doLegend); title("Max pooling activations"); subplot(1,3,2); gscatter(finalConvtsne(:,1),finalConvtsne(:,2),valImds.Labels, ... [],'.',markerSize,doLegend); title("Final conv activations"); subplot(1,3,3); gscatter(softmaxtsne(:,1),softmaxtsne(:,2),valImds.Labels, ... [],'.',markerSize,doLegend); title("Softmax activations");

Создайте больший график активизаций softmax, включая условные обозначения каждого класса. Из графика t-SNE можно понять больше о структуре апостериорного распределения вероятностей.
Например, сюжет показывает отчетливый, отдельный кластер наблюдений картофеля фри, тогда как кластеры сашими и суши не очень хорошо разрешены. Подобно матрице путаницы, сюжет предполагает, что сеть более точна при прогнозировании в класс картофеля фри.
numClasses = length(classList); colors = lines(numClasses); h = figure; gscatter(softmaxtsne(:,1),softmaxtsne(:,2),valImds.Labels,colors); l = legend; l.Interpreter = "none"; l.Location = "bestoutside";

Можно также использовать t-SNE для определения того, какие изображения неправильно классифицируются сетью и почему. Неправильные наблюдения часто являются изолированными точками неправильного цвета для их окружающего кластера. Например, неправильно классифицированное изображение гамбургера находится совсем рядом с регионом картофеля фри (зеленая точка, ближайшая к центру апельсинового скопления). Эта точка - наблюдение 99. Окружить это наблюдение на графике t-SNE и отобразить изображение с помощью imshow.
obs =99; figure(h) hold on; hs = scatter(softmaxtsne(obs, 1), softmaxtsne(obs, 2), ... 'black','LineWidth',1.5); l.String{end} = 'Hamburger'; hold off; figure(); imshow(valImds.Files{obs}); title(sprintf("Observation: %i\n" + ... "Actual: %s. Predicted: %s", obs, ... string(valImds.Labels(obs)), string(YPred(obs))), ... 'Interpreter', 'none');

Если изображение содержит несколько видов еды, сеть может запутаться. В этом случае сеть классифицирует изображение как картофель фри, даже если пища на переднем плане - гамбургер. Картошка фри, видимая на краю изображения, вызывает путаницу.
Аналогично, неоднозначное изображение 27 (показанное ранее в примере) имеет множество областей. Изучите график t-SNE, выделяющий неоднозначный аспект этого изображения картофеля фри.
obs =27; figure(h) hold on; h = scatter(softmaxtsne(obs, 1), softmaxtsne(obs, 2), ... 'k','d','LineWidth',1.5); l.String{end} = 'French Fries'; hold off;

Изображение не находится в хорошо определенном кластере на графике, что указывает на то, что классификация, вероятно, неверна. Изображение находится далеко от кластера картофеля фри, и близко к кластеру гамбургера.
Причина неправильной классификации должна быть предоставлена другой информацией, обычно гипотезой, основанной на содержании изображения. Затем можно проверить гипотезу с помощью других данных или с помощью инструментов, указывающих, какие пространственные области изображения важны для классификации сети. Примеры см. в разделе occlusionSensitivity и Grad-CAM раскрывает причины, лежащие в основе решений о глубоком обучении.
[1] ван дер Маатен, Лоренс и Джеффри Хинтон. «Визуализация данных с помощью t-SNE». Журнал исследований машинного обучения 9, 2008, стр. 2579-2605.
function downloadExampleFoodImagesData(url, dataDir) % Download the Example Food Image data set, containing 978 images of % different types of food split into 9 classes. % Copyright 2019 The MathWorks, Inc. fileName = "ExampleFoodImageDataset.zip"; fileFullPath = fullfile(dataDir, fileName); % Download the .zip file into a temporary directory. if ~exist(fileFullPath, "file") fprintf("Downloading MathWorks Example Food Image dataset...\n"); fprintf("This can take several minutes to download...\n"); websave(fileFullPath, url); fprintf("Download finished...\n"); else fprintf("Skipping download, file already exists...\n"); end % Unzip the file. % % Check if the file has already been unzipped by checking for the presence % of one of the class directories. exampleFolderFullPath = fullfile(dataDir, "pizza"); if ~exist(exampleFolderFullPath, "dir") fprintf("Unzipping file...\n"); unzip(fileFullPath, dataDir); fprintf("Unzipping finished...\n"); else fprintf("Skipping unzipping, file already unzipped...\n"); end fprintf("Done.\n"); end
activations | classify | layerGraph | occlusionSensitivity | squeezenet | trainingOptions | trainNetwork | tsne (инструментарий статистики и машинного обучения)