Задайте пользовательский слой классификации пикселей с потерями Тверского

В этом примере показано, как определить и создать пользовательский слой классификации пикселей, который использует потери Тверского.

Этот слой может использоваться для обучения сетей семантической сегментации. Дополнительные сведения о создании пользовательских слоев глубокого обучения см. в разделе «Определение пользовательских слоев глубокого обучения» (Deep Learning Toolbox).

Тверская потеря

Тверская потеря основана на индексе Тверского для измерения перекрытия между двумя сегментированными изображениями [1]. Индекс Тверского TIc между одним изображением Y и соответствующая основная истина T дается

TIc=m=1MYcmTcmm=1MYcmTcm+αm=1MYcmTcm+βm=1MYcmTcm

  • c соответствует классу и cсоответствует отсутствию в классе c.

  • M количество элементов по первым двум размерностям Y.

  • α и β являются весовыми факторами, которые контролируют вклад, который ложные срабатывания и ложные срабатывания для каждого класса вносят в потерю.

Потеря Lпо количеству классов C дается

L=c=1C1-TIc

Шаблон классификационного слоя

Скопируйте шаблон слоя классификации в новый файл в MATLAB ®. Этот шаблон описывает структуру слоя классификации и включает функции, которые определяют поведение слоя. В остальном примере показано, как выполнить tverskyPixelClassificationLayer.

classdef tverskyPixelClassificationLayer < nnet.layer.ClassificationLayer

   properties
      % Optional properties
   end

   methods

        function loss = forwardLoss(layer, Y, T)
            % Layer forward loss function goes here
        end
        
    end
end

Объявление свойств слоя

По умолчанию пользовательские выходные слои имеют следующие свойства:

  • Name - Имя слоя, заданное как вектор символов или строковый скаляр. Чтобы включить этот слой в график слоев, необходимо задать непустое уникальное имя слоя. Если вы обучаете последовательную сеть с этим слоем и Name установлено в ''затем программа автоматически присваивает имя во время обучения.

  • Description - Однострочное описание слоя, заданное как вектор символов или строковый скаляр. Это описание появляется, когда слой отображается в Layer массив. Если вы не задаете описание слоя, то программа отображает имя класса слоя.

  • Type - Тип слоя, заданный как вектор символов или строковый скаляр. Значение Type появляется, когда слой отображается в Layer массив. Если тип слоя не задан, отобразится программное обеспечение 'Classification layer' или 'Regression layer'.

Пользовательские слои классификации также имеют следующее свойство:

  • Classes - Классы выходного слоя, заданные как категориальный вектор, строковые массивы, массив ячеек из векторов символов или 'auto'. Если Classes является 'auto', затем программное обеспечение автоматически устанавливает классы во время обучения. Если вы задаете строковые массивы или массив ячеек векторов символов str, затем программное обеспечение устанавливает классы выходного слоя на categorical(str,str). Значение по умолчанию 'auto'.

Если слой не имеет других свойств, можно опустить properties раздел.

Тверская потеря требует небольшого постоянного значения, чтобы предотвратить деление на нули. Задайте свойство, Epsilon, чтобы удержать это значение. Это также требует двух свойств переменной A lpha и Beta которые контролируют взвешивание ложных срабатываний и ложных срабатываний, соответственно.

classdef tverskyPixelClassificationLayer < nnet.layer.ClassificationLayer

    properties(Constant)
       % Small constant to prevent division by zero. 
       Epsilon = 1e-8;
    end

    properties
       % Default weighting coefficients for false positives and false negatives 
       Alpha = 0.5;
       Beta = 0.5;  
    end

    ...
end

Создайте функцию конструктора

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

Задайте необязательное имя входного параметра для присвоения Name свойство при создании.

function layer = tverskyPixelClassificationLayer(name, alpha, beta)
    % layer =  tverskyPixelClassificationLayer(name) creates a Tversky
    % pixel classification layer with the specified name.
           
    % Set layer name          
    layer.Name = name;

    % Set layer properties
    layer.Alpha = alpha;
    layer.Beta = beta;

    % Set layer description
    layer.Description = 'Tversky loss';
end

Создайте функцию Forward Loss

Создайте функцию с именем forwardLoss это возвращает взвешенные потери перекрестной энтропии между предсказаниями, сделанными сетью, и целями обучения. Синтаксис для forwardLoss является loss = forwardLoss(layer,Y,T), где Y - выход предыдущего слоя и T представляет цели обучения.

Для семантических задач сегментации, размерности T соответствовать размерности Y, где Y - 4-D массив размера H-by- W-by- K-by- N, где K количество классов и N - размер мини-пакета.

