NSGA-II 遗传多目标算法(python示例)

一、前言

        最近在准备毕业论文,研究了一下主流的多目标算法,对于NSGA-II,网上大部分代码是全部是面向过程来实现的,本人更喜欢采用面向对象的方式,故采用python面向对象实现了一个示例,实现了对于二元多目标问题的求解。

二、算法基本流程

三、核心思想

1、非支配排序

这个简单的例子说明了帕累托最优的概念。上面我们有4个成员A, B, C和D,有两个特征:身高和工资。现在,如果我们同时比较他们的身高和薪水,我们会发现这不是很直观,因为他们有多个目标。

既然这两个目标越大越好,我们可以简单地对它们进行比较。首先,我们观察到A和B都比C和D多,所以我们说A和B在身高和薪水上“支配”C和D。同理,C支配D,D可被A,B,C支配。

A和B呢?A比B高,但是工资低。相反,B面临着同样的情况。我们称这种情况为“非支配”。 如果我们能找到一组解它们不互相支配,也不受其他解支配,我们称之为"帕累托最优"解。在上面的例子中,A和B都在帕累托最优前沿

几个概念:

非支配解:假设任何二解S1 及S2 对所有目标而言,S1均优于S2,则我们称S1 支配S2,若S1 的解没有被其他解所支配,则S1 称为非支配解(不受支配解),也称Pareto解(帕雷托解)

支配解:若解S2的所有目标均劣于S1,则称S1优于S2,也称S1支配S2,S2为受支配解。

Pareto前沿面:找到所有Pareto解之后,这些解组成的平面叫做Pareto前沿面(Non-dominated front)。在目标函数较多时,前沿面通常为超曲面。

2、拥挤度

通俗的来讲,当需要舍弃某一rank平面的部分节点时,由于同一平面中的所有节点rank相同,不能通过rank来舍弃,而是要通过拥挤度来舍弃,以上就是拥挤度的作用。

算法更倾向于稀疏的点,也就是让节点更可能的分散,可以有效地方式早熟和过拟合现象

3、精英选择策略

每次都将父类与子类想结合,依次采用非支配排序、计算拥挤度来选择父代。

四、python实现

github:   源代码地址

