Plot gaplotdistance in one plot for multiple runs of genetic algorithm
Show older comments
Dear all,
With the code below I managed to run the genetic algorithm multiple times.
gprMdl2 = fitrgp(X,Y1,'KernelFunction','squaredexponential','OptimizeHyperparameters','auto','HyperparameterOptimizationOptions',struct('AcquisitionFunctionName','expected-improvement-plus'));
for i = 1:3
options = optimoptions('ga','CrossoverFrac',0.9,'PopulationSize',50,'StallGen',50,'Generations',70,'PlotFcn', {'gaplotbestf','gaplotdistance'});
fun = @(X) [abs(((predict(gprMdl2,X)-MFR_exp)/MFR_exp))];
[x_opt, Obj, exitflag,output] = ga(fun,2,[],[],[],[],[0.1 0.1], [0.9 0.9],[],[],options);
end
With PlotFcn I will get the plot of the fitness value vs genration and the average distance vs generation (as shown below). How can I combine the plots of each run into one plot?

7 Comments
Mario Malic
on 28 Oct 2020
Edited: Mario Malic
on 28 Oct 2020
Hello,
You can make your own OutputFcn for ga that does what you want. You can do the plotting with plotyy function.
Tessa Kol
on 28 Oct 2020
Mario Malic
on 28 Oct 2020
Edited: Mario Malic
on 28 Oct 2020
First, backup the original gaplotdistance.m file and create your own, under different name and call that one.
In the case of PlotFcn, optimisation solver creates a figure on its own, outside of plot function, so in case of OutputFcn, you should do it prior to calling the solver and set a name or a tag so you can find it in the OutputFcn.
OptimAxes = axes(1)
set(OptimAxes, 'Name', 'CustomOptimPlot')
Regarding the custom output function: Actually plotyy is not recommended anymore, yyaxis should be used. In this example right yyaxis is considered to be gaplotbestf as it has additional case 'done'.
function state = gaplotdistance(options,state,flag)
%GAPLOTDISTANCE Averages several samples of distances between individuals.
% STATE = GAPLOTDISTANCE(OPTIONS,STATE,FLAG) plots an averaged distance
% between individuals.
%
% Example:
% Create an options structure that uses GAPLOTDISTANCE
% as the plot function
% options = optimoptions('ga','PlotFcn',@gaplotdistance);
%
% (Note: If calling gamultiobj, replace 'ga' with 'gamultiobj')
% Copyright 2003-2015 The MathWorks, Inc.
% Getting the handle for axes *** test if you can move this in case 'init'
Axes = findobj('Name', 'CustomOptimPlot')
% options for left - gaplotdistance.m
samples = 20;
choices = ceil(sum(options.PopulationSize) * rand(samples,2));
% options for right - gaplotbestf
if size(state.Score,2) > 1
msg = getString(message('globaloptim:gaplotcommon:PlotFcnUnavailable','gaplotbestf'));
title(msg,'interp','none');
return;
end
switch flag
case 'init'
yyaxis left
% Code for first PlotFcn
yyaxis right
% Code for second PlotFcn
case 'iter'
yyaxis left
% Code for first PlotFcn
yyaxis right
% Code for second PlotFcn
case 'done'
yyaxis right
% Code for second PlotFcn
end
There might be some options that interfere with each other, like titles and labels, so consider that as well.
Edit: I will update comment later on the saving the variables
Tessa Kol
on 29 Oct 2020
Mario Malic
on 29 Oct 2020
Edited: Mario Malic
on 29 Oct 2020
Unfortunately, I am not familiar with ga, if you're looking for all values of variable d, throughout all optimisations, this would be the way to do it.
function state = customgaplotdistance(options,state,flag)
%GAPLOTDISTANCE Averages several samples of distances between individuals.
% STATE = GAPLOTDISTANCE(OPTIONS,STATE,FLAG) plots an averaged distance
% between individuals.
%
% Example:
% Create an options structure that uses GAPLOTDISTANCE
% as the plot function
% options = optimoptions('ga','PlotFcn',@gaplotdistance);
%
% (Note: If calling gamultiobj, replace 'ga' with 'gamultiobj')
% Copyright 2003-2015 The MathWorks, Inc.
persistent testdist % change number 1
testdist(1,:) = [0 0]; % initialising the value
samples = 20;
choices = ceil(sum(options.PopulationSize) * rand(samples,2));
switch flag
case 'init'
population = state.Population;
distance = 0;
for i = 1:samples
d = population(choices(i,1),:) - population(choices(i,2),:);
distance = distance + sqrt( sum ( d.* d));
testdist(end+1,:) = d; % change number 2
end
plotDist = plot(state.Generation,distance/samples,'.');
set(gca,'xlimmode','manual','zlimmode','manual', ...
'alimmode','manual')
set(gca,'xlim',[1,options.MaxGenerations]);
set(plotDist,'Tag','gaplotdistance');
xlabel('Generation','interp','none');
ylabel('Average Distance');
title('Average Distance Between Individuals','interp','none')
case 'iter'
population = state.Population;
distance = 0;
for i = 1:samples
d = population(choices(i,1),:) - population(choices(i,2),:);
distance = distance + sqrt( sum ( d.* d));
testdist(end+1,:) = d; % change number 3
assignin('base', 'testdist', testdist) % it might be better to assign it and save it from the main file
% save('testdist.mat', 'testdist') % as it will save the file 3000+ times
end
plotDist = findobj(get(gca,'Children'),'Tag','gaplotdistance');
newX = [get(plotDist,'Xdata') state.Generation];
newY = [get(plotDist,'Ydata') distance/samples];
set(plotDist,'Xdata',newX,'Ydata',newY);
end
Mario Malic
on 31 Oct 2020
Edited: Mario Malic
on 31 Oct 2020
Great to hear it works! Actually, I put the distance first, and then I thought, but it doesn't show every single distance out there, so I set it back to d.
Accepted Answer
More Answers (0)
Categories
Find more on Install Products in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!