ALGORITHMS TO LIVE BY · 十一章,每章一个能动手跑的模拟器

算法之美

Brian Christian & Tom Griffiths, 2016 · 中译本:中信出版集团,2018

这本书的主张只有一句:人面临的难题,计算机科学家已经用几十年的时间研究过了。什么时候停止寻找、该尝鲜还是去老地方、要不要整理、先做哪件事、怎么预测、什么时候别想太多。下面每一章都把书里的算法做成了可以拖动、重跑、看分布的实验。

章节顺序与原书一致。标题是我自己的概括,不是译本的章名。所有数字都在你的浏览器里实时计算。

第 1 章 · OPTIMAL STOPPING

什么时候停止寻找?

租房、找对象、卖房、停车、什么时候收手。它们在数学上是同一个问题:候选按顺序出现,拒绝了就回不去,你该看多久再出手?

书里的核心是秘书问题和 37% 法则:先看前 37% 的候选只看不选,之后遇到第一个比前面都好的就定,这能以约 37% 的概率选中最好的那一个。书里还给了几个变体的答案:可以回头但对方只有一半概率接受,先看 61%;出手可能被拒绝(一半概率),看 25% 就该出手;如果你知道候选的分布(全信息),用"阈值法则",命中率能到 58%。实验发现人总是停得太早。

书里的结论

"看多久"有确定的答案,而且答案和候选有多少无关:永远是 37%。卖房时你只需要一个阈值,低于它一律拒绝;停车时离目标越近越该降低标准;做有风险的事,该做的次数约等于"逃脱概率除以被抓概率"。

作者的提醒:37% 法则的目标是"选中唯一最好",所以有六成概率落空。如果你要的只是"够好",可以更早停。

用在生活里

  • 找房子:先看一个月的三分之一时间只看不租。
  • 找对象:按时间或候选数算 37%,之后遇到更好的就定。
  • 停车:占用率 90% 时,进入目标前 7 个车位就见空就停。
  • 做有风险的事:被抓概率 10%,做 9 次就收手。
第 2 章 · EXPLORE / EXPLOIT

最新的,还是最好的?

去熟悉的餐馆,还是试一家新的?这是多臂老虎机问题:每台机器的回报率未知,你的每一次选择既是在赚钱,也是在收集信息。

书里讲了三代解法。最早的"赢留输换"(赢了留下,输了就换);1979 年 Gittins 指数给了精确解:把每台机器的记录换算成一个数,永远选数最大的。书里的表(未来按 90% 折现)显示:一台从没试过的机器指数是 0.70,比一台已知五五开的机器更值得试,这就是"乐观面对不确定性"。后来的信心上界(UCB)算法把这条原则做得更简单:按"平均回报加不确定性"选。书的落点是时间:剩的时间越多越该探索,所以年轻人该多试,老人缩小社交圈不是衰退,是最优利用。

Gittins 指数表(行:赢的次数,列:输的次数)
颜色越深越值得选。注意 0 胜 0 负(从没试过)的指数高于 1 胜 1 负。

书里的结论

对未知保持乐观是有数学依据的:一台没试过的机器,其价值不只是它的期望回报,还包括"试了之后你会知道"。折现因子越接近 1(未来越重要),指数越高,越该探索。UCB 用同样的逻辑:被试得越少的选项,不确定性奖励越大。

"赢留输换"看似合理,但它对一次失败反应过度,会把真正最好的选项丢掉。

用在生活里

  • 刚搬到一个城市,头几个月多试新餐馆;要离开前的最后一周只去最爱的那几家。
  • 好莱坞拍续集、人到老年收缩社交圈,都是剩余时间变短后的"利用"。
  • A/B 测试和临床试验用的也是这套:边试边把流量倒向表现好的一边。
第 3 章 · SORTING

建立秩序,值多少钱?

整理是为了之后找得快。但排序本身有代价,而且代价随规模增长得比你想的快。书里的问题是:什么时候该整理,什么时候"乱着就好"。

书里讲了排序的代价阶梯:冒泡排序和插入排序要 n² 量级的比较;1945 年冯·诺依曼的归并排序降到 n·log n;桶排序在允许粗分类时接近 n。然后是最重要的一句:排序是搜索的预防措施,只在你会频繁查找时才划算。电子邮件别整理,搜索比分类便宜。体育比赛也是排序:单淘汰只能找出冠军,循环赛能排出全部名次但要 n(n−1)/2 场;动物的啄序是用少量打斗换一个稳定的排序。

