前言
在评估多目标优化算法的效果时,我们通常使用五个主要指标:GD(Generational Distance)、IGD(Inverted Generational Distance)、Hypervolume、Spacing和Spread。
GD和IGD是用于测量算法生成的解集合与真实前沿解之间的距离的指标。具体而言,GD测量了所有生成解与真实前沿解之间的平均欧几里得距离,而IGD测量了所有真实前沿解与生成解之间的平均欧几里得距离。这两个指标的目标是越小越好,即算法的生成解集合应该尽可能接近真实前沿解。
Hypervolume则是用于测量算法生成的解集合能够覆盖的真实前沿解的体积大小的指标。目标是越大越好,即算法生成的解集合应该尽可能覆盖更多的真实前沿解。
Spacing和Spread是用于测量算法生成的解集合的分布情况的指标。Spacing测量了所有解之间的最小欧几里得距离,而Spread测量了所有解之间的最大欧几里得距离。
通过对这些指标的全面评估,我们可以更好地了解算法的表现并进行优化。
代码实现
MATLAB
Spread.m
%% PopObj:算法求得的pareto解集
%% PF:真实的解集
function Score = Spread(PopObj,PF)
Dis1 = pdist2(PopObj,PopObj);
Dis1(logical(eye(size(Dis1,1)))) = inf;
[~,E] = max(PF,[],1);PF(E,:)
Dis2 = pdist2(PF(E,:),PopObj);
d1 = sum(min(Dis2,[],2));
d2 = mean(min(Dis1,[],2));
Score = (d1+sum(abs(min(Dis1,[],2)-d2))) / (d1+(size(PopObj,1)-size(PopObj,2))*d2);
end
Spacing.m
%% PopObj:算法求得的pareto解集
%% PF:真实的解集
function Score = Spacing(PopObj,PF)
Distance = pdist2(PopObj,PopObj,'cityblock');
Distance(logical(eye(size(Distance,1)))) = inf;
Score = std(min(Distance,[],2));
end
IGD.m
%% PopObj:算法求得的pareto解集
%% PF:真实的解集
function Score = IGD(PopObj,PF)
Distance = min(pdist2(PF,PopObj),[],2);
Score = mean(Distance);
end
HV.m
%% PopObj:算法求得的pareto解集
%% PF:真实的解集
function [Score,PopObj] = HV(PopObj,PF)
% Hypervolume
[N,M] = size(PopObj);
fmin = min(min(PopObj,[],1),zeros(1,M));
fmax = max(PF,[],1);
PopObj = (PopObj-repmat(fmin,N,1))./repmat((fmax-fmin)*1.1,N,1);
PopObj(any(PopObj>1,2),:) = [];
% The reference point is set to (1,1,...)
RefPoint = ones(1,M);
if isempty(PopObj)
Score = 0;
elseif M < 4
% Calculate the exact HV value
pl = sortrows(PopObj);
S = {1,pl};
for k = 1 : M-1
S_ = {};
for i = 1 : size(S,1)
Stemp = Slice(cell2mat(S(i,2)),k,RefPoint);
for j = 1 : size(Stemp,1)
temp(1) = {cell2mat(Stemp(j,1))*cell2mat(S(i,1))};
temp(2) = Stemp(j,2);
S_ = Add(temp,S_);
end
end
S = S_;
end
Score = 0;
for i = 1 : size(S,1)
p = Head(cell2mat(S(i,2)));
Score = Score + cell2mat(S(i,1))*abs(p(M)-RefPoint(M));
end
else
% Estimate the HV value by Monte Carlo estimation
SampleNum = 1000000;
MaxValue = RefPoint;
MinValue = min(PopObj,[],1);
Samples = unifrnd(repmat(MinValue,SampleNum,1),repmat(MaxValue,SampleNum,1));
if gpuDeviceCount > 0
% GPU acceleration
Samples = gpuArray(single(Samples));
PopObj = gpuArray(single(PopObj));
end
for i = 1 : size(PopObj,1)
drawnow();
domi = true(size(Samples,1),1);
m = 1;
while m <= M && any(domi)
domi = domi & PopObj(i,m) <= Samples(:,m);
m = m + 1;
end
Samples(domi,:) = [];
end
Score = prod(MaxValue-MinValue)*(1-size(Samples,1)/SampleNum);
end
end
function S = Slice(pl,k,RefPoint)
p = Head(pl);
pl = Tail(pl);
ql = [];
S = {};
while ~isempty(pl)
ql = Insert(p,k+1,ql);
p_ = Head(pl);
cell_(1,1) = {abs(p(k)-p_(k))};
cell_(1,2) = {ql};
S = Add(cell_,S);
p = p_;
pl = Tail(pl);
end
ql = Insert(p,k+1,ql);
cell_(1,1) = {abs(p(k)-RefPoint(k))};
cell_(1,2) = {ql};
S = Add(cell_,S);
end
function ql = Insert(p,k,pl)
flag1 = 0;
flag2 = 0;
ql = [];
hp = Head(pl);
while ~isempty(pl) && hp(k) < p(k)
ql = [ql;hp];
pl = Tail(pl);
hp = Head(pl);
end
ql = [ql;p];
m = length(p);
while ~isempty(pl)
q = Head(pl);
for i = k : m
if p(i) < q(i)
flag1 = 1;
else
if p(i) > q(i)
flag2 = 1;
end
end
end
if ~(flag1 == 1 && flag2 == 0)
ql = [ql;Head(pl)];
end
pl = Tail(pl);
end
end
function p = Head(pl)
if isempty(pl)
p = [];
else
p = pl(1,:);
end
end
function ql = Tail(pl)
if size(pl,1) < 2
ql = [];
else
ql = pl(2:end,:);
end
end
function S_ = Add(cell_,S)
n = size(S,1);
m = 0;
for k = 1 : n
if isequal(cell_(1,2),S(k,2))
S(k,1) = {cell2mat(S(k,1))+cell2mat(cell_(1,1))};
m = 1;
break;
end
end
if m == 0
S(n+1,:) = cell_(1,:);
end
S_ = S;
end
GD.m
%% PopObj:算法求得的pareto解集
%% PF:真实的解集
function Score = GD(PopObj,PF)
% Generational distance
Distance = min(pdist2(PopObj,PF),[],2);
Score = norm(Distance) / length(Distance);
end