转载:NSGA以及NSGA2
转自http://hi.baidu.com/apricotlena/blog/item/a946fa35b129a40491ef394a.html
NSGA :《Multiobjective function optimization using nondominated sorting genetic algorithms》
与普通的遗传算法不同的在于非支配排序 以及share 的概念,对于越非支配的解,给的fitness越大,对于越密集的解,给的fitness越小。都是在选择的时候才用到。
算法在快速找到Pareto前沿和保持种群多样性方面都有很好的效果,不过存在如下问题:
1。非支配排序的时间复杂的很大,为O(MN^3)。其中M为目标函数的数量,N为种群规模。
2。不支持精英策略。精英策略在保持好的个体及加速向Pareto前沿收敛方面都有很好的表现。
3。需要自己指定共享参数。该参数将对种群的多样性产生很大的影响。
NSGA2:
对NSGA算法的改进。该NSGA2算法将在以下方面进行改进:快速的非支配排序; 精英保留;share-》crowding-distance
具体的会在下面给出。
NSGA2的一些细节:
二进制锦标赛选择,不过感觉和随机竞争方法也很相似。大概就是每次从两个父本选择出适应度高的解,这样选择两个,然后进行交叉以及变异。
“锦标赛选择方法:从群体中随机选择个体,将适应度最高的个体保存在下一代,反复执行到满足为止。”这个说得更像是从mixed群体找出下一代
“随机竞争方法:每次按赌轮选择方法选取一对个体,适应度高的获胜”。这个更像是二进制锦标赛法中选择个体进行交叉和变异。
“Boltzmann锦标赛选择:随机选择两个个体,若适应度相差很大,则选择好的,否则random。”这个更像nsga2的选择。只不过是似乎一直都只是选择好的解,除非两个解一样好才random。
采取的是精英保留,就是最佳个体保留,也就是对父代不进行交叉验证就直接复制到mixed中。
实数编码,“离散交叉:在父解向量中选择一部分分量,然后交换这些分量; 以0.5的概率交换父体s1和s2的所有分量”。
“算术交叉:现在父解向量中选择一部分分量,如第k个分量以后的所有分量,生成n-k个0到1的随机数,并将两个后代定义为:
Sz=(V1,...,Vk, a(k+1)V(k+1)+(1-a(k+1))V(k+1)', ...anVn+(1-an)Vn' ), Sw反之。”
“算术交叉2:先生成n个区间的随机数,则后代分布设定为
Zi=aiVi+(1-ai)Vi, Wi=aiVi'+(1-ai)*Vi''”
不过实数编码不一定,nsga2里面的是deb说的SBX。变异算子也是不一定。
1。快速的非支配排序
在NSGA进行非支配排序时,规模为N的种群中的每个个体都要针对M个目标函数和种群中的N-1个个体进行比较,复杂度为O(MN),因此种群中的N个个 体都比较结束的复杂度为O(MN2),即每进行一次Pareto分级的时间复杂度为O(MN2)。在最坏的情况下,每个Pareto级别都只含有一个个 体,那么需要进行N次分级所需要的时间复杂度则会上升为O(MN3)。鉴于此,论文中提出了一种快速非支配排序法,该方法的时间复杂度为O(MN2)。
该算法需要保存两个量:
(1).支配个数np。该量是在可行解空间中可以支配个体p的所以个体的数量。
(2).被支配个体集合SP。该量是可行解空间中所有被个体p支配的个体组成的集合。
排序算法的伪代码如下:
F = [ ]
for p in P:
Sp = [ ]
np = 0
for q in P:
if p > q: # 如果p支配q,把q添加到Sp列表中
Sp.append( q )
else if p < q: # 如果p被q支配,则把np加1
np += 1
if np == 0:
p_rank = 1 # 如果该个体的np为0,则该个体为Pareto第一级
F1.append( p )
F.append( F1 )
i = 0
while F[i]:
Q = [ ]
for p in F[i]:
for q in Sp: # 对所有在Sp集合中的个体进行排序
nq -= 1
if nq == 0: # 如果该个体的支配个数为0,则该个体是非支配个体
q_rank = i + 2 # 该个体Pareto级别为当前最高级别加1。此时i初始值为0,所以要加2
Q.append( q )
F.append( Q )
i += 1
在上面伪代码中,第一部分循环为二重循环,时间复杂度为O(N2),第二部分循环中,我们可以假设共有x个级别,而每个级别中最多有(N-N/x)各个 体,每个个体的支配集合中也最多有(N- N/x)各个体。由此可得出循环次数为x*(N-N/x)*(N-N/x)=((x-1)2/x2)N2M,即时间复杂度为O(MN2)。
2。种群中个体多样性的保留
原始的NSGA算法中使用共享函数的方法来维持物种的多样性,这种方法包含一个共享参数,该参数为所求解问题中所期望的共享范围。在该范围内,两个个体共享彼此的适应度。但是该方法有两个难点:
(1).共享函数方法在保持多样性的性能很大程度上依赖于所选择的共享参数值。
(2).种群中的每个个体都要与其余的个体相比较,因此该方法的全局复杂度为O(N2)。
在NSGA2中使用了排挤算法和精英策略来代替共享函数算法 。而要实现这两种方法,首先我们需要定义两个操作:密度估算和排挤算子。
(1).密度估算
要对拥挤距离进行计算,则需要根据每个目标函数对种群中的所有个体按升序进行排序。第一个和最后一个个体的拥挤距离设为无穷大,第i个个体的拥挤距离则设为第i+1和第i个体的所有目标函数值之差的和。具体方法如下面伪代码:
nLen = len( I ) # I中的个体数量
for i in I:
i.distance = 0 # 初始化所有个体的拥挤距离
for objFun in M: # M为所有目标函数的列表
I = sort( I, objFun ) # 按照目标函数objFun进行升序排序
I[0] = I[ len[I] - 1 ] = ∞ # 对第一个和最后一个个体的距离设为无穷大
for i in xrange( 1 , len(I) - 2 ):
I[i].distance = I[i].distance + ( objFun( I[i + 1 ] ) - objFun( I[i - 1 ] ) ) / (Max(objFun()) - Min(objFun()) )
伪代码中的objFun( i )是对个体i求其目标函数值。Max(objFun())为目标函数objFun()的最大值,Min(objFun())为目标函数objFun的最小值。其复杂度为O(MNlogN)。
3。主体循环部分
(1).随机初始化开始种群P0。并对P0进行非支配排序,初始化每个个体的rank值。
(2). t = 0
(3).通过二进制锦标赛法从Pt选择个体,并进行交叉和变异操作,产生新一代种群Qt。
(4).通过合并Pt 和 Qt 产生出组合种群Rt = Pt UQt 。
(5).对Rt进行非支配排序,并通过排挤和精英保留策略选出N个个体,组成新一代种群Pt+1。
(6).跳转到步骤3,并循环,直至满足结束条件。
步骤5的具体操作可见"A fast and elitist multiobjective genetic algorithm: NSGA-II"
伪代码如下:
Rt = Pt + Qt
F = fast_nondominate_sort( Rt )
Pt + 1 = [ ]
i = 0
while len(Pt + 1 ) + len( F[i] ) < N:
crowding_distance_assignment( F[i] )
Pt + 1 += F[i]
i += 1
Pt + 1 += F[i][0:N - len(Pt + 1 )]
Qt + 1 = make_new_generation( Pt + 1 )
t = t + 1
下面分析NSAG2算法的整体复杂度,以下为该算法中的基本操作和其最差复杂度:
(1).非支配排序,最差复杂度为O(M(2N)2)。
(2).拥挤距离估算赋值,最差复杂度为O(M(2N)log(2N))。
(3).拥挤操作排序,最差复杂度为O(2Nlog(2N))。
浙公网安备 33010602011771号