人工生命模拟里到处都是需要大脑的小生物:追逐食物的细胞、会游的、会走的,还有由它们组成的整个生态系统。这些大脑通常是进化出来的,而最漂亮的方法之一正是出自这个领域本身:ES-HyperNEAT(Risi & Stanley, 2012)。

ES-HyperNEAT 并不逐个进化网络的权重,而是进化一个小函数,让它根据几何位置画出权重。每个神经元都有坐标,两个神经元之间的权重就是这个函数在它们两个位置上的取值。所以移动一个神经元,会改变它的所有权重,也就改变了它的计算内容。这让生物的大脑可以映照身体的布局,而且隐藏神经元放在哪里,也由同一个函数决定。

此后,同一族编码方法还进化出了能生长和复制图案的元胞自动机(Nichele et al., 2017),以及由神经元胞自动机组成的完整生态系统(Barbieux & Canaan, 2024)。

不过,ES-HyperNEAT 的大脑通常是平的。它的搜索是一棵四叉树,专为二维平面设计,而许多模拟生物生活在三维空间里。我想知道的是:这有没有关系?测试任务是让一个细胞在三维空间里追逐一粒漂移的食物。

当神经元按三维排布时,”连接相近的神经元”这条一句话规则,转向效果和手工设计的控制器差不多。把同样的神经元压平到一个平面上,这条规则在我试过的每种布局里都失效了。在其中一种布局里,向上和向下的推进器落在同一个位置,互相抵消,细胞永远无法改变高度。

从零开始进化,结论也类似。ES-HyperNEAT 在每一次三维运行中都找到了好的控制器,而在最好的二维布局上,只有大约一半的运行找到了。

每一次进化运行,每次追逐换一个。3D 总能追上食物,2D 地图投影大约一半时候能追上,去掉 z 的则无法改变高度。

问题在于成本。放置隐藏神经元的搜索,每增加一个维度,开销就成倍增长,第 2 部分讲的就是怎么让它变便宜。

认知状态:一个玩具任务,每种设置 8 个随机种子,而且用的是我从零写的简化版 ES-HyperNEAT,而不是参考实现。手工设定规则的结果差距大而清晰。进化实验的结果有提示性,但有一个未排除的混杂因素:三维网络长出的隐藏神经元大约是二维的六倍。

1. HyperNEAT 用位置计算权重

HyperNEAT 把每个神经元放在一个几何空间里的一个点上,这个空间叫作基底(substrate),并用每条连接两端神经元的位置来计算它的权重:

\[w = f(\mathbf{p}, \mathbf{q})\]

函数 \(f\) 本身是一个小网络,叫作 CPPN(组合模式生成网络,compositional pattern-producing network)。进化从不直接改动权重,而是进化 \(f\),最初用的是 NEAT 算法。

基底 (x₀, y₀) (x₁, y₁) w = ? 询问 CPPN x₀y₀x₁y₁ CPPN sin · gaussian · tanh w
CPPN 把两个神经元的坐标变成它们之间的权重。

因为 \(f\) 是光滑的,相邻的神经元得到的权重相近。又因为 \(f\) 只看得到坐标,”连接相近的神经元”这样的规则只需要距离 \(\lVert \mathbf{p} - \mathbf{q} \rVert\)。(HyperNEAT 通常以对称和重复为卖点,这篇文章依靠的是更朴素的一点:局部性。)

那坐标从哪里来?输入和输出神经元由设计者按照物理布局摆放。朝左看的传感器放在基底左侧,向上推的推进器放在靠上的位置。物理世界只从这里进入网络。

隐藏神经元不对应任何物理实体,重要的是它们靠近什么。一个隐藏神经元的权重,就是 CPPN 在它的位置和每个输入、输出之间的取值。所以在”连接相近的”规则下,一个位于左传感器和左推进器之间的隐藏神经元,主要听前者的,并驱动后者。它的位置就是它的职责。

ES-HyperNEAT(Risi & Stanley, 2012)更进一步,让 \(f\) 也决定隐藏神经元的位置,只有输入和输出是固定的。把连接的一端固定在某个输入神经元上,比如 \((0, -1)\),那么 \(f(0, -1, x, y)\) 就成了基底上的一个标量场:位于 \((x, y)\) 的隐藏神经元会从这个输入得到的权重。

隐藏神经元就放在这个场变化的地方。在场平坦的地方,相邻的神经元会得到相同的权重,计算相同的东西,多放几个也是浪费。

2. 用四叉树找出场变化的地方

为了找到这些区域,ES-HyperNEAT 不断把正方形切成四块:

  1. 在一个单元的四个子单元中心计算 CPPN,求这四个权重的方差,从整个正方形开始。
  2. 如果方差高于阈值 \(\tau\),就把这个单元切开,对每个子单元重复这一步,直到某个最大深度。
  3. 每个方差仍然高于一个较低阈值的叶子单元,在中心放一个隐藏神经元。

下面的演示在一个随机 CPPN 的场 \(w(x, y) = f(0, -1, x, y)\) 上运行这个过程。颜色表示权重,线条是叶子单元,圆点是隐藏神经元。把 \(\tau\) 往下拖,四叉树就会往变化剧烈的区域深挖。

