理论往往是优雅简洁的,但是现实一定是复杂的。为了解决现实问题的理论通常会愈发复杂,解决方案可能会最终超越复杂,变成混乱。
# 定性
究竟该怎么定义复杂?
复杂在不同人看来可能很不相同。
正在背诵乘法口诀的小学生可能觉得复杂,正在理解理论物理公式的大学生也可能觉得复杂;
正在计算购物节满减凑单优惠的剁手党可能觉得复杂,正在试图理解经手多人外包的代码的程序员可能觉得复杂。
大学生看小学生的乘法口诀觉得小菜一碟,而程序员可能不一定能理解满减规则。
由此看来,复杂性是由概念数量决定的,需要同时考虑的概念数量越多,就会感觉到越复杂。
并且,复杂性与一个人的知识积累以及抽象能力相关,小学生背诵乘法表需要记忆。
我们面对如毛线团般的事物无从下手,而经验丰富的专家则能抽丝剥茧,重新梳理编织得井井有条。
那么我们与专家的区别在哪里呢?
答案就在知识储备上。
知识储备的一种理解是,如果把我们的思维比作工具箱,把碰到的问题比作奇形怪状的钉子,那么我们的工具箱中有多少种可选的锤子可以帮助我们敲钉子,就代表我们的知识储备的丰富程度。
同样是看到一粒凸起的钉子,普通人(未经过专业训练的人)只会觉得无从下手,光是想象自己赤手空拳跟钉子软碰硬时,就觉得疼得要命。而专家可能会掏出他惯用的锤子,敲敲打打,即使不能把钉子敲好,至少手中有锤,心里不慌。
反映到现实中来,普通人如果看到一件事的发生,可能不知从何理解,甚至陷入对复杂性的恐慌之中,大脑一片空白。不过普通人绝不止这一种反应,比如还可能回忆起自己一知半解、道听途说来的概念,强行编造个因果关系。
如果我们能把现实简化,抽象出概念,建立模型,则能帮我们更好的理解事情,从而找到可能的解决方法。
值得注意的是,工具箱思维也只是对知识储备的一种片面解释,如果眼里尽是钉子,那不得跟肉中刺一样疼吗?。
# 模型
神经生物学揭示了大脑复杂的物理结构,我们目前很难自底向上地完全解释大脑的运作方式,不过我们在不同层次上建立了几种解释模型。
一种是基于信号测量的脑区划分方法(需要准确名称),这种方法通过实验测量大脑不同区域的活跃程度与行为之间的关系。
另一种是更抽象的概念模型,用行为来验证模型的适用范围。
认知心理学中就有一个“工作记忆”的模型。模型由长期记忆和短期记忆构成,工作记忆属于短期记忆的一种,相当于思考的工作台,而长期记忆相当于记忆的仓库,用于存储暂时用不到,但可能日后还有用的记忆。
每个人的工作记忆大小不同,每个概念占用一定的空间,如果概念数量太多以至于超过了工作台的最大容限,思考将变得困难。
我们可以把外界中的概念与工作记忆“交换”,比如用纸或者白板写下来,但因为高速的“内存”和低速的“外存”直接需要不断交换信息,思考的速度将下降。
另一个模型是关于快慢系统的:我们的大脑可以简化成两种思考系统,一种是系统1,通常是迅速的,潜意识的,反射式的,不由自主的;另一种是系统2,通常是缓慢的,费力的,需要意识参与的,可以控制的。
涉及的所谓“肌肉记忆”的技能,以及需要快速反应的“机械知识”都可以通过反复练习固化下来,直接经由系统1做出反应。而学习、分析、推理、想象等行为则需要系统2参与,这时影响思考效率的就包括同时处理的概念数量了。
我们感受到的复杂通常是系统2的产物,我们不会觉得辨认普通地辨认猫或者其他常见动物是件复杂的事。
这通常在一瞬间发生,当你看到一只典型的“猫”样的物体时,猫这个概念几乎不可阻挡的进入脑中,这也是系统1的特性,它是基于神经系统的。
至于接下来的处理步骤就取决于你当时的状态,如果你的注意力集中在别的事情上,那么这个概念也只会转瞬即逝,几乎不会有机会进入长期记忆。
如果你需要仔细辨认猫的种类,或者确认那个“猫”样的物体究竟是不是猫时,则可能需要系统2的参与。
如果你对猫的特征有过深入研究,并且熟悉它们,那么同样猫的品种就已经在系统1的自动处理流水线中处理完成提交到你的脑子里了。
而如果你刚刚开始学习辨认猫的品种,捧着一本手册努力查阅或者听一旁的朋友涛涛不觉地解释,就很有可能感受到复杂,并且经历被信息淹没的感觉。
对于你而言,那些非常细节的概念之间毫无联系,光是努力维持那些概念在脑子里就十分费力了,然而实际上那些概念刚从系统1的视觉或者听觉提交上来没多久,就直接被丢弃了。
你得承认,复杂超过一定程度,人就几乎不能理解了。
# 方法
我们利用了几种模型来帮助我们分析如何处理复杂性这个问题,这些并不是唯一的解释方法。不过这些模型对于我们的提出解决方法已经有足够的启发了。
根据我们的模型,我们该如何提高处理复杂的能力呢?缩减工作记忆中的概念数量以减少甚至避免和“外界存储”的交换,提高工作记忆的容量以容纳更多的概念数量。
那么如何缩减概念数量呢?我们可以对概念进行分类、抽象、归纳、封装、近似、封装。
# 分类
物以类聚,我们可以把相似的概念分为一类——具有共同特征,或者在时空上接近。这样,我们只需按类别考虑概念。
许多苹果、梨、香蕉、西瓜、西红柿、黄瓜、冬瓜、南瓜混在一起。如果我们分别考虑每一个物体,由于物体数量很多,就很难同时考虑。如果我们先按品种先分类,就只需要考虑8堆果蔬,一共8个概念。进一步,我们再按能不能带皮吃分类,则只需要考虑2种概念:能带皮吃和不能带皮的。在此基础上讨论理解,则比同时考虑多个具体概念容易得多。
当然分类的方法不止一种,比如按颜色分类、按大小分类,分类的具体原则要根据具体问题决定。适应问题的合理分类,能帮助我们更好的简化模型,梳理思路。
# 抽象
抽象是指把多种概念的共同特征提取出来,从具体的事物体中抽象出概念。比如考虑上面提到的果蔬混合物,在分类的基础上,我们可以提取出水果和蔬菜的概念,这样就能在一般性地研究水果或者蔬菜的特性。
有时候,抽象所提取的共同特征太少,导致可以被归类的概念太多、太宽泛,这种抽象可能不一定适合我们想要考虑的问题。我们可以多层抽象,比如将共同特征的要求放严一些,这样抽象得到的概念类别也就更多并且具体些。
合理的抽象层次,对模型的组织方式有很大影响。
# 归纳
苹果是甜的,梨也是甜的,西瓜是水果,那么西瓜是甜的吗?我们可以从苹果和梨的特性上尝试归纳出水果是甜的这个特征,以此为假设前提,并通过演绎推广到同样是水果的西瓜上,可以得出西瓜也是甜的的结论。这就是归纳-演绎的常见用法。
不过,要小心掉进逻辑的陷阱!归纳-演绎的结构推导出的结论正确,必须建立在归纳的结论正确之上,归纳的结论正确又必须建立在引用事实的正确之上。
有的人把假设当事实,自然会归纳得出荒谬的结论;有的人不看具体场景,只觉得要解决的问题与归纳的模式有几分相似便套用模板,自然错到离谱,在考试上俗称套公式。
# 封装
封装是将复杂而紧密联系的概念当成一个整体,也就是当成所谓的黑盒,在考虑更高层次的问题时,仅考虑这个整体与外界的互动,而不必关心它的内部细节。
黑盒的概念应用很广。在研究大脑和行为的关系时,就有人通过人接受的刺激和做出的行为来为黑盒建立模型,这种模型是概念上的。在生活上,我们经常也不自觉结合“常识”的给身边的“黑盒”建立模型,比如在炎炎夏日我们进入室内打开空调时,可能会把空调调到最低温度,而不是最适宜温度,这里就隐含了一个我们给空调这个黑盒建立的模型——设定的温度与当前温度温差越大,空调工作的功率越高,然而这不是空调的真实模型。
因此,封装并使用简化的黑盒可以缩减概念数量,但是要注意简化后的模型能在多大程度上还原之前的解释,是否符合需要。
# 分治
有时候,许多概念一拥而上,着实令人头疼。但在开始分析之前,先判断是不是这么多概念都是需要同时思考的,是不是可以分而治之。
分而治之的思想自古有之,如果我们面对大问题难以入手,那么就化整为零,再逐个击破。同样,面对繁多的概念,如果他们可以分解成更小的概念组,再分别考虑,那么一次要处理的概念数量就能减少不少。
# 近似
近似用哲学的话来说就是:抓住主要矛盾。
近似在工程上经常使用。比如我们通过公式推导出了一串复杂的解,我们通常会在误差允许的范围内对解做近似,忽略权重低的项,保留权重高的项。在简化了解的同时在很大程度上保证结论的有效性,并且这让我们能对更有影响力的变量给予更多的注意力。放在实际应用中,我们就能集中资源攻克主要问题。
同样,需要注意的是,不要忘记模型的公式本身是对现实的近似,答案本身是对精确解的解释,而如果使用计算机求解,同样要面对有效数字的近似问题。现实在层层近似之后通过仿真展示在我们面前,然而仿真不是真,也不是现实。
化简概念也是类似,把细枝末节剔除出去后,剩下重要的概念也应该不会太多。
关于如何扩容,工作记忆这个模型对应着物理的神经系统,想要扩容十分困难。有许多号称可以提高记忆力的方法,其实是也通过减少概念数量。比如,通过谐音的方法将需要记忆的概念连成一个故事或者组成一幅画面,概念之间不再毫无关联,而是形成了一个可以自动播放的整体,回忆时再通过机械记忆住的映射规则(回忆一下小时候背乘法口诀表或者中学背元素周期表)反向解释即可。
# 应用
以编程为例,开始学习时,我们更注意程序语言的语法,通过一些简单的例子体会语言的特性。这时语法上的每一个特征对我们来说都是一个独立的概念,我们需要不断回顾语法规则来加载概念到工作记忆。此时十分费力,也就是入门的阶段。
我们在从外界反复使用这些新概念的同时,我们的大脑会根据“重复=重要”的原则把这些概念放入长期记忆中,并且通过反复练习提高熟练度可以提高概念从长期记忆中提取的速度。
在反复练习之中,我们会发现不必过于关注语法本身,而可以总结出基本的使用模式。
我们可以抽象出控制结构、循环结构这样的基本结构,明白了可以使用函数来把一系列紧密相关的实现封装起来。我们在阅读别人的代码时,可以不必关注实现细节,而是通过主要函数的调用关系理解整个模块的功能。
在这种自底向上的抽象过程中,可能会引入新的编程模型,新的功能模块,新的独立系统。
得益于此,我们可以在高抽象层次上设计系统。我们有能力把握有限的子系统数量,如果子系统的数量过多,可以进一步抽象,保持整体的概念数量可控。