多任务多目标优化是近年来研究的热点。然而,Pymoo似乎还不支持这种优化范式。因此,在本文中,我打算在Pymoo中实现这个范式。实际上,多任务优化算法还是比较新的领域。总的来说,目前还不清楚哪种算法普遍优于其他算法。根据我目前的知识,[1][2][3]是一些应该考虑的有趣的论文。
在本文中,我将尝试实现一个通用的模板代码,用于在Pymoo中嵌入自定义的多任务策略,而不是实现一个特定的多任务进化算法。
首先,请允许我解释一下我的想法。由于多任务进化优化算法的基本思想是在群体之间交换信息以帮助解决问题,因此我们需要设计一种方法来允许不同的群体在进化过程中进行通信,这并不是一个容易解决的问题,因为许多现有的进化优化框架已经封装了进化过程。因此,在大多数情况下,我们必须修改大量的代码,以维持每个群体的状态,并在他们之间交换信息。
幸运的是,在Python中,有一种神奇的方法来实现这个功能,即迭代器。因此,在下面的文章中,我将尝试将传统的进化算法转换为生成器模式。更具体地说,通过这样做,我们可以显式地指示进化算法在每轮函数调用时执行一次进化迭代。因此,我们可以在每次迭代后,在不同种群之间手动交换信息。
为了演示我的想法,清晰起见,我选择了Pymoo框架。尽管如此,我相信这个概念可以应用于其他框架。首先,我们必须定义我们的算法类。在本文中,我们将尝试将NSGA2算法转换为生成器模式。原始NSGA2类中的大多数函数都可以直接继承。接下来,我们需要定义两个函数来实现我们的目标。事实上,一旦我们对Python的生成器机制有了基本的了解,就相当简单了。在Python中调用“yield”关键字时,我们知道它将保存当前状态并返回到上层函数。更重要的是,一旦我们完成了修改,我们就可以简单地调用“next”函数返回到先前的状态。因此,利用这种机制,我们可以很容易地将我们的多任务优化机制与传统的优化算法结合起来。
import time
from pymoo.algorithms.nsga2 import NSGA2
from pymoo.factory import get_problem
from pymoo.model.result import Result
from pymoo.optimize import minimize
from pymoo.visualization.scatter import Scatter
class NSGA2MultiTask(NSGA2):
def solve(self):
# the result object to be finally returned
res = Result()
# set the timer in the beginning of the call
res.start_time = time.time()
# call the algorithm to solve the problem
self.iterator = self._solve(self.problem)
next(self.iterator)
# create the result object based on the current iteration
res = self.result()
return res
def _solve(self, problem):
# the termination criteria should be set
if self.termination is None:
raise Exception("No termination criterion defined and algorithm has no default termination implemented!")
# when the termination criterion is not fulfilled
while self.has_next():
self.next()
yield
yield "Terminate"
在生成器模式中重新定义了NSGA2类之后,我编写了一些代码来测试它。我将在下面的代码中对两个著名的多目标基准问题ZDT1和ZDT2进行测试。我们可以在实例化对象之后从对象中获取生成器,并迭代地调用这些生成器。最后,当我们遇到一个“终止”信号时,我们可以结束迭代并绘制结果。
if __name__ == '__main__':
# define problems
algorithms = []
problems = []
problem_names = ['zdt1', 'zdt2']
for p in problem_names:
problem = get_problem(p)
problems.append(problem)
algorithm = NSGA2MultiTask(pop_size=500)
algorithms.append(algorithm)
# obtain iterators
iterators = []
for problem, algorithm in zip(problems, algorithms):
minimize(problem, algorithm, termination=('n_gen', 50), copy_algorithm=False)
iterator = algorithm.iterator
iterators.append(iterator)
# perform evolutionary operations iteratively
while len(iterators) > 0:
iterator = iterators.pop(0)
r = next(iterator)
if r != 'Terminate':
iterators.append(iterator)
for i, problem, algorithm in zip(range(0, len(problems)), problems, algorithms):
res = algorithm.result()
plot = Scatter(title=problem_names[i])
plot.add(problem.pareto_front(), plot_type="line", color="black", alpha=0.7)
plot.add(res.F, color="red")
plot.show()
最后,总的来说,在本文中我们没有实现一个完整的多任务优化算法,而是实现了几行模板代码来嵌入任何可能的多任务优化策略。虽然这可能不是最好的解决方案,但它简单明了。我希望这样直观的解决方案将能鼓励更多有前途的工作出现在进化计算领域。
参考资料:
[1]. Gupta, Abhishek, Yew-Soon Ong, and Liang Feng. “Multifactorial evolution: toward evolutionary multitasking.” IEEE Transactions on Evolutionary Computation 20.3 (2015): 343-357.
[2]. Chen, Yongliang, et al. “An adaptive archive-based evolutionary framework for many-task optimization.” IEEE Transactions on Emerging Topics in Computational Intelligence (2019).
[3]. Lin, Jiabin, et al. “Multi-objective Multi-tasking Optimization Based on Incremental Learning.” IEEE Transactions on Evolutionary Computation (2019).