3. 在三维里,正确的控制器是一条一句话规则

既然 CPPN 只看得到坐标,那么当基底的坐标刻画了任务关心的几何结构时,它就能工作得很好。这时所需的权重是位置的简单函数,而简单函数正是进化最先找到的,因为它是一次一个突变地搭建 CPPN。

测试任务故意设计成三维的。一个点状智能体(上面的细胞)沿一条随机的三维曲线追逐一个目标(食物)。它有 14 个指向固定方向 \(\mathbf{u}_k\) 的传感器,对应立方体的 6 个面和 8 个角,传感器 \(k\) 的读数是 \(s_k = \max(0, \mathbf{u}_k \cdot \hat{\mathbf{r}})\),其中 \(\hat{\mathbf{r}}\) 指向目标。它通过一个单隐藏层网络,用沿 \(\pm x\)、\(\pm y\)、\(\pm z\) 的 6 个推进器转向。

一个只管朝目标推进的手工控制器得分 0.730,零推力得分 0.225。

这个控制器完全是几何的。某个传感器有反应,说明食物大致在那个方向,朝那个方向的推进器就能把细胞推过去。所以推进器 \(j\) 对传感器 \(k\) 的响应应该与两者方向的一致程度 \(\mathbf{u}_k \cdot \mathbf{a}_j\) 成正比。把每个传感器和推进器按它们的真实方向放在基底上(传感器在半径 1 处,推进器在半径 0.5 处),”方向一致”就变成了”离得近”,因为在固定半径下

\[\lVert \mathbf{p} - \mathbf{q} \rVert^2 = \lVert \mathbf{p} \rVert^2 + \lVert \mathbf{q} \rVert^2 - 2\, \mathbf{p} \cdot \mathbf{q}\]

会随 \(\mathbf{p} \cdot \mathbf{q}\) 增大而减小。所以局部性规则

\[w = b - k \lVert \mathbf{p} - \mathbf{q} \rVert\]

就是这个控制器,只不过经过了一层网格状的隐藏神经元。短连接为正,长连接为负。传感器激发它附近的隐藏神经元,这些隐藏神经元再激发它们附近的推进器,而这些推进器的朝向和传感器相同。

平面基底做不好这件事。博苏克–乌拉姆定理说,任何把球面连续压平的方式,都会把某一对相反方向送到同一个点。只有 14 个传感器时,倾斜一下投影就能躲开碰撞,但映射仍然会把一些方向挤在一起,把另一些拉开。环形布局干脆放弃连续性来避免碰撞,于是环上相邻的传感器指向毫不相干的方向。

+z “目标在上方” −z “目标在下方” 压平(去掉 z) 同一个点
沿 z 轴投影,会把 +z 和 −z 放到同一个位置。

在下面试试看。选一个基底,调一调 \(k\) 和 \(b\),或者点搜索按钮。这里的隐藏神经元放在固定网格上;到第 4 节,才让进化来放置它们。

在 16 次随机追逐上的实时得分。表中是网格搜索找到的最佳设置。

基底 用 \(w = b - k\lVert \mathbf{p} - \mathbf{q} \rVert\) 的最佳得分
3D(真实方向) 0.745
2D,去掉 z 0.317
2D,地图投影(方位等距投影) 0.306
2D,传感器排成一圈 0.231
参照:零推力 / 手工控制器 0.225 / 0.730

在三维中,局部性规则和手工控制器一样好。在每一种二维布局中,它的得分都更接近零推力。更聪明的 CPPN 可以编码局部性的例外,但进化得一个一个地碰运气撞上它们。

4. 进化大体同意,还有一个很说明问题的失败

不过,手工设定的规则用的是固定网格。真正的检验是让 ES-HyperNEAT 包办一切:从随机初始状态进化 CPPN,并用它自己的四叉树放置隐藏神经元。

实验是怎么做的:动力学、学习算法、运行和代码
  • 任务。智能体把合推力 \(\mathbf{F}\) 带阻尼地积分,\(\mathbf{v} \leftarrow 0.8\,\mathbf{v} + 0.3\,\mathbf{F}\),\(\mathbf{x} \leftarrow \mathbf{x} + 0.25\,\mathbf{v}\),所以推得太猛会冲过头。一次追逐持续 60 步,得分为 \(1/(1 + \bar{d})\),其中 \(\bar{d}\) 是与目标的平均距离。
  • 学习。每次运行从一个随机初始化的 CPPN 开始,用进化策略训练。每一代评估 CPPN 参数的 32 个随机扰动(16 对正负对称的 \(\pm\) 扰动),根据按排名加权的结果估计得分的梯度,再走一步 Adam。得分被当作黑箱,没有梯度穿过模拟过程。一次运行持续 120 代。
  • 评分。每 5 代,在 16 次从不用于训练的预留追逐上测试当前的 CPPN。图表里显示的就是这个测试得分。
  • 运行。种子固定了一次运行的随机初始化和随机选择。三维基底和二维地图投影各有 8 个种子,两种更粗糙的二维布局各有 4 个。除了基底,其他一切都相同。
  • 代码。大约 800 行 NumPy,在 /experiments/es-hyperneat/(英文)。python run_all.py 会重跑全部实验,results/ 里有每次运行的原始输出,包括最终的 CPPN。

