多目标优化算法(四)NSGA3(NSGAIII)论文复现以及matlab和python的代码

前言:最近太忙,这个系列已经很久没有更新了,本次就更新一个Deb大神的NSGA2的“升级版”算法NSGA3。因为multi-objective optimization已经被做烂了,现在学者们都在做many-objective optimization,也就是5个以上的目标函数(悄悄说一句,我觉得这个也要被做烂了)。此次我是用python复现的,这篇文章也主要以python代码讲解为主。在编写代码过程中,一些小技巧借鉴了platEMO,这个平台在我之前的博客里已经介绍过了,里面包含了近乎所有知名的多目标优化算法,想学习的小伙伴可以看我之前的博客介绍:https://blog.csdn.net/qq_40434430/article/details/88366639
为了哪些只想使用NSGA3的同学,我将NSGA3的matlab代码从平台中扣了出来,想要的在我的主页里下载吧,链接如下:(matlab我使用的是2017版的)
https://download.csdn.net/download/qq_40434430/11079440
python代码使用的python3.6,其它版本的也可以,毕竟没有用到什么复杂的库,就只是用到了numpy等常用的库。完整的python代码大家也可以去我CSDN主页下载哈,连接如下:
https://download.csdn.net/download/qq_40434430/11079551

摘要:此次博客主要记录了Kalyanmoy Deb和Himanshu Jain《An Evolutionary Many-Objective Optimization Algorithm Using Reference-point Based Non-dominated Sorting Approach, Part I: Solving Problems with Box Constraints》的论文学习心得[1],此篇文章提出了处理多个优化目标的进化优化算法NSGAIII。其主要思路是在NSGAII的基础上,引入参考点机制,对于那些非支配并且接近参考点的种群个体进行保留。此次复现处理的优化问题是具有3到15个目标的DTLZ系列[2],仿真结果反应了NSGAIII良好的搜索帕累托最优解集的能力。

关键字:Many-objective optimization,高维问题,NSGAIII,非支配排序,参考点

I.问题简介

​ 在很多真实的应用中,优化目标往往不只有一两个,而是有4个以上。针对这样的高维目标空间,现有的EMO显得有些力不从心,其主要问题为以下六点:

  1. 随着优化目标数量的增加,非支配解在种群中的比例也在增加,因而会导致搜索过程缓慢;
  2. 对于高维目标空间,维持多样性的指标计算复杂度过高,解的邻近元素寻找困难;
  3. 对于高维目标空间,重组算子的搜索能力过于低效了;
  4. 因为目标函数较多,pareto前沿难以表示,决策者无法选择自己需要的解;
  5. 性能指标的计算代价过大,算法结果不易评价;
  6. 针对高维的目标空间,如何可视化结果也是一个难题。

​ 对于前三个问题,我们可以改造EMO缓解,但是后三个问题目前还没有解决办法。除了以上问题,实际问题中由于目标解集集中在pareto front的一个小区域,因此如何寻找也是算法应用到实际中的一个阻碍。但有研究发现目标函数往往会退化成低维的优化,一般会低2~3维,因此冗余目标的识别也是一个难点。以下提出两种解决1,2,3问题的思路:

  1. 使用特殊的支配关系:可以引入自适应离散化pareto front从而解决问题1、2,使用具有较大指数分布的SBX解决问题3。
  2. 使用预定义的目标搜索:这种方式又可以分为两种:第一种是预定义一组跨越整个pareto front的搜索方向,这种方法的代表是MOEA/D;另一种是预定义多个参考点,比如算法NSGAIII。

II.NSGAIII算法要点和总结

​ 总体上来说,NSGAIII和NSGAII具有类似的框架,二者区别主要在于选择机制的改变,NSGAII主要靠拥挤度进行排序,其在高维目标空间显然作用不太明显,而NSGAIII对拥挤度排序进行了大刀阔斧的改编,通过引入广泛分布参考点来维持种群的多样性。

​ 以下总结NSGAIII的第t代的步骤。 P t P_t Pt是第t代的父代,其大小为N,其生成的子代为 Q t Q_t Qt,其大小也为N。第一步将子代和父代结合 R t = P t ∪ Q t R_t=P_t\cup Q_t Rt=PtQt(大小为2N)并从中选出N个个体。为了实现这个选择过程,首先将 R t R_t Rt通过非支配排序分为多个非支配层( F 1 , F 2 , . . . F_1,F_2,... F1,F2,...)。然后从 F 1 F_1 F1开始构造一个新的种群 S t S_t St,直到其大小为N或者第一次超过N。称最后一层为第 l l l层。第 l + 1 l+1 l+1层以上的解将被淘汰出局,在大多数情况下,最后一层被接受层( l l l层)仅有部分被接受。在这种情况下,就要用多样性衡量 l l l层里的解进而进行选择。NSGAII里的这部分使用了拥挤度排序,NSGAIII中我们用以下5步替代。下面先给出这个NSGAIII的第t代的算法步骤如下:

在这里插入图片描述

​ 这里需要注意:算法输入里的H是结构化参考点的数目,我在后文中定义为P
主程序的python代码如下:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D  # 空间三维画图
from utils import uniformpoint,funfun,cal,GO,envselect,IGD
import copy
import random

#参数设置
N_GENERATIONS = 400                                 # 迭代次数
POP_SIZE = 100                                      # 种群大小
name = 'DTLZ1'                                      # 测试函数选择,目前可供选择DTLZ1,DTLZ2,DTLZ3
M = 3                                               # 目标个数
t1 = 20                                             # 交叉参数t1
t2 = 20                                             # 变异参数t2
pc = 1                                              # 交叉概率
pm = 1                                              # 变异概率
#画图部分
if(M<=3):
    fig = plt.figure()
    ax = Axes3D(fig)