"""
author: pym
time: 2023.10.29
ide: pycharm2
"""from collections import defaultdict
import numpy as np
import random
import matplotlib.pyplot as plt
import mathclass Individual(object):def __init__(self):self.solution = None    # 实际为nparray类型,方便四则运算self.objective = defaultdict()self.n = 0              # 解p被几个解支配self.rank = 0           # 解p所在层数self.S = []             # 解p支配解的集合self.distance = 0       # 拥挤度距离def bound_process(self, bound_min, bound_max):"""对解向量 solution 中的每个分量进行定义域判断;超过最大值赋为最大值:param bound_min: 定义域下限:param bound_max: 定义域上限:return:"""for i, item in enumerate(self.solution):if item > bound_max:self.solution[i] = bound_maxelif item < bound_min:self.solution[i] = bound_mindef calculate_objective(self, objective_fun):"""计算目标值:param objective_fun: 目标函数:return:"""self.objective = objective_fun(self.solution)def __lt__(self, other):"""重载小于号,只有当solution中全部小于对方,才判断小于:param other: 比较的个体:return: 1:小于 0:大于"""v1 = list(self.objective.values())v2 = list(other.objective.values())for i in range(len(v1)):if v1[i] > v2[i]:return 0return 1def fast_non_dominated_sort(P):"""非支配排序:param P: 种群P:return: F:分层结果,返回值类型为dict,键为层号,值为list(该层中的个体)"""F = defaultdict(list)for p in P:p.S = []p.n = 0for q in P:if p < q:       # p支配qp.S.append(q)elif q < p:     # q支配pp.n += 1if p.n == 0:p.rank = 1F[1].append(p)i = 1while F[i]:Q = []for p in F[i]:for q in p.S:q.n -= 1if q.n == 0:q.rank = i + 1Q.append(q)i += 1F[i] = Qreturn Fdef crowding_distance_assignment(L):"""计算拥挤度:param L: F[i],是个list,为第i层的节点集合:return:"""l = len(L)# 初始化距离for i in range(l):L[i].distance = 0# 遍历每个目标方向(有几个优化目标,就有几个目标方向)for m in L[0].objective.keys():L.sort(key=lambda x: x.objective[m])    # 使用objective值排序L[0].distance = float('inf')L[l - 1].distance = float('inf')f_max = L[l - 1].objective[m]f_min = L[0].objective[m]# 当某一个目标方向上的最大值和最小值相同时,会出现除0错误try:for i in range(1, l - 1):L[i].distance = L[i].distance + (L[i + 1].objective[m] - L[i - 1].objective[m]) / (f_max - f_min)except Exception:print(str(m) + "目标方向上,最大值为:" + str(f_max) + " 最小值为:" + str(f_min))def binary_tornament(ind1, ind2):"""二元锦标赛:先选非支配排序靠前的,再选拥挤度低(即距离远);如果都不行,则随机:param ind1: 个体1:param ind2: 个体1:return: 返回较优的个体"""if ind1.rank != ind2.rank:return ind1 if ind1.rank < ind2.rank else ind2elif ind1.distance != ind2.distance:return ind1 if ind1.distance > ind2.distance else ind2else:return ind1def crossover_mutation(parent1, parent2, eta, bound_min, bound_max, objective_fun):"""交叉:二进制交叉算子(SBX),变异:多项式变异(PM):param parent1: 父代1:param parent2: 父代2:param eta: 变异参数,越大则后代个体越逼近父代:return:"""poplength = len(parent1.solution)   # 解向量维数# 初始化两个后代个体offspring1 = Individual()offspring2 = Individual()offspring1.solution = np.empty(poplength)offspring2.solution = np.empty(poplength)# 二进制交叉for i in range(poplength):rand = random.random()if rand < 0.5:beta = (rand * 2) ** (1 / (eta + 1))else:beta = (1 / (2 * (1 - rand)))**(1 / (eta + 1))offspring1.solution[i] = 0.5 * ((1 + beta) * parent1.solution[i] + (1 - beta) * parent2.solution[i])offspring2.solution[i] = 0.5 * ((1 - beta) * parent1.solution[i] + (1 + beta) * parent2.solution[i])# 多项式变异for i in range(poplength):mu = random.random()if mu < 0.5:delta = 2 * mu ** (1 / (eta + 1))else:delta = (1 - (2 * (1 - mu)) ** (1 / (eta + 1)))# 只变异一个offspring1.solution[i] = offspring1.solution[i] + deltaoffspring1.bound_process(bound_min, bound_max)offspring2.bound_process(bound_min, bound_max)offspring1.calculate_objective(objective_fun)offspring2.calculate_objective(objective_fun)return [offspring1, offspring2]def make_new_pop(P, eta, bound_min, bound_max, objective_fun):"""选择交叉变异获得新后代:param P: 父代种群:param eta: 变异参数,越大则后代个体越逼近父代:param bound_min: 定义域下限:param bound_max: 定义域上限:param objective_fun: 目标函数:return: 子代种群"""popnum = len(P)     # 种群个数Q = []# 二元锦标赛选择for i in range(int(popnum / 2)):# 从种群中随机选择两个个体,进行二元锦标赛,选择一个parenti = random.randint(0, popnum - 1)j = random.randint(0, popnum - 1)parent1 = binary_tornament(P[i], P[j])parent2 = parent1while (parent1.solution == parent2.solution).all():     # 小细节alli = random.randint(0, popnum - 1)j = random.randint(0, popnum - 1)parent2 = binary_tornament(P[i], P[j])Two_offspring = crossover_mutation(parent1, parent2, eta, bound_min, bound_max, objective_fun)Q.append(Two_offspring[0])Q.append(Two_offspring[1])return Qdef KUR(x):"""计算各个目标方向上的目标值:param x: 解向量:return: 字典:各个方向上的目标值(key:目标方向;value:目标值)"""f = defaultdict(float)poplength = len(x)f[1] = 0f[2] = 0for i in range(poplength - 1):f[1] = f[1] + (-10) * math.exp((-0.2) * (x[i] ** 2 + x[i + 1] ** 2) ** 0.5)for i in range(poplength):f[2] = f[2] + abs(x[i]) ** 0.8 + 5 * math.sin(x[i] ** 3)return fdef plot_P(P):"""给种群绘图:param P: 种群集合:return:"""X = []Y = []for ind in P:X.append(ind.objective[1])Y.append(ind.objective[2])plt.xlabel('F1')plt.ylabel('F2')plt.scatter(X, Y)def main():# 初始化参数generations = 250   # 迭代次数popnum = 100        # 种群大小eta = 1             # 变异分布参数poplength = 3       # 单个个体解向量的维数bound_min = -5bound_max = 5objective_fun = KUR# 生成第一代种群P = []for i in range(popnum):P.append(Individual())P[i].solution = np.random.rand(poplength) * (bound_max - bound_min) + bound_minP[i].bound_process(bound_min, bound_max)    # 越界处理P[i].calculate_objective(objective_fun)     # 计算目标值# 快速非支配排序fast_non_dominated_sort(P)Q = make_new_pop(P, eta, bound_min, bound_max, objective_fun)P_t = P     # 当前这一代的父代种群Q_t = Q     # 当前这一代的子代种群for gen_cur in range(generations):R_t = P_t + Q_tF = fast_non_dominated_sort(R_t)P_n = []    # 即为P_t+1,表示下一代的父代i = 1# 依次将最高级别的支配平面中的节点放入到P_n中,之后更新非支配,直到达到要求的规模while len(P_n) + len(F[i]) < popnum:crowding_distance_assignment(F[i])P_n += F[i]i += 1# 按照支配排序选完之后,再按照拥挤度来选择F[i].sort(key=lambda x: x.distance)P_n = P_n + F[i][:popnum - len(P_n)]Q_n = make_new_pop(P_n, eta, bound_min, bound_max, objective_fun)# 将下一届的父代和子代成为当前的父代和子代P_t = P_nQ_t = Q_n# 可视化plt.clf()plt.title("current generation: " + str(gen_cur + 1))plot_P(P_t)plt.pause(0.1)plt.show()return 0if __name__ == "__main__":main()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/175305.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

