python拓展包之pymoo使用方法:多目标优化(NSGA2)

一、pymoo的安装

pip安装

pip install -U pymoo

二、多目标优化的一般模式

一般来说,多目标优化具有几个受不等式和等式约束的目标函数。其目标是找到一组满足所有约束条件并尽可能好地处理其所有目标值的解决方案。问题的一般形式的定义为:
在这里插入图片描述
目标函数f(x)
不等式约束g(x)
等式约束和h(x)
变量x的上下约束

在下面,我们说明了一个具有两个约束条件的双目标优化问题。

在这里插入图片描述
它的可视化图像如下:

在这里插入图片描述
可以看到,它的最优解在(图中橙色区域)在这里插入图片描述
下面我们在python中使用pymoo来实现上述问题公式。

三、pymoo处理多目标优化问题的格式

一、pymoo支能够处理目标函数最小化的优化问题

然而,在不失去一般性的情况下,一个应该最大化的目标可以乘以−1并最小化。
在上述优化问题中,我们需要将目标函数
max f2(x)
转化为
min -f2(x)
此外,所有的约束函数都需要表述为一个小于等于的约束。
我们需要将约束条件
g2(x)>=0
转化为
-g2(x)<=0
我们建议将约束标准化,使它们都同等重视。将约束条件的每一个因式的常数部分相乘得到一个约束常量,
对于g1(x),约束常量为 2 ⋅ (−0.1) ⋅(−0.9) = 0.18
对于g2(x),约束常量为 20 ⋅ (−0.4) ⋅ (−0.6) = 4.8
最后,将使用pymoo进行优化的优化问题定义为:

pymoo的目标函数及约束

四、python中pymoo的使用

接下来,用Python实现该优化问题。pymoo中的每个优化问题都必须从Problem类中继承。
首先,通过调用super()函数,可以初始化问题属性。

from pymoo.model.problem import Problem
class MyProblem(Problem):
    def __init__(self,cost_matrix: list, ):
        self.cost_matrix = cost_matrix
        super().__init__(n_var=2,   # 变量数
                         n_obj=2,   # 目标数
                         n_constr=2,    # 约束数
                         xl=np.array([-2, -2]),     # 变量下界
                         xu=np.array([2, 2]),   # 变量上界
                         )

    def _evaluate(self, x, out, *args, **kwargs):

        # 定义目标函数
        f1 = x[:, 0]**2 + x[:, 1]**2    # x1放在x的第0列,x2放在x的第一列
        f2 = (x[:, 0] - 1)**2 + x[:, 1]**2
        # 定义约束条件
        g1 = 2*(x[:, 0] - 0.1) * (x[:, 0] - 0.9) / 0.18
        g2 = -20*(x[:, 0] - 0.4) * (x[:, 0] - 0.6) / 4.8
        # todo
        out["F"] = np.column_stack([f1, f2])
        out["G"] = np.column_stack([g1, g2])

super初始化中
变量数(n_var)
目标(n_obj)
约束(n_constr)
此外,下(xl)和上变量边界(xu)作为NumPy数组提供。


_evaluate函数中
定义目标函数以键“F”添加到字典中
定义约束条件以键“G”添加到字典中

五、选择优化算法

在pymoo中,需要创建一个算法对象来进行优化。对于每种算法,都有API文档,通过提供不同的参数,可以以即插即用的方式定制算法。一般来说,选择一个合适的优化问题的算法本身就是一个挑战。当事先知道问题特征时,我们建议通过定制操作符使用这些特征。然而,在我们的情况下,优化问题相当简单,但应该考虑有两个目标和两个约束的方面。因此,我们决定使用NSGA-II[12]及其默认配置,并进行少量修改。我们选择了40人的人口规模,但我们没有产生相同数量的后代,而是每一代只创造10个后代。这是NSGA-II的一个稳态变体,对于比较简单的优化问题,可以提高收敛性,存在局部帕雷托前沿。此外,我们启用了一个重复的检查,以确保交配产生的后代,以及与现有种群关于其可变向量的不同。
使用所提供的参数调用NSGA2的构造函数并返回一个初始化的算法对象。

from pymoo.algorithms.nsga2 import NSGA2
from pymoo.factory import get_sampling, get_crossover, get_mutation
from pymoo.optimize import minimize
from example import MyProblem

# 定义遗传算法
algorithm = NSGA2(
    pop_size=40,
    n_offsprings=10,
    sampling=get_sampling("real_random"),
    crossover=get_crossover("real_sbx", prob=0.9, eta=15),
    mutation=get_mutation("real_pm", eta=20),
    eliminate_duplicates=True
)

接下来,我们使用初始化的算法对象来优化所定义的问题。因此,将具有实例问题和算法的最小化函数作为参数。此外,我们提供了运行40代算法的终止标准,这将导致40个+40×10=440函数评估。此外,我们定义了一个随机种子,以确保重现性,并使冗长标志能够看到每一代的打印输出。该方法返回一个结果对象,其中包含该算法找到的非支配解集。