书里的结论

左图:东西翻倍,冒泡排序的工作量翻四倍,归并只多一点。右图:整理一次的成本是固定的,之后每次查找省下的是 n/2 对 log n 的差距,查找次数超过临界点才值得整理。书的建议是"宁可乱一点":把力气花在搜索上,而不是花在维持秩序上。

用在生活里

  • 邮箱、下载文件夹:不分类,用搜索。
  • 书架、衣柜:你每天都要翻的那部分值得整理,其余不值得。
  • 比赛排名带噪声时,让每个人跟所有人都比一次最稳,但也最贵。
第 4 章 · CACHING

忘了它吧

空间有限,放不下所有东西,留什么、丢什么?计算机的回答是缓存:把最可能再用到的东西放在手边。

1966 年 Bélády 证明最优策略是千里眼:丢掉"下次用到最晚"的那个。没人能预知未来,但最近最少使用(LRU)是最好的近似:刚用过的东西马上又会用到。书里把这条规则用在衣柜(穿过的挂最左边)、野口悠纪雄的文件法(用过的放回最前面)、图书馆的还书架,以及人的记忆:心理学家安德森发现,遗忘曲线和"这件事再被需要的概率"曲线几乎重合。记忆不是坏了,是在做缓存。

书里的结论

LRU 几乎贴着千里眼的曲线走,先进先出和随机丢弃明显落后。局部性越强,LRU 的优势越大。所以"最近用过"是比"最常用"更好的留存标准。缓存不是让你记住一切,是让该在手边的在手边。

用在生活里

  • 桌面、衣柜、工具箱:用过的放回最前面,自然形成 LRU。
  • 想不起来一个名字,不是记忆衰退,是它太久没被用到。
  • 多级缓存:常用的在桌上,次常用的在抽屉,剩下的进仓库。
第 5 章 · SCHEDULING

先做哪一件?

时间管理的书有几百本,调度理论的回答是:先说清你要优化什么。目标不同,正确的顺序完全不同。

书里的三条基本规则:想让最大的迟到最小,按截止日期从早到晚做(最早截止优先);想让迟到的件数最少,用 Moore 算法:按截止日期排,一旦有件会迟到,就把目前最长的那件扔到最后;想让每件事的完成时间之和最小(手头的事清得最快),按时长从短到长(最短优先)。事情有轻重时,按"重要度除以时长"排。书里还讲了火星探路者号因"优先级反转"死机的故事,以及"颠簸":切换太频繁,全部时间都花在切换上。

书里的结论

表里每一列的最优值都来自不同的规则,没有一种顺序同时赢下所有指标。所以时间管理的第一步不是列清单,是选指标。选了"清得快"就按最短优先,选了"少违约"就用 Moore。

另外两条:别让低优先级的事卡住高优先级的(优先级反转);把打断合并起来处理(固定时间看邮件),不然你会"颠簸"。

用在生活里

  • 还债用"雪球法"(最小的先还)就是最短优先:清得快,心理上有动力。
  • 一堆有截止日的事,先按截止日排,再看哪件最长、最该放弃。
  • 邮件、消息集中在固定时段处理,中间关掉提醒。
第 6 章 · BAYES'S RULE

只有一个数据点,怎么预测?

一件事已经持续了 t,还会持续多久?一个人活到了 60,还能活多久?书里说这些问题可以回答,关键是你心里带着什么样的先验。

拉普拉斯的继承法则:试了 n 次成功 w 次,下一次成功的概率估为 (w+1)/(n+2),比 w/n 稳得多。哥白尼原理(Gott):没有任何信息时,假设自己处在一件事寿命的随机时刻,预测它还会持续"和已经过去的一样久"。然后是全书最有用的一段:先验分布有三种形状,对应三条预测法则。幂律分布(票房、财富)用乘法法则:预测 = 常数 × 已观测;正态分布(寿命)用平均法则:预测向均值靠;埃尔朗分布(无记忆的等待)用加法法则:永远再加一个固定量。实验显示人的直觉预测恰好符合这三条。

书里的结论

三条线就是三种世界观。幂律的世界里,活得越久预期越久(公司、票房、名气);正态的世界里,活得越久剩得越少(人的寿命);埃尔朗的世界里,过去多久都不影响还要等多久(无记忆)。预测错,多半是先验用错了形状。