iOS iGameGuardian修改器检测方案

一直以来&#xff0c;iOS 系统的安全性、稳定性都是其与安卓竞争的主力卖点。这要归功于 iOS 系统独特的闭源生态&#xff0c;应用软件上架会经过严格审核与测试。所以&#xff0c;iOS端的作弊手段&#xff0c;总是在尝试绕过 App Store 的审查。 常见的 iOS 游戏作弊&#xf…

jenkins工具系列 —— 删除Jenkins JOB后清理workspace

文章目录 问题现象分析解决思路脚本实现问题现象分析 Jenkins使用过程中,占用空间最大的两个位置: 1 、workspace: 工作空间,可以随便删除,删除后再次构建时间可能会比较长,因为要重新获取一些资源。 2 、job: 存放的是项目的配置、构建结果、日志等。不建议手动删除,…

深度学习_2 数据操作

数据操作 机器学习包括的核心组件有&#xff1a; 可以用来学习的数据&#xff08;data&#xff09;&#xff1b;如何转换数据的模型&#xff08;model&#xff09;&#xff1b;一个目标函数&#xff08;objective function&#xff09;&#xff0c;用来量化模型的有效性&…

如何在Instagram和kol展开合作

网红营销已经演变成一个由品牌、MCN机构、红人和消费者组成的复杂生态系统&#xff0c;并在某种程度上重新定义了当今社交媒体时代营销和广告的本质。在这个情况下&#xff0c;品牌找红人进行营销推广已经成为大势&#xff0c;而最能体现网红营销发展的莫过于Instagram这个平台…

黑豹程序员-架构师学习路线图-百科:jMeter并发测试计划

我们开发一个软件系统&#xff0c;为了保证代码的正确&#xff0c;我们需要测试。测试日常包括&#xff1a;单元测试、功能测试、集成测试、压力测试、回归测试。 Apache JMeter 是 Apache 组织基于 Java 开发的压力测试工具&#xff0c;用于对软件做压力测试。 JMeter 最初被…

抖音上怎么挂小程序?制作小程序挂载抖音视频

公司企业商家现在已经把抖音作为营销的渠道之一&#xff0c;目前抖音支持短视频挂载小程序&#xff0c;可方便做营销。以下给大家分享这一操作流程。 一、申请自主挂载能力 首先需要在抖音开放平台官网注册一个抖音小程序账号&#xff0c;然后申请短视频自主挂载能力。 二、搭…

【ROS教程demo】用C++创建一个ROS节点,发布指令使得小海龟做圆周运动

ROS创建节点发布命令使得小海龟做圆周运动 1.任务需求2.任务分析2.1发布方topic和msg2.2接收方topic和msg2.3目标明确!3.创建ROS节点3.1创建发布方节点pub_pose3.2创建订阅方节点sub_pose1.任务需求 创建一个节点,在其中实现一个订阅者和一个发布者,完成以下功能: 发布者:…

2.预备知识-2简化版

#pic_center R 1 R_1 R1​ R 2 R^2 R2 目录 知识框架No.1 数据操作数据预处理一、N维数组样例二、创建数组三、访问元素四、数据操作D2L注意点五、数据预处理六、D2L注意点七、QA No.2 线性代数一、标量二、向量1、基本操作2、空间表示3、乘法 三、矩阵1、基本操作2、乘法3、空…

一百九十七、Java——IDEA项目中把多层文件夹拆开显示

