143 lines
5.3 KiB
Matlab
143 lines
5.3 KiB
Matlab
function plot_results2(results, cfg, classLabels)
|
||
% PLOT_RESULTS2 — Scenario 2 plotting suite
|
||
% Produces and saves:
|
||
% (A) CV heatmap of Kappa over (#features × radius)
|
||
% (B) CV heatmap of mean #rules over the same grid
|
||
% (C) Confusion matrix on TEST for the best model
|
||
% (D) PA/UA bars on TEST
|
||
% (E) Learning curves (train/validation error)
|
||
% (F) MFs before/after for the best model
|
||
% (G) Truth vs Prediction (TEST)
|
||
% (H) ReliefF feature weights bar chart
|
||
%
|
||
% All PNGs saved under cfg.outDir.
|
||
|
||
outDir = cfg.outDir;
|
||
|
||
% (A) CV heatmap — Kappa
|
||
fig = figure('Color','w');
|
||
imagesc(results.cvScores);
|
||
set(gca,'XTick',1:numel(results.rGrid),'XTickLabel',compose('%.2f',results.rGrid));
|
||
set(gca,'YTick',1:numel(results.fGrid),'YTickLabel',string(results.fGrid));
|
||
xlabel('SC radius r_a'); ylabel('#Features (ReliefF)'); colorbar;
|
||
title(sprintf('CV mean Kappa (K=%d folds)', cfg.kfold));
|
||
for i = 1:numel(results.fGrid)
|
||
for j = 1:numel(results.rGrid)
|
||
text(j,i,sprintf('%.2f',results.cvScores(i,j)),...
|
||
'HorizontalAlignment','center','Color','w','FontWeight','bold');
|
||
end
|
||
end
|
||
exportgraphics(fig, fullfile(outDir,'cv_kappa_heatmap.png'), 'Resolution', 200);
|
||
close(fig);
|
||
|
||
% (B) CV heatmap — mean #rules
|
||
fig = figure('Color','w');
|
||
imagesc(results.cvRules);
|
||
set(gca,'XTick',1:numel(results.rGrid),'XTickLabel',compose('%.2f',results.rGrid));
|
||
set(gca,'YTick',1:numel(results.fGrid),'YTickLabel',string(results.fGrid));
|
||
xlabel('SC radius r_a'); ylabel('#Features (ReliefF)'); colorbar;
|
||
title(sprintf('CV mean #Rules (K=%d folds)', cfg.kfold));
|
||
for i = 1:numel(results.fGrid)
|
||
for j = 1:numel(results.rGrid)
|
||
text(j,i,sprintf('%d',results.cvRules(i,j)),...
|
||
'HorizontalAlignment','center','Color','w','FontWeight','bold');
|
||
end
|
||
end
|
||
exportgraphics(fig, fullfile(outDir,'cv_rules_heatmap.png'), 'Resolution', 200);
|
||
close(fig);
|
||
|
||
% (C) Confusion matrix — TEST
|
||
fig = figure('Color','w');
|
||
confusionchart(results.metrics.confMat, string(classLabels), ...
|
||
'Title', sprintf('Confusion — best model (features=%d, r=%.2f, rules=%d)', ...
|
||
results.bestF, results.bestR, numel(results.bestFis.rule)));
|
||
exportgraphics(fig, fullfile(outDir,'cm_best_model.png'), 'Resolution', 200);
|
||
close(fig);
|
||
|
||
% (D) PA/UA bars — TEST
|
||
fig = figure('Color','w');
|
||
t = tiledlayout(2,1,'TileSpacing','compact','Padding','compact');
|
||
nexttile; bar(results.metrics.PA); ylim([0 1]);
|
||
xticks(1:numel(classLabels)); xticklabels(string(classLabels));
|
||
ylabel('PA (Recall)'); title('Producer''s Accuracy (TEST)'); grid on;
|
||
nexttile; bar(results.metrics.UA); ylim([0 1]);
|
||
xticks(1:numel(classLabels)); xticklabels(string(classLabels));
|
||
ylabel('UA (Precision)'); title('User''s Accuracy (TEST)'); grid on;
|
||
exportgraphics(fig, fullfile(outDir,'pa_ua_best_model.png'), 'Resolution', 200);
|
||
close(fig);
|
||
|
||
% (E) Learning curves
|
||
fig = figure('Color','w');
|
||
plot(1:numel(results.trError), results.trError, 'LineWidth', 1.2); hold on;
|
||
if ~isempty(results.vaError)
|
||
plot(1:numel(results.vaError), results.vaError, '--', 'LineWidth', 1.2);
|
||
legend('Training Error','Validation Error','Location','best');
|
||
else
|
||
legend('Training Error','Location','best');
|
||
end
|
||
xlabel('Epoch'); ylabel('Error'); grid on;
|
||
title(sprintf('Learning Curve — best model (features=%d, r=%.2f)', ...
|
||
results.bestF, results.bestR));
|
||
exportgraphics(fig, fullfile(outDir,'learning_best_model.png'), 'Resolution', 200);
|
||
close(fig);
|
||
|
||
% (F) MFs before/after for the best model
|
||
try
|
||
plot_mfs_before_after(results.initFis, results.bestFis, ...
|
||
sprintf('MFs — best model (features=%d, r=%.2f)', results.bestF, results.bestR), ...
|
||
fullfile(outDir,'mfs_best_model.png'));
|
||
catch ME
|
||
warning('MF plot failed: %s', ME.message);
|
||
end
|
||
|
||
% (G) Truth vs Prediction — TEST
|
||
fig = figure('Color','w');
|
||
plot(results.ytrue, 'LineWidth', 1.0); hold on;
|
||
plot(results.yhat, '--', 'LineWidth', 1.0);
|
||
xlabel('Test sample index'); ylabel('Class label'); grid on;
|
||
title('Truth vs Prediction (TEST)');
|
||
legend('Truth','Prediction','Location','best');
|
||
exportgraphics(fig, fullfile(outDir,'pred_vs_truth_best_model.png'), 'Resolution', 200);
|
||
close(fig);
|
||
|
||
% (H) ReliefF feature weights (on full train+val)
|
||
fig = figure('Color','w');
|
||
w = results.reliefW(:);
|
||
idx = results.selIdx(:);
|
||
% map back: selected indices first for clarity
|
||
bar(1:numel(idx), w(idx)); grid on;
|
||
xlabel('Selected feature index'); ylabel('ReliefF weight');
|
||
title(sprintf('ReliefF weights (top %d features)', results.bestF));
|
||
exportgraphics(fig, fullfile(outDir,'relieff_weights_selected.png'), 'Resolution', 200);
|
||
close(fig);
|
||
|
||
|
||
|
||
|
||
% ===================== local helper =====================
|
||
function plot_mfs_before_after(fisBefore, fisAfter, suptitleStr, outPng)
|
||
D = numel(fisAfter.Inputs);
|
||
fig = figure('Color','w','Position',[100 100 1200 420]);
|
||
t = tiledlayout(2, D, 'TileSpacing','compact','Padding','compact');
|
||
for d = 1:D
|
||
nexttile(d); hold on;
|
||
try
|
||
[xB, yB] = plotmf(fisBefore, 'input', d);
|
||
plot(xB, yB, 'LineWidth', 1.0);
|
||
catch
|
||
end
|
||
title(sprintf('Input %d — BEFORE', d));
|
||
ylim([0 1]); grid on;
|
||
|
||
nexttile(D + d); hold on;
|
||
[xA, yA] = plotmf(fisAfter, 'input', d);
|
||
plot(xA, yA, 'LineWidth', 1.0);
|
||
title(sprintf('Input %d — AFTER', d));
|
||
ylim([0 1]); grid on;
|
||
end
|
||
sgtitle(suptitleStr);
|
||
exportgraphics(fig, outPng, 'Resolution', 200);
|
||
close(fig);
|
||
end
|
||
end
|