Размер Y зависит от выхода предыдущего слоя. Чтобы гарантировать, что Y - тот же размер, что и Tнеобходимо включить слой, который выводит правильный размер перед слоем выхода. Для примера, чтобы гарантировать, что Y является 4-D массивом счетов предсказания для K классы, можно включать полносвязный слой размера K или сверточный слой с K фильтры, за которыми следует слой softmax перед слоем выхода.

function loss = forwardLoss(layer, Y, T)
    % loss = forwardLoss(layer, Y, T) returns the Tversky loss between
    % the predictions Y and the training targets T.

    Pcnot = 1-Y;
    Gcnot = 1-T;
    TP = sum(sum(Y.*T,1),2);
    FP = sum(sum(Y.*Gcnot,1),2);
    FN = sum(sum(Pcnot.*T,1),2);

    numer = TP + layer.Epsilon;
    denom = TP + layer.Alpha*FP + layer.Beta*FN + layer.Epsilon;
    
    % Compute Tversky index
    lossTIc = 1 - numer./denom;
    lossTI = sum(lossTIc,3);
    
    % Return average Tversky index loss
    N = size(Y,4);
    loss = sum(lossTI)/N;

end

Функция обратных потерь

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

Список функций, поддерживающих автоматическую дифференциацию, см. в Списке функций с поддержкой dlarray (Deep Learning Toolbox).

Завершенный слой

Завершенный слой обеспечен в tverskyPixelClassificationLayer.m.

classdef tverskyPixelClassificationLayer < nnet.layer.ClassificationLayer
    % This layer implements the Tversky loss function for training
    % semantic segmentation networks.
    
    % References
    % Salehi, Seyed Sadegh Mohseni, Deniz Erdogmus, and Ali Gholipour.
    % "Tversky loss function for image segmentation using 3D fully
    % convolutional deep networks." International Workshop on Machine
    % Learning in Medical Imaging. Springer, Cham, 2017.
    % ----------
    
    
    properties(Constant)
        % Small constant to prevent division by zero.
        Epsilon = 1e-8;
    end
    
    properties
        % Default weighting coefficients for False Positives and False
        % Negatives
        Alpha = 0.5;
        Beta = 0.5;
    end

    
    methods
        
        function layer = tverskyPixelClassificationLayer(name, alpha, beta)
            % layer =  tverskyPixelClassificationLayer(name, alpha, beta) creates a Tversky
            % pixel classification layer with the specified name and properties alpha and beta.
            
            % Set layer name.          
            layer.Name = name;
            
            layer.Alpha = alpha;
            layer.Beta = beta;
            
            % Set layer description.
            layer.Description = 'Tversky loss';
        end
        
        
        function loss = forwardLoss(layer, Y, T)
            % loss = forwardLoss(layer, Y, T) returns the Tversky loss between
            % the predictions Y and the training targets T.   

            Pcnot = 1-Y;
            Gcnot = 1-T;
            TP = sum(sum(Y.*T,1),2);
            FP = sum(sum(Y.*Gcnot,1),2);
            FN = sum(sum(Pcnot.*T,1),2); 
            
            numer = TP + layer.Epsilon;
            denom = TP + layer.Alpha*FP + layer.Beta*FN + layer.Epsilon;
            
            % Compute tversky index
            lossTIc = 1 - numer./denom;
            lossTI = sum(lossTIc,3);
            
            % Return average tversky index loss.
            N = size(Y,4);
            loss = sum(lossTI)/N;
            
        end     
    end
end

Совместимость с GPU

Функции MATLAB, используемые в forwardLoss в tverskyPixelClassificationLayer все gpuArray поддержки вводит, поэтому слой совместим с графическим процессором.

Проверяйте валидность выходного слоя

Создайте образец слоя.

layer = tverskyPixelClassificationLayer('tversky',0.7,0.3);

Проверьте валидность слоя при помощи checkLayer (Deep Learning Toolbox). Задайте допустимый размер входного сигнала, чтобы быть размером одного наблюдения типового входа для слоя. Слой ожидает H-by- W-by- K-by- N входы массива, где K количество классов и N количество наблюдений в мини-пакете.

numClasses = 2;
validInputSize = [4 4 numClasses];
checkLayer(layer,validInputSize, 'ObservationDimension',4)
Skipping GPU tests. No compatible GPU device found.
 
Skipping code generation compatibility tests. To check validity of the layer for code generation, specify the 'CheckCodegenCompatibility' and 'ObservationDimension' options.
 
Running nnet.checklayer.TestOutputLayerWithoutBackward
........
Done nnet.checklayer.TestOutputLayerWithoutBackward
__________