res = minimize(MyProblem(),
               algorithm,
               ('n_gen', 40),
               seed=1,
               verbose=True
               )

打印输出

D:\Soft\Anaconda3\envs\datadeal\python.exe D:/WorkSpace/pymooto/alg_example.py
=====================================================================================
n_gen |  n_eval |   cv (min)   |   cv (avg)   |  n_nds  |     eps      |  indicator  
=====================================================================================
    1 |      40 |  0.00000E+00 |  2.36399E+01 |       1 |            - |            -
    2 |      50 |  0.00000E+00 |  1.15486E+01 |       1 |  0.00000E+00 |            f
    3 |      60 |  0.00000E+00 |  5.277918607 |       1 |  0.00000E+00 |            f
    4 |      70 |  0.00000E+00 |  2.406068542 |       2 |  1.000000000 |        ideal
    5 |      80 |  0.00000E+00 |  0.908316880 |       3 |  0.869706146 |        ideal
    6 |      90 |  0.00000E+00 |  0.264746300 |       3 |  0.00000E+00 |            f
    7 |     100 |  0.00000E+00 |  0.054063822 |       4 |  0.023775686 |        ideal
    8 |     110 |  0.00000E+00 |  0.003060876 |       5 |  0.127815454 |        ideal
    9 |     120 |  0.00000E+00 |  0.00000E+00 |       6 |  0.004633441 |        ideal
   10 |     130 |  0.00000E+00 |  0.00000E+00 |       6 |  0.062649485 |        nadir
   11 |     140 |  0.00000E+00 |  0.00000E+00 |       7 |  0.026769546 |            f
   12 |     150 |  0.00000E+00 |  0.00000E+00 |       7 |  0.047566009 |            f
   13 |     160 |  0.00000E+00 |  0.00000E+00 |       7 |  0.000678729 |            f
   14 |     170 |  0.00000E+00 |  0.00000E+00 |       9 |  0.043888006 |        ideal
   15 |     180 |  0.00000E+00 |  0.00000E+00 |      10 |  0.013506283 |            f
   16 |     190 |  0.00000E+00 |  0.00000E+00 |      11 |  0.052719639 |        ideal
   17 |     200 |  0.00000E+00 |  0.00000E+00 |      14 |  0.008531768 |            f
   18 |     210 |  0.00000E+00 |  0.00000E+00 |      16 |  0.011165361 |            f
   19 |     220 |  0.00000E+00 |  0.00000E+00 |      18 |  0.004040787 |            f
   20 |     230 |  0.00000E+00 |  0.00000E+00 |      20 |  0.001296614 |            f
   21 |     240 |  0.00000E+00 |  0.00000E+00 |      22 |  0.000911500 |            f
   22 |     250 |  0.00000E+00 |  0.00000E+00 |      24 |  0.003461153 |        nadir
   23 |     260 |  0.00000E+00 |  0.00000E+00 |      27 |  0.004261571 |        ideal
   24 |     270 |  0.00000E+00 |  0.00000E+00 |      28 |  0.029927769 |        nadir
   25 |     280 |  0.00000E+00 |  0.00000E+00 |      28 |  0.001150567 |            f
   26 |     290 |  0.00000E+00 |  0.00000E+00 |      30 |  0.002181257 |            f
   27 |     300 |  0.00000E+00 |  0.00000E+00 |      33 |  0.006887739 |        nadir
   28 |     310 |  0.00000E+00 |  0.00000E+00 |      36 |  0.001237981 |            f
   29 |     320 |  0.00000E+00 |  0.00000E+00 |      37 |  0.000102543 |            f
   30 |     330 |  0.00000E+00 |  0.00000E+00 |      38 |  0.000747546 |            f
   31 |     340 |  0.00000E+00 |  0.00000E+00 |      40 |  0.005157126 |        nadir
   32 |     350 |  0.00000E+00 |  0.00000E+00 |      40 |  0.00000E+00 |            f
   33 |     360 |  0.00000E+00 |  0.00000E+00 |      40 |  0.002321697 |            f
   34 |     370 |  0.00000E+00 |  0.00000E+00 |      40 |  0.016674348 |        nadir
   35 |     380 |  0.00000E+00 |  0.00000E+00 |      40 |  0.000760584 |            f
   36 |     390 |  0.00000E+00 |  0.00000E+00 |      40 |  0.016011922 |        nadir
   37 |     400 |  0.00000E+00 |  0.00000E+00 |      40 |  0.000333129 |            f
   38 |     410 |  0.00000E+00 |  0.00000E+00 |      40 |  0.000980877 |            f
   39 |     420 |  0.00000E+00 |  0.00000E+00 |      40 |  0.001264690 |            f
   40 |     430 |  0.00000E+00 |  0.00000E+00 |      40 |  0.001571863 |            f

关于pymoo的中文使用教程很少,本文内容大都翻译自pymoo的官方使用说明。

参考资料

pymoo: Multi-objective Optimization in Python

  • 31
    点赞
  • 223
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 26
    评论
评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橘蓝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值