拉普拉斯法则的意义:三次全成不等于必成,(3+1)/(3+2) = 80%。小样本需要先验来压一压。

用在生活里

  • 一家开了 10 年的餐馆,预期还能开 10 年;一家开了 3 个月的,预期再开 3 个月。
  • 等公交或等电话,已经等了多久不说明还要等多久。
  • 书里重新解读棉花糖实验:孩子等不等,取决于他对"大人会不会兑现"的先验。
第 7 章 · OVERFITTING

不要想太多

考虑的因素越多,模型越贴合已知数据,预测却越差。这叫过度拟合,是机器学习最核心的教训,也适用于人。

书里用一组数据点演示:一次函数欠拟合,九次多项式把每个点都穿过去,却把噪声也学进去了。解药有三种:交叉验证,留一部分数据专门检验;正则化,给复杂度加惩罚(Lasso 让多余的系数直接归零);早停,想到一定程度就停下。达尔文决定结婚只列了两栏利弊,心理学家 Gigerenzer 的研究表明简单的经验法则在多数预测任务上打败了复杂模型。考核指标被过度优化也是过拟合:学生学会了考试而不是知识。

书里的结论

右图是整章的图像:次数越高,训练误差一路下降,验证误差先降后升。最好的模型不是最贴数据的,是在没见过的数据上最准的。把正则化拉高,高次多项式会被压平,验证误差回落,这就是"给复杂度收费"。

用在生活里

  • 重大决定列两三条关键理由就够,列二十条是在拟合噪声。
  • 被考核的指标会被过度优化,所以别只看一个数。
  • 没把握时用早停:先用简单方案,证据多了再加复杂度。
第 8 章 · RELAXATION

先解一个更容易的问题

有些问题没有高效的精确解法,旅行商问题就是代表。计算机科学的办法是"松弛":去掉一条约束,解那个更容易的问题,再把答案拉回来。

书里讲了三种松弛。约束松弛:旅行商要走一条闭合路线,去掉"不能分叉"的约束就变成最小生成树,一瞬间能算出来,而且它是真实答案的下界,真实路线不会超过它的两倍。拉格朗日松弛:把硬约束变成罚款,允许违反但要付钱,体育联赛排赛程就是这么做的。连续松弛:把"要么选要么不选"放宽成"选一部分",解完再取整。作者的建议:想不出办法时,问自己"如果这条限制不存在,我会怎么做"。

书里的结论

9 个城市穷举要试 20160 条路线,20 个城市就是六千万亿条。但最小生成树瞬间给出一个下界,最近邻加 2-opt 给出一个离最优很近的上界,两者一夹,你就知道答案在哪个范围里,不必真的算出最优。

用在生活里

  • 排不出完美的日程,先排一个允许冲突的,再给每个冲突定代价。
  • "如果预算无限我会怎么做"是约束松弛,答案往往能缩回预算内。
  • 完美主义的反面不是将就,是知道下界在哪里。
第 9 章 · RANDOMNESS

什么时候让运气决定?

随机不是放弃思考。书里的随机算法用抽样代替穷举,用随机扰动跳出局部最优,用概率换速度。

三个例子。蒙特卡洛:乌拉姆玩单人纸牌时发现,与其推导胜率,不如发 100 把牌数一数,曼哈顿计划用的就是这招。Miller-Rabin 素性检验:每做一轮随机测试,误判的概率至少砍掉四分之三,做几十轮之后比硬件出错的概率还低,于是"概率上的确定"就够用了。模拟退火:爬山法会卡在小山包上;Kirkpatrick 从金属退火得到灵感,开始时允许大胆地往坏的方向走,随着"温度"降低逐渐只接受变好的一步,这样能跨过山谷找到更高的峰。

撒点估 π:落在扇形里的比例 × 4

书里的结论

右图里橙点是 60 次爬山的终点,大多卡在小山包;蓝点是 60 次退火的终点,更多落在最高峰附近。温度为零就是爬山,温度太高就是乱走,中间有一个最好的区间。书的落点是:卡住的时候,随机走一步,再慢慢收敛。

用在生活里

  • 不知道一个决定好不好,先随机试几次看结果,别推理。
  • 创作卡住,用随机的提示打乱自己(Brian Eno 的"迂回策略"卡片)。
  • 年轻时温度高一点,多做没把握的尝试;之后逐渐降温。
