进化算法、遗传编程和学习

404 阅读7分钟

image.png

进化算法是一个搜索算法家族,其灵感来自于大自然中的(达尔文)进化过程。
所有不同家族成员的共同点是,通过应用受自然遗传学和自然选择启发的
算子,通过进化最初的随机候选解决方案群体来解决问题,从而在
,出现更合适(即更好)的问题解决方案。

这个领域的起源可以追溯到20世纪50年代和60年代,在过去的20年里,它已经形成了自己的风格,在解决高度多样化领域的许多问题方面证明是成功的,包括(仅举几例):优化、自动编程、电子电路设计、电信、网络、金融、经济、图像分析、信号处理、音乐和艺术。

有趣的是,研究人员--包括我自己--已经发现进化算法可以与机器学习和深度学习相结合,并从中受益。稍后会有更多关于这方面的内容。

下面是一个 基本的进化算法的样子:

  1. 产生一个初始的个体群体 ,这些个体是手头问题的候选解决方案
  2. 根据寻求解决方案的问题,评估每个个体的适应性
  3. 如果 不满足终止条件*,则
    *-选择 更合适的个体进行繁殖
    -重组 (交叉)个体
    -变异 个体
    -评估 改良个体的适配性

让我们总结一下进化算法的主要成分:

基因组(染色体)。进化算法本质上是基于群体的。群体中的一个个体被称为基因组,或染色体。它可以采取多种形式,包括比特串、实值向量、基于字符的编码、计算机程序等等。设计一个适合手头问题的表示法对进化算法的成功至关重要。

健身,或健身函数。衡量群体中候选解决方案的质量。定义好这个函数对进化算法的成功也很关键。

生成。上述while 循环的一次迭代。

选择。进化算法选择(通常是概率性的)更适合的个体来为下一代贡献遗传(嗯,"遗传")材料的操作者。

交叉。两个主要的遗传 算子之一,其中两个(或多个)候选方案(父母)以某种预先定义的方式结合,形成后代。

变异。第二个主要的遗传操作符,其中一个候选方案被随机改变。

是时候举个简单的例子了。让我们考虑一个由4个个体组成的群体,它们是长度为10的比特串(基因组)。健身值等于
,即比特串中1的数量。在实际应用中,种群大小和基因组长度当然会更大。

这种情况下的适配度计算非常简单:只需计算个体中1的数量。对于现实世界的问题,我们常常需要进行一些繁重的计算来获得适配度。

最初的随机种群可能是这样的(括号里是健身值):0000011011 (4), 1110111101 (8), 0010000010 (2), 0011010000 (3).

然后选择可能会选择:1110111101(8)与0011010000(3),以及0000011011(4)与1110111101(8)作为亲本配对。请注意,有些个体被选择的次数比其他个体多,而有些个体可能根本就没有被选择--选择是概率性的,它取决于适配性。健身性越高,被选为父本的概率就越高。

交叉操作在一对亲本之间交换随机块,然后是突变操作,随机翻转少量的比特。

一旦我们完成了选择-交叉-突变,我们就得到了一个新的世代。在我们的例子中,它可能看起来像这样:1111010000 (5), 0010101101 (5), 0000011011 (4), 1110111111 (9).是的,这个父代的一点,那个父代的一点,再加上一点改动,然后就有了--一个改进的解决方案,其适配度为9(而之前最好的是8)。

现在怎么办?只是不断地循环代数--选择--交叉--变异--健身--直到你得到一个足够好的解决方案。甚至可能 最佳方案。

遗传编程。现在让我们把事情变得更有趣。为什么要进化简单的比特串?进化算法中的一个主要子领域被称为遗传编程,其重点是使用更复杂的表示法。传统上,这些都是计算树,但多年来已经提出了许多其他表示方法。

一个计算树看起来像这样:

image.png

我通过遗传编程进化了 这棵树 ,它实际上是在计算(递归)等价的数学表达式:x⁴ + x³ + x² + x + 1。有时,进化会产生更复杂的树,比如说:

image.png

机器学习和深度学习。正如我和其他人在过去几年中发现的那样,进化算法的主要优势之一是它们在机器学习和深度学习中的 "发挥 "程度--如果明智地使用的话。

例如,在机器学习的环境中,我设计了一些基于进化的分类器,它们与XGBoost、LightGBM和一个深度神经网络竞争。以下是论文全文

在深度学习环境中,我们使用了一种所谓的协同进化 算法,即多个种群串联进化,来进化深度网络的激活函数。我们没有使用标准的ReLU、sigmoid等,而是将进化的激活函数插入到深度网络中,并显示其性能有所提高。以下是论文全文

对抗性深度学习领域,研究人员调查了深度模型对攻击的脆弱性,既试图改善模型的防御,又试图设计新的攻击。输入图像的微小变化,我们无法察觉,会导致网络出错。

在一项工作中,我们使用进化论来生成物理上合理的对抗性补丁,这些补丁性能良好且看起来很真实--不需要使用梯度。我们使用了GAN(生成式对抗网络)生成器。给定一个预训练的生成器,我们寻找一个输入的潜在向量,对应于一个导致物体检测器出错的生成图像。我们利用潜伏空间的(相对)小维度,使用进化策略算法接近梯度,通过查询目标物体检测器反复更新输入潜伏向量,直到发现一个合适的对抗补丁。

下面见证了我的天才研究生Raz Lapid站在他的另一半身边,展示了进化的补丁(印刷的,也就是物理的)如何将他从深度学习模型中隐藏起来(没有边界框)。完整的论文在这里。

image.png

进化算法的入门有多难? 好吧,我会从那里的许多优秀软件包中选择一个开始。毫不掩饰地说,我想推荐我发起的项目--与我优秀的合作者和研究生一起--EC-KitY

我们对这个项目有多个目标,因此EC-KitY是:

  • 一个运行进化算法的综合工具箱;
  • 用Python编写;
  • 可以和scikit-learn一起工作,也可以不和scikit-learn一起工作,也就是说,它同时支持sklearn和非sklearn模式;
  • 设计时考虑到了现代软件工程;
  • 设计用于支持所有流行的进化算法范式。

你只需要3行代码就可以运行一个进化算法:

algo = SimpleEvolution(Subpopulation(SymbolicRegressionEvaluator()))algo.evolve()print(f'algo.execute(x=2,y=3,z=4): {algo.execute(x=2, y=3, z=4)}')

而且EC-KitY还与scikit-learn兼容,你可以在这个代码片段中看到:

X, y = make_regression(n_samples=100, n_features=3)terminal_set = create_terminal_set(X)algo = SimpleEvolution(Subpopulation(creators=FullCreator(terminal_set=terminal_set),                                     evaluator=RegressionEvaluator()))regressor = SKRegressor(algo)X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)regressor.fit(X_train, y_train)print('MAE on test set:', mean_absolute_error(y_test, regressor.predict(X_test)))

让我以查尔斯-达尔文的一句名言结束--《物种起源》的结尾几行:

在这种观点中,有一种宏伟的力量,那就是生命,它的几种力量,最初被吸入几个形式或一个形式中;而且,当这个星球按照固定的重力法则循环往复时,从如此简单的开始,已经并正在进化出无尽的最美丽和最奇妙的形式。