三
上回聊了很多概念,总的来说希望给大家带来一个基于描述复杂性的层级的视角来理解AGI、深度学习和图灵机的整体蓝图。简单总结一下:
- 图灵机支持的算法集合包罗万象,统称为图灵可计算函数。
- 人可以维护的复杂性有限,人可以直接设计出的图灵机算法的集合是低描述复杂性算法集合,是图灵可计算函数的一个很小的子集。
- 深度学习模型基于图灵机,训练好的深度学习模型整个前向过程也是图灵可计算函数,深度学习模型的集合也是图灵可计算函数的一个子集,但大多落在高描述复杂性算法集合内。深度学习帮助我们提高了描述复杂性的层级,从而也带来了突破性的能力。
- 人建模深度学习模型是站在模型结构层面,而非具体规则(参数)层面,在模型结构层面看,模型的描述复杂性仍然是比较低的。深度学习模型的集合同样很大,但人可以直接设计出的深度学习模型也只是低描述复杂性模型子集。
- 人脑很可能是一个跨越了大量层级的超级系统,其能力很难在低层级实现,甚至概念上都没法有效地定义出来。
所以从这样的视角来看,实现类脑智能就像攀登描述复杂性的珠峰,图灵机为我们提供了坚实的地基。传统的机器学习向上一跃,抓住了一根高处的树枝,瞥见了高处的风景。而深度学习则真正带领我们爬上了第一层复杂性极限的台阶,逐步构建起一个大本营,能让我们在这个高度自由探索,这个平台看到的风景和山脚的风景有很大的不同。而自然界创造出来的人类大脑显然是远在山巅。我们能看到云层深处的人脑具有的强大通用智能能力。
深度学习带我们爬上了一定的高度,但显然和人脑在山顶的风景差异巨大,因此很多人就觉得我们可能走错路了,想推翻深度学习,重新搜索一个新的路径上山,类脑在SNN算法上的执着正如重新回到山角开辟一条新的路上山,当然目前还处于够树枝的阶段,远没实现迈上一个台阶的目标。而类脑目前在芯片系统层面的挣扎是连地基都砸了,于是深陷到海沟里了。我在前面的文章里提过我写的一篇关于类脑系统栈的设计,充其量顶多是提供了一块木板,勉强让类脑芯片可以趴在上面喘口气,但其坚固程度远远比不上图灵机。
那么回到这篇文章的主旨,出路在哪里?如果你接受了我前面的整个视角,那么战略上的答案显然是呼之欲出的——基于深度学习继续往上爬!!!!
问题是战术上怎么做呢?
战术上的做法肯定很多,我在这里也算是抛砖引玉了。不过在介绍具体的一些策略前,我还是想进一步探讨一下怎样才算是往上爬。
其实人类战胜复杂性的手段只有一个,那就是解耦合。但解耦合有两种,一种是问题的抽象和解耦。计算机领域有一个经典的方法论:
All problems in computer science can be solved by another level of indirection.
通过增加抽象将问题解耦合,我们可以降低整个系统设计的复杂性。这是我们构建整个计算机系统最核心的方法论。
但我在这个系列里讲的层级则是另一种,一定程度上也是对应上面那段话的后面半句。
Except for the problem of too many layers of indirection
当我们做了过多的解耦合,以至于这些分层本身也变成一个问题时,如果系统的设计还是没法简化,那此时系统的复杂度就非常接近我们前面提的描述复杂性了,因为描述复杂性是本身就是解耦合和化简的极限。对于这种高描述复杂性的问题,我们只能用涌现的方式来实现复杂性层级的跨越。
涌现和传统的抽象解耦的主要区别在于,抽象解耦仍然是精确的,对细节的把控仍然是精确到每一个基本组件的,只是抽象的不同层聚焦问题的不同部分,但不同层的解决逻辑作为一个整体仍然是精确控制着整个系统的组织形式,解决问题的基本逻辑是没有变的。而涌现则必然需要放弃对系统每个基本实体状态的控制,只关注宏观层面涌现出来的状态,并且涌现出的状态要能体现出全新的解决问题的逻辑。
具体来讲,图灵机解决问题的基本思路就是一步一步精确的逻辑与指令,拿到一个具体问题,如何拆成一步一步的指令,这就是我们平时所说的编程思维,也是图灵机解决问题的根本逻辑,这一点无论我们对软件进行分层和抽象都不会变化。因此没有描述复杂性的涌现,算法的逻辑变了就是不同的算法。
而深度学习放弃了对精确的逻辑与指令的控制,转而把控计算的形式,也就是模型结构。只要结构相同就是同一个模型,哪怕训练出的模型参数完全不同。另一方面,深度学习解决问题的根本逻辑与图灵机带来的编程思维是有根本性不同的。我们设计神经网络对架构的设计遵循的是一套截然不同的逻辑,这套逻辑现在甚至没法形式化,更多是靠神经网络研究人员的经验,但显然和图灵机那套拆分成指令的编程思维完全不同。这种设计范式在底层逻辑上与图灵机的编程思维的差异才能带来描述复杂性的层级提升和涌现。
这一点区别非常重要,大家可以好好思考和感悟一下。
那么同样,对于深度学习建模的问题,其基石是计算图,我们可以通过增加抽象来简化建模的难度,例如当前一些框架引入的module概念,以嵌套方式建模。但要提高层级,我们必须放弃对部分建模细节的控制,并且把控一些更高层级的概念。
说到这里不知道大家有没有想到automl。当然我相信大部分做automl研究的并非朝着这个目标在演进,不过确实可以提供一定的借鉴意义。我这篇文章其实也想以automl为例子抛砖引玉探讨一下进一步提升描述复杂性层级的可能性。
我们可以重复一下前面的思想实验,前面我们把一个训练好的图像分类深度学习模型带到几十年前作为标准答案给大家当图灵机算法抄作业,大家根本没法理解这个算法怎么工作的。现在如果把几十年后用一种更高级的automl方式建出了更通用的智能模型,然后把搜出来的模型结构带到现在给大家抄答案,大家可以想象一下一个结构庞大且非常混乱的深度学习模型,但是可以跑一下可以实现很复杂任务的模型,我们一样也没法理解为啥能工作,同样也没法基于这个模型抄作业搞二次开发,更没法按照现在设计模型的方式设计出这种模型。这就是层级的重要性。
深度学习模型虽然具体规则都是训练出来的,但模型结构是可编程的,模型结构至关重要,也指导了到底生成什么样的规则。同样,automl的结构虽然是搜出来的,但仍然需要很多人类先验知识,也就是说我们需要对automl进行元编程,并且要把这种元编程的形式设计得逐渐和计算图解耦合,能让大家直接在这个层面设计模型。这一点,目前的automl还是远远不够的,现在automl的大框架基本是定义搜索空间和定义基本块,最后再加上一个搜索算法,背后计算图的抽象还是脱离不了的。要沿着这条路实现层级提升,至少要实现两个方面的改造。
一方面是元编程范式/语言的设计,也就是怎样建立一层抽象来尽量完备地表达先验知识,这个其实我们可以从过去深度学习的各种milestone论文来考虑,而且不同领域可能不太一样。像cv领域更注重结构的pattern,宏观结构基本是确定的,典型的如inception,resnet等,都是对于结构pattern的描述。而nlp领域则更多是宏观结构的设计,像seq2seq,attention到self attention等。这种pattern和宏观结构是需要元编程范式来描述的,最好能做到论文里一张图或者一个公式,描述起来也是一句声明。然后靠automl算法来生成细节的模型。比如resnet核心就是残差连接,元语言应当也需要一两句话表达清楚,然后靠算法来生成具体的resnetxxx,准确率还要能达到差不多的水平。这样研究人员才能快速验证idea的可靠性,同时可以开发元语言需要写几百几千行代码的超级模型。
另一方面是automl搜索算法的改进,automl现在基本是靠随机搜索来找结构,随机战胜不了复杂性。深度学习的权重是靠梯度来训练的。如果我们用随机搜索的方式来确定一个cnn模型的权重,估计永远搜不出好的解。目前automl看起来还可以一方面是因为先验给的足够好,毕竟都是成熟的领域,另一方面规模还太小,还是在低复杂性模型范围的浅滩上尝试。搜出来的模型虽然也比较乱,但还是完全没法抄作业的程度。而未来,我们是要靠这样的算法带领我们走进高复杂性模型的汪洋大海的去探索不成熟、未知的领域的。而且它要作为我们未来探索的新地基,就像梯度下降一样,支持我们从最简单的感知机模型一直走到目前各种超大规模预训练模型。
automl再往上走,层级是什么样,我也不清楚,现阶段也很难有很靠谱的方向,等我们爬上了新的地基探索一段时间就慢慢能建立起来,有可能仍然是规模的扩展,也有可能是类似硬件到软件的变化。我也希望和大家共同努力,努力爬上更高的台阶。
前面说了很多都是算法层面的事情,其实这个也确实是实现AGI最critical的问题。不过,automl需要的计算资源已经非常可怕了,如果我们沿着这条路把automl做到现在难以想象的规模,算力怎么办?其实我觉得也不用过于担心,要知道描述复杂性的提升也是算力利用率的提升,毕竟描述复杂性上来了,模型就不是“虚胖了”,虚胖的模型吃的计算资源还是巨大的,但解决的问题却不多,随着描述复杂性提升,模型会变得越来越实在。像人脑这种超级系统整体规模其实非常有限,功耗也极低。我们看深度学习的发展历程也可以看出来,早期确实会有一个算力黑洞的阶段,像早期的vgg模型,这个是模型探索阶段必然要经历的,后面会慢慢精细化,最后cnn分类可以小到可以全放片上缓存里,这个过程肯定是迭代的,像现在的nlp的超大规模预训练模型也正处于一个粗放型探索阶段,随着探索阶段的收尾,又会慢慢回到精细型,这种wave会持续很久,直到我们把这个层级的算力利用能力榨干。
因此,在硬件和系统层面,我们也要做好迎接初期算力黑洞时期的准备,但请相信,我们在下个层级能拿到的更高级的智能模型所需的运算量肯定不会超过目前预训练模型的计算量。我也希望和各位共同努力,愿有生之年能一览众山小!