###################################################################################################################################################################
#产生一致性的参考点和随机初始化种群
Z,N = uniformpoint(POP_SIZE,M)#生成一致性的参考解
pop,popfun,PF,D = funfun(M,N,name)#生成初始种群及其适应度值,真实的PF,自变量个数
popfun = cal(pop,name,M,D)#计算适应度函数值
Zmin = np.array(np.min(popfun,0)).reshape(1,M)#求理想点
#ax.scatter(Z[:,0],Z[:,1],Z[:,2],c='r')
#ax.scatter(PF[:,0],PF[:,1],PF[:,2],c='b')

#迭代过程
for i in range(N_GENERATIONS):
    print("第{name}次迭代".format(name=i)) 
    matingpool=random.sample(range(N),N)   
    off = GO(pop[matingpool,:],t1,t2,pc,pm)#遗传算子,模拟二进制交叉和多项式变异
    offfun = cal(off,name,M,D)#计算适应度函数
    mixpop = copy.deepcopy(np.vstack((pop, off)))
    Zmin = np.array(np.min(np.vstack((Zmin,offfun)),0)).reshape(1,M)#更新理想点
    pop = envselect(mixpop,N,Z,Zmin,name,M,D)
    popfun = cal(pop,name,M,D)
    if(M<=3):
        ax.cla()
        type1 = ax.scatter(popfun[:,0],popfun[:,1],popfun[:,2],c='g')
        plt.pause(0.00001)

# 绘制PF
if(M<=3):
    type2 = ax.scatter(PF[:,0],PF[:,1],PF[:,2],c='r',marker = 'x',s=200)
    plt.legend((type1, type2), (u'Non-dominated solution', u'PF'))
else:
    fig1 = plt.figure()
    plt.xlim([0,M])
    for i in range(pop.shape[0]):
        plt.plot(np.array(pop[i,:]))    
plt.show()

#IGD
score = IGD(popfun,PF)

1.将种群按照非支配层进行划分

​ 将非支配层等级1到 l l l的种群成员依次放入 S t S_t St中,如果 ∣ S t ∣ = N |S_t|=N St=N,则无需进行下面的操作,直接 P t + 1 = S t P_{t+1}=S_t Pt+1=St。如果 ∣ S t ∣ &gt; N |S_t|&gt;N St>N,那么下一代的一部分解为 P t + 1 = ∪ i = 1 l − 1 F i P_{t+1}=\cup _{i=1}^{l-1}F_i Pt+1=i=1l1Fi,剩余部分( K = N − ∣ P t + 1 ∣ K=N-|P_{t+1}| K=NPt+1)从 F l F_l Fl中选择。这个选择过程见步骤2到5。
非支配排序的python代码如下:

from scipy.special import comb
from itertools import combinations
import numpy as np
import copy
import math
def NDsort(mixpop,N,M):
    nsort = N#排序个数
    N,M = mixpop.shape[0],mixpop.shape[1]
    Loc1=np.lexsort(mixpop[:,::-1].T)#loc1为新矩阵元素在旧矩阵中的位置,从第一列依次进行排序
    mixpop2=mixpop[Loc1]
    Loc2=Loc1.argsort()#loc2为旧矩阵元素在新矩阵中的位置
    frontno=np.ones(N)*(np.inf)#初始化所有等级为np.inf
    #frontno[0]=1#第一个元素一定是非支配的
    maxfno=0#最高等级初始化为0
    while (np.sum(frontno < np.inf) < min(nsort,N)):#被赋予等级的个体数目不超过要排序的个体数目
        maxfno=maxfno+1
        for i in range(N):
            if (frontno[i] == np.inf):
                dominated = 0
                for j in range(i):
                    if (frontno[j] == maxfno):
                        m=0
                        flag=0
                        while (m<M and mixpop2[i,m]>=mixpop2[j,m]):
                            if(mixpop2[i,m]==mixpop2[j,m]):#相同的个体不构成支配关系
                                flag=flag+1
                            m=m+1 
                        if (m>=M and flag < M):
                            dominated = 1
                            break
                if dominated == 0:
                    frontno[i] = maxfno
    frontno=frontno[Loc2]
    return frontno,maxfno

2.超平面上参考点的确定

​ NSGAIII使用一组预定义的参考点以确保解的多样性,这一组参考点可以结构化的方式定义,也可以用户根据自己的参考点。以下介绍一种产生结构化参考点的方法叫Das and Dennis’s method,此方法来源于田野老师对产生参考点方法的综述论文[3]。其参考点在一个(M-1)维的超平面上,M是目标空间的维度,即优化目标的个数。如果我们将每个目标划分为 H H H份,那么其参考点的数量为
P = ( m + H − 1 H ) P=(\begin{matrix} m+H-1\\ H \end{matrix}) P=(m+H1H)
例如对于一个 H = 4 H=4 H=4的三目标问题,其参考点构成了一个三角形,根据公式(1)可知其产生15个参考点,见图1所示。

在这里插入图片描述

图1 对于一个H=4的三目标的问题产生的15个参考点

​ 那么它们的坐标该如何计算呢?以下通过田野老师的论文讲解一下如何产生这些参考点。假设由Das and Dennis’s method产生的参考点为 s = ( s 1 , s 2 , . . . , s M ) s=(s_1,s_2,...,s_M) s=(s1,s2,...,sM),这里
s j ∈ { 0 / H , 1 / H , . . . , H / H } , ∑ j = 1 M s j = 1 s_j\in \left\{ 0/H,1/H,...,H/H \right\},\sum_{j=1}^{M}s_j=1 sj{ 0/H,1/H,...,H/H},j=1Msj=

评论 54
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值