第 10 章 · NETWORKING

我们如何联系

两台机器隔着不可靠的线路怎么沟通?互联网的协议解决了这个问题,而它的三个办法恰好也是人际关系的办法。

回执(ACK):收到就说一声,没回执就重发;聊天时的"嗯""对"就是回执。指数退避:发送失败后等 1、2、4、8 个单位再试,越失败越耐心,但永不放弃;书里说这是最好的宽恕算法,夏威夷的毒品法庭(HOPE 项目)用的正是这套。加性增、乘性减(AIMD):TCP 每成功一轮就多发一点,一旦丢包就把速度砍半,于是流量是一条锯齿线。作者说这也是职场升迁的合理版本:做得好就加一点担子,做不动就退回一半,而不是"晋升到不胜任为止"。书还讲了"缓冲膨胀":队列太长反而让所有人都慢。

书里的结论

AIMD 的锯齿不是缺陷,是在没人告诉你容量多大的情况下,唯一能既试探上限、又在撞墙后迅速让路的办法。加一点,撞墙砍半,再加一点。指数退避则是在"放弃"和"无限纠缠"之间的第三条路:每次失败都把下次的耐心翻倍。

用在生活里

  • 谈话里及时给回执,对方才知道消息到了。
  • 对一再失约的人,用指数退避:下次约的间隔翻倍,但不拉黑。
  • 接新任务:加性增,撞墙就减半,比一次性接满再崩溃好。
第 11 章 · GAME THEORY

别人的想法

当对手也在算,你的最优解取决于他的最优解。书里从纳什均衡讲到机制设计,落点是:与其算别人怎么想,不如改规则,让大家不用算。

囚徒困境和公地悲剧说明均衡可以对每个人都糟("无限假期"政策下没人敢休假)。无政府的代价:自私驾驶让总通勤时间最多比最优差三分之一,所以自动驾驶统一调度的收益有限。信息级联:每个人都参考前人的选择,几个人之后所有人都在跟风,哪怕每个人的私人信号都说不对,这就是泡沫。机制设计换个思路:维克里拍卖(第二价格密封拍卖)让"报真实价"成为每个人的最优策略,于是没人需要揣摩别人。

一次信息级联:上排是每个人收到的私人信号,下排是他做出的选择

书里的结论

级联一旦形成,后面的人的选择不再包含任何信息,所以"大家都这么选"的证据价值远低于看起来的样子。信号准确率 65% 时,30 个人集体选错的概率仍有两三成。右图是机制设计的答案:第二价格拍卖里按真实估价出价是最优的,而第一价格拍卖里你必须猜别人。

用在生活里

  • 看到一边倒的评价,先问:他们是各自判断的,还是在跟前面的人?
  • 和人谈条件,优先设计一个"说实话就是最优"的规则,而不是博弈。
  • 情绪(愤怒、愧疚)是进化给人的承诺装置,让威胁和承诺可信。
结语 · COMPUTATIONAL KINDNESS

计算的善意

全书最后落在一个意外的地方:算法不是让人变成计算机,而是让人知道哪些问题本来就很难,然后对自己和别人宽容一点。

  1. 有些问题没有高效的精确解。旅行商、调度、博弈的均衡都是如此。你没找到完美答案,不是你的问题,是问题的问题。
  2. 近似、随机、提前停止,都是正当的策略。37% 法则有六成概率落空,模拟退火不保证最优,Miller-Rabin 只给概率上的确定。它们仍是已知最好的办法。
  3. 减少别人的计算量是一种善意。说"我想吃泰国菜"比说"随便"更体贴,因为后者把搜索的成本转嫁给了对方。给人两三个选项,不要给一份菜单。
  4. 减少自己的计算量也是。对 LRU 式的遗忘、对两栏式的决定、对一次随机的尝试,不必愧疚。
  5. 流程比结果更可控。按最优流程做了决定,结果不好,也不说明决定错了;这是书里反复出现的一句。

关于本页

内容按 Brian Christian 与 Tom Griffiths 所著 Algorithms to Live By: The Computer Science of Human Decisions(2016)整理,中译本《算法之美:指导工作与生活的算法》(中信出版集团,2018,万慧、胡小锐译)。Gittins 指数按书中设定(伯努利回报、均匀先验、折现 0.9)在页面内实时计算,与书中表格一致。各章的模拟器是对书中思想的演示,参数是我设的,不是书里的原始数据。