在前面几篇文章中,我们已经介绍了高性能Python遗传和进化算法框架——Geatpy的使用及一些案例。
https://blog.csdn.net/qq_33353186/article/details/82014986
https://blog.csdn.net/qq_33353186/article/details/82020507
https://blog.csdn.net/qq_33353186/article/details/82021750
https://blog.csdn.net/qq_33353186/article/details/82047692
本篇就一个多目标优化实例进行展开讲述,并且与使用Matlab工具箱得到相近效果进行一些对比:
Geatpy已于2018.08.27更新至1.0.4版本,提供了全新的多目标进化优化的模板函数,这些新模板可以同时支持连续型变量和离散型变量的多目标优化了。因此需要执行以下命令更新:
pip install --upgrade geatpy
下面对一个两个目标的最小化问题进行求解:
先用Geatpy尝试求解,直接套用内置的nsga2_templet编程模板:
-
# -*- coding: utf-8 -*-
-
"""main.py"""
-
import numpy
as np
-
import geatpy
as ga
-
-
def aimfuc(x):
# define the aim function
-
x1 = x[:,
0]; x2 = x[:,
1]
-
fun1 = x1**
4
-10*x1**
2+x1*x2+x2**
4-x1**
2*x2**
2
-
fun2 = x2**
4-x1**
2*x2**
2+x1**
4+x1*x2
-
return np.vstack([fun1, fun2]).T
# 对矩阵进行转置使得目标函数矩阵符合Geatpy数据结构
-
-
if __name__ ==
"__main__":
-
AIM_M = __import__(
'main')
# 获取函数接口所在文件的地址
-
# 变量设置
-
ranges = np.array([[
-5,
-5], [
5,
5]])
# 生成自变量的范围矩阵
-
borders = np.array([[
1,
1], [
1,
1]])
# 生成自变量的边界矩阵(1表示变量的区间是闭区间)
-
precisions = [
1,
1]
# 因为变量范围都是闭区间,而且nsga2_templet编程模板采用的是实数编码,因此precisions不起作用,随便设置均可
-
FieldDR = ga.crtfld(ranges, borders, precisions)
# 生成区域描述器
-
# 调用编程模板
-
[ObjV, NDSet, NDSetObjV, times] = ga.nsga2_templet(AIM_M,
'aimfuc',
None,
None, FieldDR,
'R', maxormin =
1, MAXGEN =
1000, MAXSIZE =
200, NIND =
200, SUBPOP =
1, GGAP =
1, selectStyle =
'tour', recombinStyle =
'xovdp', recopt =
0.9, pm =
0.6, drawing =
1)
执行结果:
这里设置了MAXSIZE为200,表示当搜索到的帕累托前沿点超过200个时就停止搜索。设置进化最大代数为1000,种群规模为200。这里是为了和后面的Matlab代码设置一样,实际上Geatpy的nsga2编程模板不需要很大的种群规模。并且,由于nsga2算法是将父子两代合并进行进化选择的,因此变异概率可以设置大一些,不会对影响算法的收敛性产生太大影响。
当前Geatpy内置的nsga2_templet编程模板中并没有严格约束帕累托解的均匀分布,在后面的版本中将提供一些帕累托前沿严格均分的算法模板。nsga2的算法模板源代码可以参见:
https://github.com/geatpy-dev/geatpy/blob/master/geatpy/source-code/templets/nsga2_templet.py
下面将用Matlab的遗传算法工具箱进行对比实验:
-
clc,clear
-
% 定义目标函数
-
fun1 = @(x) x(
1)^
4-
10*x(
1)^
2+x(
1)*x(
2)+x(
2)^
4-x(
1)^
2*x(
2)^
2; %min f1(x1,x2)
-
fun2 = @(x) x(
2)^
4-x(
1)^
2*x(
2)^
2+x(
1)^
4+x(
1)*x(
2); %min f2(x1,x2)
-
-
aimfuc = @(x) [fun1(x) fun2(x)]; %获取目标函数句柄
-
nvars=
2; %变量个数
-
lb=[-
5,-
5]; %下限
-
ub=[
5,
5]; %上限
-
A=[];b=[]; %线性不等式约束
-
Aeq=[];beq=[];%线性等式约束
-
tic %开始计时
-
options=gaoptimset(
'paretoFraction',
1,
'populationsize',
200,
'generations',
1000,
'stallGenLimit',
200,
'TolFun',
1e-
100);
-
[x,fval] = gamultiobj(aimfuc,nvars,A,b,Aeq,beq,lb,ub,options);
-
time = toc %结束计时
-
plot(fval(
:,
1),fval(
:,
2),
'k.') %绘图
-
fprintf(
'找到的前沿点数: %d\n', size(fval,
1));
-
fprintf(
'平均每秒找到的前沿点数: %f\n', size(fval,
1)/time);
-
执行结果如下:
对比发现Geatpy的效率比Matlab高出不少。尝试增大所需要搜索的帕累托前沿点的数量,Matlab变慢了一个数量级,而Geatpy的耗时基本稳定。
在Matlab的遗传算法工具箱中,是通过种群规模和"paretoFraction"的参数来控制帕累托最优解的数量的。当需要搜索大量的帕累托最优解时,Matlab的遗传算法工具箱就会变得极慢。这是因为种群规模太大的缘故。而Geatpy很好地解决了这个问题。Geatpy的许多编程模板都是采用一个全局帕累托最优解集来指导搜索过程的,种群规模不会因需要搜索更多的解而爆炸性增长。
Geatpy内核调用的是高性能mkl矩阵库,因此执行速度极快。
除了nsga-II算法外,Geatpy还支持适应性权法重法(awGA)、随机权重法(rwGA)、交互式适应性权重法(i-awGA)、基于快速非支配排序的多目标进化优化算法。相应的算法均整合在编程模板内,源代码参见:
https://github.com/geatpy-dev/geatpy/tree/master/geatpy/source-code/templets
仔细研究Geatpy的模板函数发现,这些内置的模板函数为了兼容多种情况,设置了较多的if语句去判定。因此,假如要达到更高的性能,可以模仿这些模板自定义一些新的模板。在前面的文章中我也初步谈到如何自定义编程模板。在下一篇,我将更加详细地讲解怎样把自创的多目标进化算法写成一个编程模板。欢迎继续跟进,感谢!