- "trueLabels" contains the actual output data for each sample ranging from 1 to 5.
- TPR and FPR are calculated for a set of thresholds to get the ROC curve.
- ROC curve for each class is plotted separately.
How to generate ROC curve for multiclass semantic segmentation of biological tissue
9 views (last 30 days)
Show older comments
How would I obtain ROC curve based on https://www.mathworks.com/help/vision/ref/semanticseg.html?s_tid=d ?
My code looks something like this:
inputSize = [24 32 3];
imgLayer = imageInputLayer(inputSize)
filterSize = 3;
numFilters = 32;
conv = convolution2dLayer(filterSize,numFilters,'Padding',1);
relu = reluLayer();
poolSize = 2;
maxPoolDownsample2x = maxPooling2dLayer(poolSize,'Stride',2);
downsamplingLayers = [
conv
relu
maxPoolDownsample2x
conv
relu
maxPoolDownsample2x
]
filterSize = 4;
transposedConvUpsample2x = transposedConv2dLayer(4,numFilters,'Stride',2,'Cropping',1);
upsamplingLayers = [
transposedConvUpsample2x
relu
transposedConvUpsample2x
relu
]
numClasses = 5;
conv1x1 = convolution2dLayer(1,numClasses);
finalLayers = [
conv1x1
softmaxLayer()
pixelClassificationLayer()
]
net = [
imgLayer
downsamplingLayers
upsamplingLayers
finalLayers
]
imgLayer =
ImageInputLayer with properties:
Name: ''
InputSize: [24 32 3]
Hyperparameters
DataAugmentation: 'none'
Normalization: 'zerocenter'
NormalizationDimension: 'auto'
Mean: []
downsamplingLayers =
6×1 Layer array with layers:
1 '' Convolution 32 3×3 convolutions with stride [1 1] and padding [1 1 1 1]
2 '' ReLU ReLU
3 '' Max Pooling 2×2 max pooling with stride [2 2] and padding [0 0 0 0]
4 '' Convolution 32 3×3 convolutions with stride [1 1] and padding [1 1 1 1]
5 '' ReLU ReLU
6 '' Max Pooling 2×2 max pooling with stride [2 2] and padding [0 0 0 0]
upsamplingLayers =
4×1 Layer array with layers:
1 '' Transposed Convolution 32 4×4 transposed convolutions with stride [2 2] and cropping [1 1 1 1]
2 '' ReLU ReLU
3 '' Transposed Convolution 32 4×4 transposed convolutions with stride [2 2] and cropping [1 1 1 1]
4 '' ReLU ReLU
finalLayers =
3×1 Layer array with layers:
1 '' Convolution 5 1×1 convolutions with stride [1 1] and padding [0 0 0 0]
2 '' Softmax softmax
3 '' Pixel Classification Layer Cross-entropy loss
net =
14×1 Layer array with layers:
1 '' Image Input 24×32×3 images with 'zerocenter' normalization
2 '' Convolution 32 3×3 convolutions with stride [1 1] and padding [1 1 1 1]
3 '' ReLU ReLU
4 '' Max Pooling 2×2 max pooling with stride [2 2] and padding [0 0 0 0]
5 '' Convolution 32 3×3 convolutions with stride [1 1] and padding [1 1 1 1]
6 '' ReLU ReLU
7 '' Max Pooling 2×2 max pooling with stride [2 2] and padding [0 0 0 0]
8 '' Transposed Convolution 32 4×4 transposed convolutions with stride [2 2] and cropping [1 1 1 1]
9 '' ReLU ReLU
10 '' Transposed Convolution 32 4×4 transposed convolutions with stride [2 2] and cropping [1 1 1 1]
11 '' ReLU ReLU
12 '' Convolution 5 1×1 convolutions with stride [1 1] and padding [0 0 0 0]
13 '' Softmax softmax
14 '' Pixel Classification Layer Cross-entropy loss
>> dataSetDir = fullfile('C:\Users\a0050627\Pictures\3D reconstruction stacks\Final dissertation images\final dissertation images\ground truth 13 32h24w\trainingImages');
imageDir = fullfile('C:\Users\a0050627\Pictures\3D reconstruction stacks\Final dissertation images\final dissertation images\ground truth 13 32h24w\trainingImages');
labelDir = fullfile('C:\Users\a0050627\Pictures\3D reconstruction stacks\Final dissertation images\final dissertation images\ground truth 13 32h24w\trainingLabels');
>> imds = imageDatastore(imageDir);
classNames = ["Fibrous_tissue" "Cartilage" "Blood_cells" "Smooth_muscle" "Background"];
labelIDs = [1 2 3 4 5];
pxds = pixelLabelDatastore(labelDir,classNames,labelIDs);
I = read(imds);
C = read(pxds);
>> I = imresize(I,5);
L = imresize(uint8(C{1}),5);
imshowpair(I,L,'montage')
numFilters = 56;
filterSize = 3;
numClasses = 5;
layers = [
imageInputLayer([24 32 3])
convolution2dLayer(filterSize,numFilters,'Padding',1)
reluLayer()
maxPooling2dLayer(2,'Stride',2)
convolution2dLayer(filterSize,numFilters,'Padding',1)
reluLayer()
transposedConv2dLayer(4,numFilters,'Stride',2,'Cropping',1);
convolution2dLayer(1,numClasses);
softmaxLayer()
pixelClassificationLayer()
];
opts = trainingOptions('sgdm', ...
'InitialLearnRate',1e-3, ...
'MaxEpochs',100, ...
'MiniBatchSize',56);
trainingData = combine(imds,pxds);
net = trainNetwork(trainingData,layers,opts);
testImage = imread('trainingImages0000.tif');
imshow(testImage)
C = semanticseg(testImage,net);
B = labeloverlay(testImage,C);
imshow(B)
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 | 16.08% | 2.4888 | 0.0010 |
| 50 | 50 | 00:00:03 | 69.22% | 0.8458 | 0.0010 |
| 100 | 100 | 00:00:05 | 73.94% | 0.6949 | 0.0010 |
|========================================================================================|
Error using imread>get_full_filename (line 570)
File "trainingImages0000.tif" does not exist.
Error in imread (line 377)
fullname = get_full_filename(filename);
>> I = imresize(I,5);
L = imresize(uint8(C{1}),5);
imshowpair(I,L,'montage')
numFilters = 56;
filterSize = 3;
numClasses = 5;
layers = [
imageInputLayer([24 32 3])
convolution2dLayer(filterSize,numFilters,'Padding',1)
reluLayer()
maxPooling2dLayer(2,'Stride',2)
convolution2dLayer(filterSize,numFilters,'Padding',1)
reluLayer()
transposedConv2dLayer(4,numFilters,'Stride',2,'Cropping',1);
convolution2dLayer(1,numClasses);
softmaxLayer()
pixelClassificationLayer()
];
opts = trainingOptions('sgdm', ...
'InitialLearnRate',1e-3, ...
'MaxEpochs',100, ...
'MiniBatchSize',56);
trainingData = combine(imds,pxds);
net = trainNetwork(trainingData,layers,opts);
testImage = imread('trainingImages0000.tif');
imshow(testImage)
C = semanticseg(testImage,net);
B = labeloverlay(testImage,C);
imshow(B)
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 | 25.46% | 2.5070 | 0.0010 |
| 50 | 50 | 00:00:03 | 71.97% | 0.8210 | 0.0010 |
| 100 | 100 | 00:00:05 | 75.99% | 0.6633 | 0.0010 |
|========================================================================================|
>> dataSetDir = fullfile('C:\Users\a0050627\Pictures\3D reconstruction stacks\Final dissertation images\final dissertation images\ground truth 13 32h24w\dataSetDir');
testImagesDir = fullfile('C:\Users\a0050627\Pictures\3D reconstruction stacks\Final dissertation images\final dissertation images\ground truth 13 32h24w\trainingImages');
imds = imageDatastore(testImagesDir);
testLabelsDir = fullfile('C:\Users\a0050627\Pictures\3D reconstruction stacks\Final dissertation images\final dissertation images\ground truth 13 32h24w\trainingLabels');
classNames = ["Fibrous_tissue" "Cartilage" "Blood_cells" "Smooth_muscle" "Background"];
labelIDs = [1 2 3 4 5];
pxdsTruth = pixelLabelDatastore(testLabelsDir,classNames,labelIDs);
pxdsResults = semanticseg(imds,net,"WriteLocation",tempdir);
metrics = evaluateSemanticSegmentation(pxdsResults,pxdsTruth);
metrics.ClassMetrics
metrics.ConfusionMatrix
normConfMatData = metrics.NormalizedConfusionMatrix.Variables;
figure
h = heatmap(classNames,classNames,100*normConfMatData);
h.XLabel = 'Predicted Class';
h.YLabel = 'True Class';
h.Title = 'Normalized Confusion Matrix (%)';
imageIoU = metrics.ImageMetrics.MeanIoU;
figure
histogram(imageIoU)
title('Image Mean IoU')
[minIoU, worstImageIndex] = min(imageIoU);
minIoU = minIoU(1);
worstImageIndex = worstImageIndex(1);
worstTestImage = readimage(imds,worstImageIndex);
worstTrueLabels = readimage(pxdsTruth,worstImageIndex);
worstPredictedLabels = readimage(pxdsResults,worstImageIndex);
worstTrueLabelImage = im2uint8(worstTrueLabels == classNames(1));
worstPredictedLabelImage = im2uint8(worstPredictedLabels == classNames(1));
worstMontage = cat(4,worstTestImage,worstTrueLabelImage,worstPredictedLabelImage);
worstMontage = imresize(worstMontage,4,"nearest");
figure
montage(worstMontage,'Size',[1 3])
title(['Test Image vs. Truth vs. Prediction. IoU = ' num2str(minIoU)])
[maxIoU, bestImageIndex] = max(imageIoU);
maxIoU = maxIoU(1);
bestImageIndex = bestImageIndex(1);
bestTestImage = readimage(imds,bestImageIndex);
bestTrueLabels = readimage(pxdsTruth,bestImageIndex);
bestPredictedLabels = readimage(pxdsResults,bestImageIndex);
bestTrueLabelImage = im2uint8(bestTrueLabels == classNames(1));
bestPredictedLabelImage = im2uint8(bestPredictedLabels == classNames(1));
bestMontage = cat(4,bestTestImage,bestTrueLabelImage,bestPredictedLabelImage);
bestMontage = imresize(bestMontage,4,"nearest");
figure
montage(bestMontage,'Size',[1 3])
title(['Test Image vs. Truth vs. Prediction. IoU = ' num2str(maxIoU)])
evaluationMetrics = ["accuracy" "iou"];
metrics = evaluateSemanticSegmentation(pxdsResults,pxdsTruth,"Metrics",evaluationMetrics);
metrics.ClassMetrics
Running semantic segmentation network
-------------------------------------
* Processed 8 images.
Evaluating semantic segmentation results
----------------------------------------
* Selected metrics: global accuracy, class accuracy, IoU, weighted IoU, BF score.
* Processed 8 images.
* Finalizing... Done.
* Data set metrics:
GlobalAccuracy MeanAccuracy MeanIoU WeightedIoU MeanBFScore
______________ ____________ _______ ___________ ___________
0.7609 0.42784 0.34059 0.6219 0.49539
ans =
5×3 table
Accuracy IoU MeanBFScore
________ _______ ___________
Fibrous_tissue 0 0 NaN
Cartilage 0.41071 0.31293 0.44522
Blood_cells 0.20241 0.16634 0.27843
Smooth_muscle 0.61982 0.45857 0.57353
Background 0.90628 0.7651 0.68441
ans =
5×5 table
Fibrous_tissue Cartilage Blood_cells Smooth_muscle Background
______________ _________ ___________ _____________ __________
Fibrous_tissue 0 3 6 6 0
Cartilage 0 46 37 28 1
Blood_cells 0 20 84 273 38
Smooth_muscle 0 12 42 1151 652
Background 0 0 5 346 3394
Looking forward to a response,
Zandile
0 Comments
Answers (1)
Avadhoot
on 24 Jan 2024
Hi Zandine,
From your question I infer that you need to plot the ROC curve for your segmentation model. Typically it is not a standard practice to use ROC curves in case of segmentation as it is a multiclass and pixel-by-pixel classification problem. You could generate ROC curve for all the classes separately. In this approach, for every class that class is considered as positive and all the other classes are considered as negative. For that you will require the predicted probabilities matrix for this data. This matrix should contain the output of your neural network before the softmax layer. Using that you can calculate the true positive rate (TPR) and the false positive rate(FPR) for each class in the data.
You can refer to a sample code given below:
for i = 1:numClasses
% Get predicted probabilities for class 'i'
predictedProbabilitiesForClass = predictedProbabilities(:,:,i);
% Initialize arrays to hold TPR and FPR values
TPR = [];
FPR = [];
% Threshold levels to evaluate
thresholds = 0:0.01:1;
for threshold = thresholds
% Binarize predictions based on the current threshold
predictedLabels = predictedProbabilitiesForClass >= threshold;
% Calculate confusion matrix elements
TP = sum((predictedLabels == 1) & (trueLabels == i), 'all');
FP = sum((predictedLabels == 1) & (trueLabels ~= i), 'all');
TN = sum((predictedLabels == 0) & (trueLabels ~= i), 'all');
FN = sum((predictedLabels == 0) & (trueLabels == i), 'all');
% Calculate True Positive Rate (TPR) and False Positive Rate (FPR)
currentTPR = TP / (TP + FN);
currentFPR = FP / (FP + TN);
% Append to TPR and FPR arrays
TPR = [TPR, currentTPR];
FPR = [FPR, currentFPR];
end
% Sort the FPR and TPR values
[FPR, ind] = sort(FPR);
TPR = TPR(ind);
% Plot ROC curve for class 'i'
figure;
plot(FPR, TPR);
xlabel('False Positive Rate');
ylabel('True Positive Rate');
title(sprintf('ROC Curve for Class %d', i));
end
Below are the few considerations regarding the code:
I hope it helps.
0 Comments
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!