上:平均测试得分,±1 标准误。下:每次运行的最终得分。

每一次三维运行,最后都和手工控制器打成平手。

二维地图投影一分为二。八次运行中有四次也做到了,只是晚一些;另外四次停滞在 0.27 到 0.54 之间。环形布局从没超过 0.35。

“去掉 z”是我最喜欢的失败。四次运行全都停在 0.319。去掉 \(z\) 会把 \(\pm z\) 两个方向送到同一个点,而那里恰好住着一对传感器和一对推进器。两个垂直推进器总是得到相同的权重,一起启动、互相抵消,所以无论 CPPN 怎么做,细胞都无法改变高度。

有一个混杂因素我无法排除。三维网络长出了大约 480 个隐藏神经元,二维只有 75 个。这不是因为二维的树没地方长了,但它确实意味着这个实验分不清”更多维度”和”更多神经元”。

5. 每多一个维度,搜索就翻好几倍

在 \(n\) 维中,四叉树变成了 \(2^n\) 叉树。一个单元在二维中有 4 个子单元,三维中 8 个,六维中 64 个,成本的两部分都随之增长:

  • 每次测试都要在 \(2^n\) 个子单元中心计算 CPPN;
  • 每次切分都会产生 \(2^n\) 个新单元,每个都需要各自的测试。

如果场在深度 \(m\) 以内处处都有变化,那就是大约 \((2^n)^m\) 个单元,每个 \(2^n\) 次计算,而且每个输入神经元都要来一遍。

下面是在 2 到 7 维的随机 CPPN 上、深度为 2 的树的实际情况:

10 个随机 CPPN 的中位数,对数坐标。树的大小各不相同,所以五维并不比四维更贵。

显示具体数字
n 测试的单元数 CPPN 计算次数 每次搜索耗时
2 13 416 1.1 ms
3 49 3,136 3.9 ms
4 193 24,704 27 ms
5 97 24,832 27 ms
6 1,537 786,944 0.87 s
7 6,209 6,358,016 8.8 s

计时来自 AMD Ryzen 7 7840HS。

从二维到七维,工作量大约增加到 15,000 倍,而这只是在一个网络上做一次搜索。进化在每一代都要为每个候选 CPPN 做一次搜索。即便在转向实验里,从二维换到三维,也让一次 1.2 分钟的训练拉长到了 5.9 分钟。

6. 注意事项

  • 预测只对了一半。手工设定的规则让二维看起来毫无希望。可进化随后在一半的时间里解决了二维地图投影,所以不匹配的基底会让好的解更难找、更不稳定,但并不会让它们无法找到。
  • 一开始什么都学不会。第一个版本从没超过零推力。随机的 CPPN 会让每个神经元都饱和,相反方向的推进器又互相抵消。在做任何比较之前,对所有运行都加上了扇入缩放和零均值的输出偏移,问题就解决了。一个悄悄把神经元挤到一个角落里的隐藏神经元上限,也被去掉了。
简化与适用范围
  • 简化。这个 ES-HyperNEAT 是从零写的,不是取自参考实现。CPPN 形状固定,用进化策略而不是 NEAT 训练。每个网络只有一棵树,而不是每个输入神经元一棵;只有单隐藏层;剪枝步骤也是已发表版本的简化。这些在各基底之间都相同,但在参考代码里,绝对数值会不一样。
  • 证据有限。只有一个玩具任务,选它是因为它的几何结构能说明问题;每个基底 8 次运行,所以只能看出相当大的差异。而且它只比较了三维和二维。

7. 两难

匹配问题的几何结构,意味着问题有几个维度,就该用几个维度,而大多数物理问题,从机械臂到无人机,都是三维的。可每多一个维度,放置神经元的成本就成倍增加。

也许有办法绕过去。四叉树的方差测试,实际上是在问权重场在一个单元里变化得有多快,这是一个关于梯度的问题,而 CPPN 是由可微函数搭成的。第 2 部分:给 ES-HyperNEAT 的四叉树做梯度测试 把 \(2^n\) 次采样换成一次梯度,检验它能否用更少的工作找到同样好的网络。

参考文献

  • Barbieux, A. & Canaan, R. (2024). Coralai: Intrinsic evolution of embodied neural cellular automata ecosystems. Proceedings of the Artificial Life Conference (ALIFE 2024). arXiv:2406.09654
  • Nichele, S., Ose, M. B., Risi, S. & Tufte, G. (2017). CA-NEAT: Evolved compositional pattern producing networks for cellular automata morphogenesis and replication. IEEE Transactions on Cognitive and Developmental Systems. doi:10.1109/TCDS.2017.2737082
  • Risi, S. & Stanley, K. O. (2012). An enhanced hypercube-based encoding for evolving the placement, density, and connectivity of neurons. Artificial Life, 18(4), 331–363. doi:10.1162/artl_a_00071