本文是神经架构搜索相关主题的第一篇文章,针对《Neural Architecture Search: A Survey》的一个翻译。
神经架构搜索:综述
- 摘要
- 1 引言
- 2 搜索空间
- 3 搜索策略
- 4 性能评估策略
- 5 未来方向
摘要
过去几年,深度学习在图像识别、语音识别和机器翻译等各种任务上取得了显著进展。这一进展的一个关键方面是新的神经结构。目前使用的架构大多是由人工专家手动开发的,这是一个耗时且容易出错的过程。正因为如此,人们对自动神经结构搜索方法越来越感兴趣。我们概述了该研究领域的现有工作,并根据三个维度对其进行了分类:搜索空间、搜索策略和性能评估策略。
1 引言
深度学习在感知任务中的成功很大程度上归功于其对特征工程过程的自动化:分层特征提取器是以端到端的方式从数据中学习的,而不是手动设计的。然而,伴随着这一成功,对架构工程的需求不断增长,越来越复杂的神经结构是手动设计的。因此,神经架构搜索(NAS)是架构工程自动化的过程,是机器学习自动化的下一步。到目前为止,NAS方法在一些任务上已经优于手动设计的架构,如图像分类、目标检测或语义分割。NAS可以被视为AutoML的子领域,并与超参数优化和元学习有显著重叠。我们根据三个维度对NAS的方法进行分类:搜索空间、搜索策略和性能估计策略:
- 搜索空间。搜索空间定义了原则上可以表示哪些体系结构。结合关于非常适合任务的体系结构的典型特性的先验知识可以减少搜索空间的大小并简化搜索。然而,这也引入了人类的偏见,这可能会阻止找到超越当前人类知识的新型架构构建块。
- 搜索策略。搜索策略详细说明了如何探索搜索空间(搜索空间通常是指数级的,甚至是无界的)。它包含了经典的探索与利用权衡问题,因为一方面,希望快速找到性能良好的体系结构,而另一方面,应避免过早收敛到次优体系结构区域。
- 性能评估策略。NAS的目标通常是找到在看不见的数据上实现高预测性能的体系结构。性能估计是指估计这种性能的过程:最简单的选择是对数据执行架构的标准训练和验证,但不幸的是,这在计算上很昂贵,并限制了可以探索的架构的数量。因此,最近的许多研究都集中在开发降低这些性能估计成本的方法上。
我们参考图1进行说明。本文也是根据这三个维度构建的:我们在第2节中讨论搜索空间,在第3节中介绍搜索策略,并在第4节中概述性能估计方法。最后,我们在第5节中展望了未来的发展方向。
2 搜索空间
搜索空间定义了NAS方法原则上可能发现的神经结构。我们现在讨论最近工作中的常见搜索空间。
一个相对简单的搜索空间是链结构神经网络的空间,如图2(左)所示。链结构的神经网络架构A可以写成
n
n
n层的序列,其中第
i
i
i层
L
i
L_i
Li从第
i
−
1
i-1
i−1层接收其输入,其输出用作第
i
+
1
i+1
i+1层的输入,即
A
=
L
n
∘
…
L
1
∘
L
0
A=L_n\circ\dots L_1\circ L_0
A=Ln∘…L1∘L0。然后,搜索空间被参数化为:(i)(最大)层的数量n(可能是无界的);(ii)每层执行的操作类型,例如池化、卷积或更高级的操作,如深度可分离卷积或扩张卷积;和(iii)与操作相关的超参数,例如卷积层的滤波器数量、内核大小和步长,或者全连接网络的简单单元数量。注意,来自(iii)的参数以(ii)为条件,因此搜索空间的参数化不是固定长度,而是条件空间。
最近在NAS方面的工作结合了手工构建的架构中已知的现代设计元素,如跳跃连接,可以构建复杂的多分支网络,如图2(右)所示。在这种情况下,层
i
i
i的输入可以被正式地描述为组合先前层输出的函数
g
i
(
L
i
−
1
o
u
t
,
…
,
L
0
o
u
t
)
g_i(L_{i-1}^{out},\dots,L_0^{out})
gi(Li−1out,…,L0out)。采用这样的函数会产生明显更多的自由度。这些多分支架构的特殊情况是(i)链结构网络(通过设置
g
i
(
L
i
−
1
o
u
t
,
…
,
L
0
o
u
t
)
=
L
i
−
1
o
u
t
g_i(L_{i-1}^{out},\dots,L_0^{out})=L_{i-1}^{out}
gi(Li−1out,…,L0out)=Li−1out),(ii)残差网络,其中对前一层输出进行求和(
g
i
(
L
i
−
1
o
u
t
,
…
,
L
0
o
u
t
)
=
L
i
−
1
o
u
t
+
L
j
o
u
t
,
j
<
i
−
1
g_i(L_{i-1}^{out},\dots,L_0^{out})=L_{i-1}^{out}+L_{j}^{out},j<i-1
gi(Li−1out,…,L0out)=Li−1out+Ljout,j<i−1),以及(iii)密度网络,其中将前一层输出进行拼接(
g
i
(
L
i
−
1
o
u
t
,
…
,
L
0
o
u
t
)
=
c
o
n
c
a
t
(
L
i
−
1
o
u
t
,
…
,
L
0
o
u
t
)
g_i(L_{i-1}^{out},\dots,L_0^{out})=concat(L_{i-1}^{out},\dots,L_0^{out})
gi(Li−1out,…,L0out)=concat(Li−1out,…,L0out))。
受到重复模块构成的人工设计架构的启发,Zoph et al.(2018)和Zhong et al.(2018a)建议搜索这些模块,分别称为单元或块,而不是整个架构。Zoph等人(2018)优化了两种不同类型的单元:一种是保持输入维度的正常单元,另一种是降低空间维度的归约单元。然后,通过以预定义的方式堆叠这些单元来构建最终的体系结构,如图3所示。与上面讨论的搜索空间相比,该搜索空间具有三个主要优点:
- 1.搜索空间的大小显著减小,因为单元通常由比整个体系结构明显更少的层组成。例如,Zoph等人(2018)估计,与之前的工作相比,速度提高了7倍,同时实现了更好的性能。
- 2.通过简单地改变模型中使用的单元和过滤器的数量,可以更容易地将由单元构建的体系结构传输或调整为其他数据集。事实上,Zoph等人将在CIFAR-10上优化的单元转移到ImageNet,并实现了最先进的性能。
- 3.通过重复构建块来创建架构已被证明是一个有用的设计原则,例如在RNN中重复LSTM块或堆叠残差块。
因此,这种基于单元的搜索空间也被最近的许多工作成功地采用。然而,当使用基于单元的搜索空间时,出现了一个新的设计选择,即如何选择宏架构:应该使用多少个单元,以及应该如何连接它们来构建实际模型?例如,Zoph等人从单元构建序列模型,其中每个单元接收前两个单元的输出作为输入,而Cai等人采用了众所周知的手动设计架构的高级结构,如DenseNet,并在这些模型中使用它们的单元。原则上,可以通过简单地用单元替换层来任意组合单元,例如,在上述多分支空间内。理想情况下,宏观架构和微观架构(即单元的结构)都应该联合优化,而不是单独优化微观架构;否则,在找到一个性能良好的单元后,可能很容易不得不进行手动宏架构工程。优化宏架构方向上的一步是Liu等人引入的分层搜索空间,它由几个层次的模块组成。第一级由一组基元运算组成,第二级通过有向无环图连接基元运算的不同基元,第三级模块编码如何连接第二级模块,等等。基于单元的搜索空间可以被视为这种分层搜索空间的一种特殊情况,其中级的数量为三,第二级模块对应于单元,第三级是硬编码的宏架构。
搜索空间的选择在很大程度上决定了优化问题的难度:即使对于基于具有固定宏架构的单个单元的搜索空间的情况,优化问题仍然是(i)非连续的和(ii)相对高维的(因为更复杂的模型往往表现得更好,从而产生更多的设计选择)。
我们注意到,许多搜索空间中的架构可以写成固定长度的向量;例如,Zoph等人的两个单元中每个单元的搜索空间可以写成具有分类维度的40维搜索空间,每个搜索空间在少量不同的构建块和输入之间进行选择。无界搜索空间可以被约束为具有(可能非常大但有限)数量的层,这再次产生了具有(可能很多)条件维度的固定大小搜索空间。
在下一节中,我们将讨论非常适合这类搜索空间的搜索策略。
3 搜索策略
许多不同的搜索策略可以用来探索神经结构的空间,包括随机搜索、贝叶斯优化、进化方法、强化学习(RL)和基于梯度的方法。从历史上看,几十年前,许多研究人员已经使用进化算法来进化神经结构(通常还有它们的权重)。Yao(1999)对2000年以前的工作进行了文献综述。
自2013年以来,贝叶斯优化在NAS领域取得了几项早期成功,导致了最先进的视觉架构,CIFAR-10在没有数据增强的情况下具有最先进的性能,以及第一个在比赛数据集上战胜人类专家的自动调整神经网络。Zoph和Le通过基于强化学习的搜索策略在CIFAR-10和Penn Treebank基准测试中获得了竞争性表现后,NAS成为了机器学习界的主流研究课题。虽然Zoph和Le使用了大量的计算资源来实现这一结果(三到四周使用800个GPU),但在他们的工作之后,各种各样的方法已经相继发表,以降低计算成本并实现性能的进一步提高。
为了将NAS定义为强化学习(RL)问题,神经架构的生成可以被认为是代理的动作,动作空间与搜索空间相同。代理的奖励是基于对训练后的体系结构在看不见的数据上的性能的估计(见第4节)。不同的RL方法在如何表示代理的策略以及如何优化策略方面有所不同:Zoph和Le使用循环神经网络(RNN)策略对字符串进行顺序采样,然后对神经架构进行编码。他们最初使用增强策略梯度算法训练该网络,但在后续工作中使用近端策略优化。Baker等人使用Q学习来训练策略,该策略依次选择层的类型和相应的超参数。
这些方法的另一种观点是,作为顺序决策过程,策略对动作进行采样,以顺序生成体系结构,即环境的“状态”包含迄今为止采样的动作的摘要,并且只有在最终动作之后才能获得(未贴现的)奖励。然而,由于在这个顺序过程中没有与环境发生交互(没有观察到外部状态,也没有中间奖励),我们发现将架构采样过程解释为单个动作的顺序生成更直观;这将RL问题简化为无状态的多臂赌博机问题。
Cai等人提出了一种相关的方法,他们将NAS定义为一个顺序决策过程:在他们的方法中,状态是当前(部分训练的)架构,奖励是对架构性能的估计,而动作对应于函数保留变异的应用,称为网络同态,另见第4节,随后是网络的训练阶段。为了处理可变长度的网络架构,他们使用双向LSTM将架构编码为固定长度的表示。基于这个编码的表示,actor网络决定采样的动作。这两个组件的组合构成了策略,该策略使用增强策略梯度算法进行端到端训练。我们注意到,这种方法不会两次访问同一个状态(体系结构)。
使用RL的替代方案是使用进化算法来优化神经架构的神经进化方法。我们所知的第一种设计神经网络的方法可以追溯到近三十年前:Miller等人使用遗传算法提出架构,并使用反向传播优化其权重。从那时起,许多神经进化方法使用遗传算法来优化神经结构及其权重;然而当扩展到用于监督学习任务的具有数百万权重的当代神经架构时,基于SGD的权重优化方法目前优于进化方法。最近的神经进化方法因此再次使用基于梯度的方法来优化权重,并仅使用进化算法来优化神经结构本身。进化算法进化出一组模型,即一组(可能经过训练的)网络;在每一个进化步骤中,都会对种群中的至少一个模型进行采样,并作为亲本,通过对其应用突变来生成后代。在NAS的背景下,突变是局部操作,例如添加或删除层、更改层的超参数、添加跳过连接以及更改训练超参数。在训练后代后,评估他们的适应度(例如,在验证集上的表现),并将他们添加到群体中。
神经进化方法在如何对父母进行采样、更新种群和产生后代方面有所不同。例如,Real等人和Liu等人使用锦标赛选择对父母进行抽样,而Elsken等人使用反向密度从多目标Pareto前沿对父母进行采样。Real等人从种群中去除最差的个体,而Real等人发现去除年龄最大的个体是有益的(这会减少贪婪),Liu等人根本不去除个体。为了生成后代,大多数方法随机初始化子网络,而Elsken等人采用拉马克遗传,即通过使用网络同态将知识(以学习权重的形式)从父网络传递给其子网络。Real等人还让后代继承其父母的所有不受应用突变影响的参数;虽然这种继承不是严格的函数保留,但与随机初始化相比,它也可能加快学习速度。此外,它们还允许改变学习率,这可以被视为在NAS期间优化学习率计划的一种方式。我们参考Stanley等人最近对神经进化方法的深入综述。
Real等人进行了一项案例研究,比较了RL、进化和随机搜索(RS),得出的结论是,RL和进化在最终测试准确性方面表现同样好,进化具有更好的随时随地性能,并能找到更小的模型。这两种方法在实验中的表现始终优于RS,但幅度较小:RS在CIFAR-10上实现了约4%的测试误差,而RL和进化达到了约3.5%(在“模型增强”后,滤波器的深度和数量增加了;实际用于搜索的非增强空间的差异约为2%)。Liu等人的差异甚至更小,他们报告了CIFAR-10上3.9%的测试误差和ImageNet上21.0%的RS top-1验证误差,而基于进化的方法分别为3.75%和20.3%。
贝叶斯优化(BO,参见,例如(Shahriari et al.,2016))是超参数优化最流行的方法之一,但由于典型的BO工具箱基于高斯过程,并专注于低维连续优化问题,因此许多小组尚未将其应用于NAS。Swersky等人和Kandasamy等人推导了体系结构搜索空间的核函数,以便使用经典的基于GP的BO方法。相反,一些工作使用基于树的模型(特别是树Parzen估计量或随机森林)来有效地搜索高维条件空间,并在广泛的问题上实现最先进的性能,联合优化神经结构及其超参数。虽然缺乏全面的比较,但有初步证据表明,这些方法也可以优于进化算法。
Negrinho和Gordon以及Wistuba利用了他们搜索空间的树结构,并使用蒙特卡罗树搜索。Elsken等人提出了一种简单但性能良好的爬山算法,该算法通过贪婪地朝着性能更好的架构的方向前进来发现高质量的架构,而不需要更复杂的探索机制。
虽然上述方法使用离散搜索空间,但Liu等人提出了一种连续松弛,以实现基于梯度的直接优化:作者不是固定要在特定层执行的单个运算
o
i
o_i
oi(例如,卷积或池化),而是根据一组运算
{
o
1
,
…
,
o
m
}
\{o_1,…,o_m\}
{o1,…,om}计算凸组合。更具体地说,给定层输入
x
x
x,层输出
y
y
y计算为
y
=
∑
i
=
1
m
α
i
o
i
(
x
)
α
i
≥
0
,
∑
i
=
1
m
α
i
=
1
y=\sum_{i=1}^m\alpha_i o_i(x)\alpha_i\geq0,\sum_{i=1}^m\alpha_i=1
y=∑i=1mαioi(x)αi≥0,∑i=1mαi=1,其中凸系数
α
i
\alpha_i
αi有效地参数化了网络架构。Liu等人然后通过在权重的训练数据和架构参数(如
α
\alpha
α)的验证数据上交替梯度下降步骤来优化网络权重和网络架构。最终,通过为每一层选择具有
i
∗
=
arg max
i
α
i
i^*=\argmax_i\alpha_i
i∗=argmaxiαi的运算
i
∗
i^*
i∗,获得了离散体系结构。Xie等人;Cai等人提出在可能的操作上优化参数化分布。Shin等人以及Ahmed和Torresani也采用了基于梯度的神经架构优化,但分别侧重于优化层超参数或连接模式。
4 性能评估策略
第3节中讨论的搜索策略旨在找到一种神经架构
A
\mathbf{A}
A,该架构可以最大限度地提高一些性能指标,例如对未发现数据的准确性。为了指导他们的搜索过程,这些策略需要估计他们考虑的给定架构
A
\mathbf{A}
A的性能。最简单的方法是在训练数据上训练
A
\mathbf{A}
A,并在验证数据上评估其性能。然而,从头开始训练每个要评估的体系结构通常会产生NAS数千GPU天数量级的计算需求。这自然会导致开发用于加快性能估计的方法,我们现在将对此进行讨论。我们参考表1了解现有方法的概述。
可以基于完全训练后的实际性能的较低置信度来估计性能(也称为代理度量)。这种较低的置信度包括较短的训练时间、对数据子集的训练、对较低分辨率图像的训练,或者每层较少的滤波器和较少的单元。虽然这些低保真度近似降低了计算成本,但它们也在估计中引入了偏差,因为性能通常会被低估。只要搜索策略仅依赖于对不同架构进行排名并且相对排名保持稳定,这就可能没有问题。然而,最近的结果表明,当廉价近似值和“完全”评估之间的差异太大时,这种相对排名可能会发生巨大变化,主张可信度逐渐增加。
估计架构性能的另一种可能方法建立在学习曲线外推的基础上。Domhan等人建议外推初始学习曲线,并终止那些预测表现不佳的曲线,以加快架构搜索过程。Swersky等人,Klein等人,Baker等人,以及Rawal和Miikkulainen也考虑了用于预测哪些部分学习曲线最有前途的架构超参数。Liu等人还提出了训练用于预测新架构性能的替代模型,他们不采用学习曲线外推,但支持基于架构/单元属性预测性能,并外推到比训练期间看到的更大尺寸的架构/单元。预测神经结构性能的主要挑战是,为了加快搜索过程,需要在相对较少的评估基础上,在相对较大的搜索空间中做出良好的预测。
另一种加速性能估计的方法是基于之前训练过的其他架构的权重来初始化新架构的权重。实现这一点的一种方法,称为网络同态,允许修改架构,同时保持网络所代表的功能不变,从而产生只需要几天GPU的方法。这允许连续增加网络容量并保持高性能,而不需要从头开始进行训练。持续训练几个时期也可以利用网络同态引入的额外容量。这些方法的一个优点是,它们允许搜索空间,而不存在架构大小的固有上限;另一方面,严格的网络同态只能使体系结构变得更大,从而可能导致体系结构过于复杂。这可以通过使用允许收缩架构的近似网络同态来减弱。
一次性架构搜索(见图4)将所有架构视为超图(一次性模型)的不同子图,并在具有该超图的共同边的架构之间共享权重。只需要(以各种方式中的一种)训练单个一次性模型的权重,然后可以通过从一次性模型继承训练的权重来评估架构(它们只是一次性模型的子图),而无需任何单独的训练。这大大加快了架构的性能估计,因为不需要训练(只需要评估验证数据的性能),再次导致方法只需要几天的GPU时间。一次性模型通常会产生很大的偏差,因为它严重低估了最佳架构的实际性能;然而,它允许对体系结构进行排名,如果估计的性能与实际性能密切相关,这就足够了。然而,目前尚不清楚情况是否真的如此。
不同的一次性NAS方法在如何训练一次性模型方面有所不同:ENAS学习RNN控制器,该控制器从搜索空间对架构进行采样,并基于通过增强获得的近似梯度训练一次性模型。DARTS通过在单次模型的每个边缘上放置候选操作的混合物来获得搜索空间的连续松弛,从而联合优化单次模型中的所有权重。SNAS优化了候选操作的分布,而不是像DARTS那样优化操作的实值权重。作者采用简单的、非参数化的离散概率分布和重新参数化来放松离散分布并使其可微分,从而能够通过梯度下降进行优化。为了克服将整个一次性模型保留在GPU内存中的必要性,ProxylessNAS将架构权重“二值化”,每次操作屏蔽掉除一条边之外的所有边。然后,通过对一些二进制架构进行采样并使用BinaryConnect来更新相应的概率,来学习边缘被屏蔽或未被屏蔽的概率。Bender等人只训练一次单次模型,并表明当在使用路径丢弃的训练过程中随机停用该模型的部分时,这就足够了。
虽然前面提到的方法在训练期间优化了架构上的分布,但Bender等人的方法可以被视为使用固定分布。后者可获得的高性能表明,重量分担和固定(精心选择)分布的组合可能(也许令人惊讶)是一次性NAS唯一需要的成分。与这些方法相关的是超网络的元学习,其为新的体系结构生成权重,因此只需要训练超网络,而不需要训练体系结构本身。这里的主要区别在于,权重不是严格共享的,而是由共享的超网络生成的(以采样的架构为条件)。
一次性NAS的一个一般限制是,先验定义的超图将搜索空间限制为其子图。此外,在架构搜索期间要求整个超图驻留在GPU存储器中的方法将被限制为相对较小的超图和相应的搜索空间,因此通常与基于单元的搜索空间结合使用。虽然基于权重共享的方法大大减少了NAS所需的计算资源(从数千天减少到几天),但目前还不清楚,如果架构的采样分布与一次性模型一起优化而不是修复它,它们会在搜索中引入哪些偏差。例如,比其他部分更多地探索搜索空间的某些部分的初始偏差可能导致一次性模型的权重更好地适应这些架构,这反过来又会加强搜索对搜索空间的这些部分的偏差。这可能导致NAS过早收敛,或者架构的一次性性能和真实性能之间几乎没有相关性。一般来说,对不同表现带来的偏见进行更系统的分析估算将是未来工作的一个理想方向。
5 未来方向
在本节中,我们将讨论NAS研究的几个当前和未来方向。大多数现有工作都集中在用于图像分类的NAS上。一方面,这提供了一个具有挑战性的基准,因为许多手动工程都致力于寻找在该领域表现良好且不易被NAS超越的体系结构。另一方面,通过利用手工工程中的知识来定义一个非常适合的搜索空间相对容易。这反过来又使得NAS不太可能找到显著优于现有体系结构的体系结构,因为找到的体系结构不能有根本的不同。因此,我们认为通过将NAS应用于探索较少的领域来超越图像分类问题是很重要的。在图像恢复、语义分割、迁移学习、机器翻译和强化学习,以及优化循环神经网络,例如用于语言或音乐建模。NAS的进一步有前景的应用领域将是生成对抗性网络或传感器融合。
另一个有希望的方向是开发用于多任务问题的NAS方法和用于多目标问题的NAS算法,其中资源效率的衡量标准与对未知数据的预测性能一起被用作目标。我们强调,多目标NAS与网络压缩密切相关:两者都旨在寻找性能良好但高效的架构。因此,一些压缩方法也可以被视为NAS方法,反之亦然。
同样,扩展RL/多臂方法(如第3节中讨论的方法)以学习以编码任务属性/资源需求的状态为条件的策略(即,将设置变成上下文多臂)也是很有意思的。Ramachandran和Le遵循了类似的方向,扩展了一次性NAS,以根据运行中的任务或实例生成不同的体系结构。此外,将NAS应用于搜索对对抗性示例更具鲁棒性的架构是一个有趣的近期方向。
与此相关的是关于定义更通用、更灵活的搜索空间的研究。例如基于单元的搜索空间提供了不同图像分类任务之间的高可迁移性,它在很大程度上基于人类在图像分类方面的经验,并且不容易推广到硬编码分层结构(在链式结构中多次重复相同的单元)不适用的其他领域(例如,语义分割或对象检测)。一个搜索空间,允许表示和确定更通用的层次结构将使NAS更广泛地适用,参见Liu等人在这一方向上的首次工作。此外,公共搜索空间也基于预定义的构建块,例如不同类型的卷积和池化,但不允许在该级别上识别新的构建块;超过这一限制可能会大大增加NAS的能力。
NAS的不同方法的比较,甚至已公布结果的再现性都很复杂,因为体系结构性能的测量取决于除体系结构本身之外的许多因素。虽然大多数作者报告了CIFAR-10数据集的结果,但实验往往在搜索空间、计算预算、数据增强、训练程序、正则化和其他因素方面有所不同。例如,对于CIFAR-10,当使用余弦退火学习速率调度、CutOut的数据增强、MixUp或多种因素的组合以及Shake-Shake正则化和ScheduledDropPath的正则化时,性能显著提高。因此,可以想象,与NAS发现的更好的体系结构相比,这些成分的改进对报告的性能数字的影响更大。因此,我们认为共同基准的定义对于公平比较不同的NAS方法至关重要。朝着这个方向迈出的第一步是Ying等人提出的基准,其中考虑了由大约423000个独特卷积架构组成的搜索空间。该空间的每个元素都经过了多次预训练和评估,形成了一个数据集,其中包含训练、验证和测试的准确性,以及多次运行的不同训练预算的训练时间和模型大小。因此,通过简单地查询预先计算的数据集,可以将不同的搜索策略与该基准上的低计算资源进行比较。在之前的一项较小的研究中,Klein等人预先评估了神经结构和超参数的联合空间。同样有趣的是,不是孤立地评估NAS方法,而是将其作为完整开源AutoML系统的一部分,其中超参数和数据增强管道也与NAS一起优化。
虽然NAS已经取得了令人印象深刻的性能,但到目前为止,它几乎没有深入了解为什么特定的架构能很好地工作,以及独立运行中衍生的架构有多相似。识别常见的模块,理解为什么这些模块对高性能很重要,并研究这些模块是否能概括不同的问题是可取的。