Test Summary:
	 8 Passed, 0 Failed, 0 Incomplete, 2 Skipped.
	 Time elapsed: 1.083 seconds.

В сводных данных тестов указывается количество пройденных, неудачных, неполных и пропущенных тестов.

Использование пользовательского слоя в семантической сети сегментации

Создайте семантическую сеть сегментации, которая использует tverskyPixelClassificationLayer.

layers = [
    imageInputLayer([32 32 1])
    convolution2dLayer(3,64,'Padding',1)
    batchNormalizationLayer
    reluLayer
    maxPooling2dLayer(2,'Stride',2)
    convolution2dLayer(3,64,'Padding',1)
    reluLayer
    transposedConv2dLayer(4,64,'Stride',2,'Cropping',1)
    convolution2dLayer(1,2)
    softmaxLayer
    tverskyPixelClassificationLayer('tversky',0.3,0.7)]
layers = 
  11x1 Layer array with layers:

     1   ''          Image Input              32x32x1 images with 'zerocenter' normalization
     2   ''          Convolution              64 3x3 convolutions with stride [1  1] and padding [1  1  1  1]
     3   ''          Batch Normalization      Batch normalization
     4   ''          ReLU                     ReLU
     5   ''          Max Pooling              2x2 max pooling with stride [2  2] and padding [0  0  0  0]
     6   ''          Convolution              64 3x3 convolutions with stride [1  1] and padding [1  1  1  1]
     7   ''          ReLU                     ReLU
     8   ''          Transposed Convolution   64 4x4 transposed convolutions with stride [2  2] and cropping [1  1  1  1]
     9   ''          Convolution              2 1x1 convolutions with stride [1  1] and padding [0  0  0  0]
    10   ''          Softmax                  softmax
    11   'tversky'   Classification Output    Tversky loss

Загрузите обучающие данные для семантической сегментации с помощью imageDatastore и pixelLabelDatastore.

dataSetDir = fullfile(toolboxdir('vision'),'visiondata','triangleImages');
imageDir = fullfile(dataSetDir,'trainingImages');
labelDir = fullfile(dataSetDir,'trainingLabels');

imds = imageDatastore(imageDir);

classNames = ["triangle" "background"];
labelIDs = [255 0];
pxds = pixelLabelDatastore(labelDir, classNames, labelIDs);

Связать изображение и данные о пиксельных метках можно используя pixelLabelImageDatastore.

ds = pixelLabelImageDatastore(imds,pxds);

Установите опции обучения и обучите сеть.

options = trainingOptions('adam', ...
    'InitialLearnRate',1e-3, ...
    'MaxEpochs',100, ...
    'LearnRateDropFactor',5e-1, ...
    'LearnRateDropPeriod',20, ...
    'LearnRateSchedule','piecewise', ...
    'MiniBatchSize',50);

net = trainNetwork(ds,layers,options);
Training on single CPU.
Initializing input data normalization.
|========================================================================================|
|  Epoch  |  Iteration  |  Time Elapsed  |  Mini-batch  |  Mini-batch  |  Base Learning  |
|         |             |   (hh:mm:ss)   |   Accuracy   |     Loss     |      Rate       |
|========================================================================================|
|       1 |           1 |       00:00:00 |       50.32% |       1.2933 |          0.0010 |
|      13 |          50 |       00:00:08 |       98.83% |       0.0988 |          0.0010 |
|      25 |         100 |       00:00:15 |       99.33% |       0.0547 |          0.0005 |
|      38 |         150 |       00:00:21 |       99.37% |       0.0473 |          0.0005 |
|      50 |         200 |       00:00:28 |       99.48% |       0.0400 |          0.0003 |
|      63 |         250 |       00:00:36 |       99.48% |       0.0383 |          0.0001 |
|      75 |         300 |       00:00:43 |       99.54% |       0.0348 |          0.0001 |
|      88 |         350 |       00:00:50 |       99.51% |       0.0353 |      6.2500e-05 |
|     100 |         400 |       00:00:57 |       99.56% |       0.0331 |      6.2500e-05 |
|========================================================================================|

Оцените обученную сеть, сегментировав тестовое изображение и отобразив результат сегментации.

I = imread('triangleTest.jpg');
[C,scores] = semanticseg(I,net);

B = labeloverlay(I,C);
montage({I,B})

Figure contains an axes. The axes contains an object of type image.

Ссылки

[1] Салехи, Сейед Садег Мохсени, Дениз Эрдогмус и Али Голипур. «Функция потерь Тверского для сегментации изображений 3D используя полностью сверточные глубокие сети». Международный семинар по машинному обучению в медицинской визуализации. Спрингер, Чэм, 2017.

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