一、目的 由于IDEA项目中&#xff0c;默认的是把文件夹连在一起显示&#xff0c;于是为了方便需要把这些连在一起的文件夹拆开&#xff0c;分层显示 如文件夹cn.kgc 二、解决措施 解决方法很简单 &#xff08;一&#xff09;找到IDEA项目上的小齿轮 &#xff08;二&#xf…

springboot的spring.jackson.date-format失效解决

看起来数据库的格式非常完美,但是数据库字段look_date 是 datetime类型,java里没有datetime类型,这样一来如果你不在后端做处理,那么模型属性Date来接收一定会出问题.我通过实验证明最后拿到的是一个时间戳. 第一 解决时间格式问题 1.可以通过application.propertis配置文件中…

Ubuntu 内核降级到指定版本

reference https://www.cnblogs.com/leebri/p/16786685.html 前往此网站&#xff0c;找到所需的内核 https://kernel.ubuntu.com/~kernel-ppa/mainline/ 查看系统架构 dpkg --print-architecture 二、下载安装包 注意&#xff1a;下载除lowlatency以外的deb包 三、安装内核 3…

python excel接口自动化测试框架

前言 前些天写了pytestyamlallure接口自动化测试框架这篇文章。 今天采用Excel继续写一个接口自动化测试框架。 设计流程图 这张图是我的excel接口测试框架的一些设计思路。 首先读取excel文件&#xff0c;得到测试信息&#xff0c;然后通过封装的requests方法&#xff0c…

吴恩达《机器学习》1-3:监督学习

一、监督学习 例如房屋价格的数据集。在监督学习中&#xff0c;我们将已知的房价作为"正确答案"&#xff0c;并将这些价格与房屋的特征数据一起提供给学习算法。学习算法使用这些已知答案的数据来学习模式和关系&#xff0c;以便在未知情况下预测其他房屋的价格。这就…

SurfaceFliger与Vsync信号如何建立链接?

Vsync信号上报流程 Vsync的注册函数&#xff0c;来临时会回调HWComposer的hook_VSYNC方法&#xff0c;接着调用到vsync方法中 大致流程梳理&#xff1a; 该方法会通知给SurfaceFliger的onVsyncReceived方法&#xff0c;接着调用DispSync的addResyncSample方法。 DispSyncThr…

MA网络下,静态路由仅配出接口,不配下一跳是否可行

在MA网络模式下&#xff0c;静态路由只配置出接口&#xff0c;不配置下一跳地址是否可行 如下拓扑图&#xff1a; 如图所示&#xff0c;在R1上配置一条去往4.4.4.4的静态路由&#xff0c;此时如果静态路由只配置出接口&#xff0c;不配置下一跳地址&#xff1a; ip route-stat…

Hi3516DV500部署paddle版型分析模型记录

原版模型测试并导出onnx paddle 版面分析-> https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.7/ppstructure/layout/README_ch.md 测试 python3 deploy/python/infer.py \ --model_dirmodel/picodet_lcnet_x1_0_fgd_layout_cdla_infer/ \ --image_fil…

Day 4 登录页及路由 (二) -- Vue状态管理

状态管理 之前的实现中&#xff0c;判断登录状态用了伪实现&#xff0c;实际当中&#xff0c;应该是以缓存中的数据为依据来进行的。这就涉及到了应用程序中的状态管理。在Vue中&#xff0c;状态管理之前是Vuex&#xff0c;现在则是推荐使用Pinia&#xff0c;在脚手架项目创建…

渗透测试-Fastjson反序列化漏洞getshell

目录 前言 测试环境准备 dnslog测试 搭建rmi服务器&准备恶意类 引用JdbcRowSetImpl攻击 反弹shell$命令执行 总结 关键字&#xff1a;fastjson 1.2.24反序列化导致任意命令执行漏洞 注&#xff1a;本次渗透测试全在虚拟机中进行仅用于学习交流&#xff0c;请勿在实…

Visual Studio(VS)C++项目 管理第三方依赖库和目录设置

发现很多程序员存在这种做法&#xff1a;把项目依赖的第三方库的lib和dll放在项目目录下&#xff0c;或者复制到输出目录&#xff0c;因为每种配置都有不同的输出目录&#xff0c;所以要复制多份&#xff08;至少包括Debug和Release两个输出目录&#xff09;&#xff0c;这些做…

Mac电脑配置Dart编程环境

1.安装Dart SDK 官网地址&#xff1a;https://dart.dev/get-dart $brew tap dart-lang/dart$brew install dart 安装后&#xff0c;用命令检测一下是否安装正常。 $brew info dart 2.VS Code配置Dart环境 1).安装VS Code 官网地址&#xff1a;https://code.visualstudio.c…