2018/4/15 15:02:29当前位置推荐好文程序员浏览文章

十二、合作进化

原文:Chapter 12 Evolution of cooperation

译者:飞龙

协议:CC BY-NC-SA 4.0

自豪地采消耗谷歌翻译

在最后一章中,我们提出两个问题,一个来自生物学,一个来自哲学:

  • 在生物学中,“利他主义问题”是自然选择与利他主义之间的显著冲突,自然选择表明动物生存在不断竞争的状态中来生存和繁殖,利他主义是许多动物帮助其余动物的倾向,甚至是显然对他们不利。见 https://en.wikipedia.org/wiki/Altruism_(biology)。
  • 在道德哲学中,人性问题是,人类能否从根本上是善良的,或者者邪恶的,或者者是由环境塑造的空白状态。见 https://en.wikipedia.org/wiki/Human_nature。

我们将消耗来处理这些问题的工具,(同样)是基于智可以体的模拟和博弈论,博弈论是一组笼统模型,旨在形容智可以体交互的各种方式。具体来说,我们会考虑囚徒困境。

本章的代码位于chap12.ipynb中,该书是本书仓库中的Jupyter笔记本。使消耗此代码的更多信息,请参见第?节。

12.1 囚徒困境

囚徒困境是博弈论中的一个话题,但它不是一种有趣的博弈。相反,这种博弈揭示了人类的动机和行为。以下是来自维基百科的它的详情(http://en.wikipedia.org/wiki/Prisoners_dilemma):

两名犯罪团伙成员被逮捕并囚禁。每个囚犯都被单独监禁,无法与另一方交流。检察官缺乏足够的证据,来证实这两个人的主要指控。他们希望以较轻的指控被判处两年徒刑。同时,检察官为每个囚犯提供商量的余地。每个囚犯都有机会:(1)通过证实对方犯罪出卖对方,或者(2)通过保持沉默与另一方合作。出价是:

  • 假如 A 和 B 各自背叛对方,每个人都服刑 2 年。
  • 假如 A 背叛 B 但 B 保持沉默,A 将被释放,B 将被监禁 3 年(反之亦然)。
  • 假如 A 和 B 都保持沉默,他们两人只会服刑 1 年(较轻的质控)。

很显然,这种情况是假想的,但它消耗于代表各种不同的互动,其中智可以体必需选择是相互“合作”还是“背叛”,以及每个智可以体的奖励(或者惩罚)取决于他人的选择。

有了这套奖惩,我们很有可可以说智可以体应该合作,也就是说,双方都应该保持沉默。 但两个智可以体不知道对方会做什么,所以每个人都必需考虑两种可可以的结果。 首先,从 A 的角度来看它:

  • 假如 B 保持沉默,A 最好是背叛;他会无罪而不是服刑 1 年。
  • 假如 B 背叛,A 最好也是背叛;他只会服刑 2 年而不是 3 年。

不论 B 做什么,A 最好都是背叛。 而且由于博弈是对称的,所以从 B 的角度来看这个分析是一样的:不论 A 做什么,B 最好也是背叛。

在这个博弈的最简单版的本中,我们假设 A 和 B 没有考虑其余因素。 他们不可以互相沟通,所以他们不可以协商,作出承诺或者相互威胁。 他们只考虑直接目标,最小化他们的判决;他们不考虑任何其余因素。

在这些假设下,两个智可以体的理性选择都是背叛。 这可可以是一件好事,至少在刑事司法方面是这样。 但对囚犯来说,这令人沮丧,由于显然,他们无法取得他们双方都想要的结果。 而且这种模式适消耗于现实生活中的其余场合,其中合作有更大的好处以及对于玩家来说都会更好。

研究这些场景以及摆脱困境的方法,博弈论研究者关注的焦点,但这不是本章的重点。 我们正朝着不同的方向前进。

12.2 善良的问题

自 20 世纪 50 年代,囚徒困境被初次探讨以来,它一直是社会心理学研究的热门话题。根据前一节的分析,我们能说一个理想的智可以体应该做什么; 很难预测真正的人到底做了些什么。 幸运的是,试验已经完成了 [1]。

[1] 这里有一个最近的报告,提到以前的试验:Barreda-Tarrazona, Jaramillo-Gutiérrez, Pavan, Sabater-Grande, “Individual Characteristics vs. Experience: An Experimental Study on Cooperation in Prisoner’s Dilemma", Frontiers in Psychology, 2017; 8: 596. https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5397528/。

假如我们假设人们足够聪明地进行分析(或者者在解释时了解它),并且他们通常为了自己的利益而行事,那么我们估计他们几乎总是背叛。 但他们没有。 在大多数试验中,受试者的合作远远超过理性的智可以体模型的预测 [2]。

[2] 有个不错的视频归纳了我们目前探讨的内容:https://www.youtube.com/watch?v=t9Lo2fgxWHw。

这个结果最显著的解释是,人们不是理性的智可以体,这对任何人都不应该感到惊讶。 但为什么不是呢? 是由于他们不够聪明,无法了解这种情况,还是由于他们成心违反自己的利益行事?

根据试验结果,似乎至少有一部分解释是纯粹的利他主义:许多人愿意为了让别人受益而承担成本。现在,在你提出《Journal of Obvious Results》上发表的结论之前,让我们继续问为什么:

  • 为什么人们会帮助别人,即便自己会付出代价?至少部分起因是他们想这样;这让他们对自己和世界感觉良好。
  • 为什么善良让人感觉良好?诱人的说法是,有人跟他们提出这是正确的,或者者更普遍来说,他们被社会训练为想要做好事。但毫无疑问 [3],至少有一大部分利他主义是天生的;在不同程度上,利他主义的倾向是正常大脑发育的结果。
  • 那么,为什么呢?大脑发育的内在部分,以及随后的个体特征,是基因的结果。当然,基因与利他主义的关系是复杂的,可可以有许多基因与环境因素相互作消耗,导致人们在不同情况下或者多或者少是无私的。虽然如此,几乎能一定的是基因导致人们变得无私。
  • 最后,为什么呢?假如在自然选择下,动物为了生存和繁殖而彼此不断竞争,似乎显然利他主义会适得其反。在一个种群中,有些人帮助别人,甚至是为别人伤害自己,其余人纯粹是自私的,似乎自私者会受益,利他者会受到影响,并且利他主义的基因将被驱逐而灭绝。

[3] 我希望你可以原谅我在这里消耗“毫无疑问”代替试验的参考资料,我想在本章中详情少量理由,而不会陷入太深。

这个显著的矛盾是“利他主义问题”:为什么利他主义的基因没有消失?

在生物学家中,有很多可可以的解释,包括互惠利他主义,性选择,亲属选择和群体选择。而在非科学家中,还有更多的解释。我把它交给你去探究别的假说;现在我想专注于一种解释,能说是最简单的一种解释:也许利他主义是适应性的。换句话说,利他主义的基因可可以使人们更容易生存和繁殖。

事实证实,引发利他主义问题的囚徒困境,也可可以有助于处理问题。

12.3 囚徒困境比赛

在 20 世纪 70 年代后期,密歇根大学的政治学家罗伯特阿克塞尔罗德(Robert Axelrod)组织了一场比赛来比较囚徒困境(PD)的策略。

他邀请参加者以计算机程序的形式提交策略,而后相互对抗并保持得分。具体来说,他们玩的是 PD 的迭代版的本,其中智可以体针对同一对手进行多轮比赛,因而他们的决定能基于历史。

在 Axelrod 的比赛中,一个简单的策略出人预料地好,称为“针锋相对”,即 TFT,TFT 在第一轮迭代比赛中总是合作;之后,它会复制上一轮对手所做的任何事情。对手继续合作,TFT 保持合作,假如对手任何时候都背叛,下一轮 TFT 背叛,但假如对手变回合作,TFT 也会合作。

这些比赛的更多信息,以及 TFT 为何如此出色的解释,请参阅以下视频:https://www.youtube.com/watch?v=BOvAbjfJ0x0。

看看这些比赛中体现出色的策略,Alexrod 发现了他们倾向于分享的特点:

  • 善良:体现好的策略在第一轮比赛中合作,并且通常会在随后的几轮中合作。
  • 报复:始终合作的策略,并不如假如对手背叛就报复的策略好。
  • 宽恕:但是过于斗气的策略往往会惩罚自己以及对手。
  • 不嫉妒:少量最成功的策略很少超过对手;他们成功了,由于他们对各种各样的对手都做得足够好。

TFT 具备所有这些属性。

Axelrod 的比赛为利他主义问题提供了部分可可以的答案:也许利他主义的基因是普遍存在的,由于它们是适应性的。 许多社会互动能建模为囚徒困境的变种,就这种程度而言,假如将一个大脑设定为善良,平衡报复和宽恕,就会在各种各样的情况下体现良好。

但是 Axelrod 比赛中的策略是由人们设计的;他们并不进化。 我们需要考虑,善良、报复和宽恕的基因能否能通过突变出现,成功侵入其余策略的种群,并抵制后续突变的侵入。

12.4 合作进化的模拟

合作进化是第一本书的标题,Axelrod 展现了来自囚徒困境比赛的结果,并探讨了利他主义问题的影响。 从那以后,他和其余研究人员已经探究了 PD 比赛的进化动态性,也就是说,PD 选手的总体中,策略的分布随时间如何变化。 在本章的其他部分中,我运行这些试验的一个版的本并展现结果。

首先,我们需要一种将 PD 策略编码为基因型的方法。 在这个试验中,我考虑了少量策略,其中智可以体每一轮的选择仅取决于前两轮中对手的选择。 我消耗字典来表示策略,它将对手的前两个选择映射为智可以体的下一个选择。

以下是这些智可以体的类定义:

class Agent:    keys = [(None, None),            (None, C),            (None, D),            (C, C),            (C, D),            (D, C),            (D, D)]    def __init__(self, values, fitness=np.nan):        self.values = values        self.responses = dict(zip(self.keys, values))        self.fitness = fitness

keys是每个智可以体的词典中的键序列,其中元组(C, C)表示对手在前两轮合作;(None, C)意味着只有一轮比赛并且对手合作;(None, None)表示还没有回合。

__init__方法中,values是对应于键的一系列选项,C或者D。 所以假如值的第一个元素是C,那就意味着这个智可以体将在第一轮合作。 假如值的最后一个元素是D,那么假如对手在前两轮中背叛,该智可以体将会背叛。

在这个实现中,总是背叛的智可以体的基因型是DDDDDDD; 总是合作的智可以体的基因型是CCCCCCC,而 TFT 的基因型是CCDCDCD

Agent类提供copy,它使其它智可以体具备相同的基因型,但具备肯定的变异概率:

prob_mutate = 0.05def copy(self):    if np.random.random() > self.prob_mutate:        values = self.values    else:        values = self.mutate()    return Agent(values, self.fitness)

突变的原理是,在基因型中选择一个随机值并从C翻转到D,或者者相反:

def mutate(self):    values = list(self.values)    index = np.random.choice(len(values))    values[index] = C if values[index] == D else D    return values

既然我们有了智可以体,我们还需要比赛。

12.5 Tournament

Tournament类封装了 PD 比赛的细节:

payoffs = {(C, C): (3, 3),           (C, D): (0, 5),           (D, C): (5, 0),           (D, D): (1, 1)}num_rounds = 6def play(self, agent1, agent2):    agent1.reset()    agent2.reset()    for i in range(self.num_rounds):        resp1 = agent1.respond(agent2)        resp2 = agent2.respond(agent1)        pay1, pay2 = self.payoffs[resp1, resp2]        agent1.append(resp1, pay1)        agent2.append(resp2, pay2)    return agent1.score, agent2.score

payoffs是一个字典,将从智可以体的选择映射为奖励。例如,假如两个智可以体合作,他们每个得到 3 分。假如一个背叛而另一个合作,背叛者得到 5 分,而合作者得到 0 分。假如他们都背叛,每个都会得到 1 分。这些是 Axelrod 在他的比赛中使消耗的收益。

play运行几轮 PD 游戏。它使消耗Agent类中的以下方法:

  • reset:在第一轮之前初始化智可以体,重置他们的分数和他们的回应的历史记录。
  • respond:考虑到对手之前的回应,向每个智可以体讯问回应。
  • append:通过存储选项,并将连续轮次的分数相加,来升级每个智可以体。

在给定的回合数之后,play将返回每个智可以体的总分数。我选择了num_rounds = 6,以便每个基因型的元素都以大致相同的频率访问。第一个元素仅在第一轮访问,或者在六分之一的时间内访问。接下来的两个元素只可以在第二轮中访问,或者者每个十二分之一。最后四个元素在六分之一时间内访问,平均每次访问六次,或者者平均每个六分之一。

Tournament提供了第二种方法,即melee,确定哪些智可以体互相竞争:

def melee(self, agents, randomize=True):    if randomize:        agents = np.random.permutation(agents)    n = len(agents)    i_row = np.arange(n)    j_row = (i_row + 1) % n    totals = np.zeros(n)    for i, j in zip(i_row, j_row):        agent1, agent2 = agents[i], agents[j]        score1, score2 = self.play(agent1, agent2)        totals[i] += score1        totals[j] += score2    for i in i_row:        agents[i].fitness = totals[i] / self.num_rounds / 2

melee接受一个智可以体列表和一个布尔值randomize,它决定了每个智可以体每次能否与同一邻居竞争,或者者匹配能否随机化。

i_rowj_row包含匹配的索引。 totals包含每个智可以体的总分数。

在循环内部,我们选择两个智可以体,调消耗play和升级totals。 最后,我们计算每个智可以体取得的,每轮和每个对手的平均点数,并将结果存储在每个智可以体的fitness属性中。

12.6 Simulation

本章的Simulation类基于第?章的中的那个;唯一的区别是__init__step

这是__init__方法:

class PDSimulation(Simulation):    def __init__(self, tournament, agents):        self.tournament = tournament        self.agents = np.asarray(agents)        self.instruments = []

Simulation对象包含一个Tournament对象,一系列的智可以体和一系列的Instrument对象(就像第?章中一样)。

以下是step方法:

def step(self):    self.tournament.melee(self.agents)    Simulation.step(self)

此版的本的step使消耗Tournament.melee,它为每个智可以体设置fitness属性;而后它调消耗父类的step方法,父类来自第?章:

# class Simulation    def step(self):        n = len(self.agents)        fits = self.get_fitnesses()        # see who dies        index_dead = self.choose_dead(fits)        num_dead = len(index_dead)        # replace the dead with copies of the living        replacements = self.choose_replacements(num_dead, fits)        self.agents[index_dead] = replacements        # any instruments        self.update_instruments()

Simulation.step将智可以体的适应性收集到一个数组中; 而后它会调消耗choose_dead来决定哪些智可以体死掉,并消耗choose_replacements来决定哪些智可以体繁殖。

我的模拟包含生存差异,就像第?章那样,但不包括繁殖差异。 你能在本章的笔记本上看到细节。 作为练习之一,你将有机会探究繁殖差异的效果。

12.7 结果

假设我们从三个智可以体开始:一个总是合作,一个总是背叛,另一个执行 TFT 策略。 假如我们在这个种群中运行Tournament.melee,合作者每轮取得 1.5 分,TFT 智可以体取得 1.9 分,而背叛者取得 3.33 分。 这个结果表明,“总是背叛”应该很快成为主导策略。

但是“总是缺陷”包含着自我破坏的种子,假如更好的策略被驱使而灭绝,那么背叛者就没有人能利消耗,他们的适应性下降,并且容易受到合作者的入侵。

根据这一分析,预测系统的行为不容易:它会找到一个稳固的平衡点,还是在基因型景观的各个位置之间振荡? 让我们运行模拟来发现它!

我以 100 个始终背叛的相同智可以体开始,并运行 5000 个步骤的模拟:

tour = Tournament()agents = make_identical_agents(100, list(DDDDDDD))sim = PDSimulation(tour, agents)
image

图 12.1:平均适应性(囚徒困境的每个回合的所得点数)

图?展现了随时间变化的平均适应性(使消耗第?章的MeanFitness仪器)。最初平均适应性是 1,由于当背叛者面对对方时,他们每轮只可以得到 1 分。

经过大约 500 个时间步,平均适应性添加到近 3,这是合作者面对彼此时得到的。但是,正如我们所怀疑的那样,这种情况不稳固。在接下来的 500 个步骤中,平均适应性下降到 2 以下,回到 3,并继续振荡。

模拟的其他部分变化很大,但除了一次大的下降之外,平均适应性通常在 2 到 3 之间,长期平均值接近 2.5。

而且这还不错!它不是一个合作的乌托邦,每轮平均得 3 分,但距离始终背叛的乌托邦还很远。这比我们所期待的,自利智可以体的自然选择要好得多。

为了深入理解这种适应性水平,我们来看看更多的仪器。Niceness在每个时间步骤之后测量智可以体的基因型的合作比例:

class Niceness(Instrument):    def update(self, sim):        responses = np.array([agent.values                              for agent in sim.agents])        metric = np.mean(responses == C)        self.metrics.append(metric)
image

图 12.2:种群中所有基因组的平均友善度(左)和第一轮合作的种群比例(右)

图?(左图)展现结果:平均友善度从 0 迅速上升到 0.75,而后在 0.4 到 0.85 之间波动,长期平均值接近 0.65。 同样,这相当好!

具体看开始的移动,我们能追踪第一轮合作的智可以体的比例。 这是这个仪器:

class Retaliating(Instrument):    def update(self, sim):        after_d = np.array([agent.values[2::2]                            for agent in sim.agents])        after_c = np.array([agent.values[1::2]                            for agent in sim.agents])        metric = np.mean(after_d==D) - np.mean(after_c==D)        self.metrics.append(metric)

报复行为将所有基因组中的元素数量,其中对手背叛后智可以体也背叛(元素 2, 4 和 6),与其中的元素数量,其中对手合作后智可以体背叛相比较。正如你现在的预期,结果差异很大(你能在笔记本中看到图形)。平均而言,这些分数之间的差异小于 0.1,所以假如智可以体在对手合作后,30% 的时间中背叛,他们可可以会在背叛后的 40% 时间中背叛。

这个结果为这个断言提供了较弱的支持,即成功的策略会报复。也许所有智可以体甚至很多智可以体都没有必要进行报复;假如整个种群中至少存在肯定的报复倾向,那么这可可以足以阻止高度报复策略的普及。

为了衡量宽恕,我再次定义了一个工具,来查看在前两轮之后,智可以体能否更有可可以在 D-C 之后进行合作,与 C-D 相比。在我的模拟中,没有证据表明这种特殊的宽恕。另一方面,这些模拟中的策略在某种意义上是必然的宽容,由于它们只考虑前两轮的历史。

12.8 总结

Axelrod 的比赛提出理解决利他主义问题的一个可可以的处理办法:或者许善良,但不是太善良,是适应性的。但是原始比方中的策略是由人们,而不是进化论设计的,并且策略的分布在比赛过程中没有改变。

所以这就提出了一个问题:像 TFT 这样的策略可可以会在固定的人为设计策略中体现良好,但它们能否会进化?换句话说,他们能否能通过变异出现在种群中,与祖先竞争成功,并抵抗他们的后代的入侵?

本章中的模拟表明:

  • 背叛者种群容易受到更善良的策略的入侵。
  • 过于善良的种群容易受到背叛者的入侵。
  • 所以,善良的平均程度有所波动,但善良的平均数量普遍较高,而平均适应程度一般更接近合作乌托邦而不是偏差异议程度。
  • 在 Alexrod 的比赛中,TFT 是一项成功的战略,但对于不断发展的种群来说,这似乎不是一个最佳策略。事实上,可可以没有稳固的最佳策略。
  • 某种程度的报复可可以是适应性的,但对所有智可以体来说,可可以没有必要进行报复。 假如在整个种群中有足够的报复行为,这可可以足以防止背叛者入侵 [4]。

[4] 这就引入了博弈论中一个全新的话题 - 搭便车问题(见 https://en.wikipedia.org/wiki/Free-rider_problem)。

很显著,这些模拟中的智可以体很简单,而囚徒困境是一种有限范围的社交互动的高度笼统模型。 虽然如此,本章的结果对人性提供了少量见地。 也许我们对合作,报复和宽恕的倾向是天生的,至少部分是。 这些特征是我们的大脑的工作机制的结果,至少部分是由我们的基因控制的。 也许我们的基因这样来构建我们的大脑,由于在人类进化史上,自私的大脑的基因不太可可以传播。

所以也许这就是为什么自私基因会建立无私的大脑。

12.9 练习

本章的代码位于本书仓库的 Jupyter 笔记本chap12.ipynb中。打开笔记本,阅读代码并运行单元个。你能使消耗这个笔记原本练习本章的练习。我的处理方案在chap12soln.ipynb中。

练习 1

本章中的模拟取决于我任意选择的条件和参数。作为练习,我鼓励你去探究其余条件,看看他们对结果有什么影响。这里有少量建议:

  1. 改变初始条件:不要从所有背叛者开始,看看假如从所有合作者,所有 TFT 或者随机智可以体开始会发生什么。
  2. Tournament.melee中,我在每个时间步骤开始时洗牌,所以每个玩家对抗两个随机选择的玩家。假如你不洗牌会怎样样?在这种情况下,每个智可以体都会反复与相同的邻居进行比赛。这可可以会让少数人的战略,更容易通过利消耗局部性入侵大多数。
  3. 因为每个智可以体只与另外两个智可以体进行比赛,因而每轮比赛的结果都是非常不同的:在任何一轮比赛中,胜过大部​​分智可以体的智可以体可可以会运气不好,或者者相反。假如添加每个智可以体在每轮中的对手数量会发生什么?或者者假如在每一步结束时,智可以体的适应性是上一轮结束时其当前得分和适应性的平均值,会怎样样?
  4. 我为prob_survival函数选择的值从 0.7 到 0.9 不等,所以适应性最差的智可以体p = 0.7,生存了 3.33 个时间步骤,适应性最强的智可以体生存了 10 个。假如你使prob_survival更加或者更加不“激进”,会发生什么情况。
  5. 我选择了num_rounds = 6,以便基因组的每个元素比照赛的结果具备大致相同的影响。 但这比 Alexrod 在他的比赛中使消耗的值要小得多。 假如添加num_rounds会发生什么? 注意:假如你研究这个参数的效果,你可可以想修改Niceness来衡量基因组中最后4个元素的友善度,随着num_rounds的添加,它会受到更多的选择性压力。
  6. 我的实现拥有生存差异和随机繁殖。 假如增加繁殖差异会发生什么?

练习 2

在我的模拟中,种群从未收敛到一个状态,其中多数人共享相同的,据推测是最佳的基因型。对于这个结果有两种可可以的解释:一是没有最佳策略,由于无论何时种群被大多数基因型控制,这种状况为少数人入侵提供了机会;另一种可可以性是,突变率高到足以维持多种基因型,即便多数是非最佳的。为了辨别这些解释,请尝试降低突变率来查看发生了什么。或者者,从随机种群开始,并且不带突变来运行,直到只有一个基因型存活。或者者带突变来运行,直到系统达到稳固状态;而后关闭突变并运行,直到只有一个幸存的基因型。这些情况下基因型的特征是什么?

练习 3

我的试验中的智可以体是“反应型”的,由于他们在每轮中的选择只取决于对手在前几轮中的做法。考虑探究少量策略,它们也考虑到智可以体过去的选择。这样的策略将可以够区分报复性对手,和没有挑衅而背叛的对手。

网友评论