美文网首页复杂性思维 2e程序员我爱编程
复杂性思维中文第二版 九、基于智能体的模型

复杂性思维中文第二版 九、基于智能体的模型

作者: 布客飞龙 | 来源:发表于2018-04-12 11:37 被阅读60次

    九、基于智能体的模型

    原文:Chapter 9 Agent-based models

    译者:飞龙

    协议:CC BY-NC-SA 4.0

    自豪地采用谷歌翻译

    我们迄今为止看到的模型可能具有“基于规则”的特征,因为它们涉及受简单规则支配的系统。 在本章和以后的章节中,我们将探索基于智能体(agent)的模型。

    基于智能体的模型包含智能体,它旨在模拟人和其他实体,它们收集世界的信息,制定决策并采取行动。

    智能体通常位于空间或网络中,并在本地彼此交互。 他们通常有不完整的,不全面的世界信息。

    智能体之间经常存在差异,而不像以前的所有模型,它们的所有成分都相同。 基于智能体的模型通常包含智能体之间,或世界中的随机性。

    自 20 世纪 70 年代以来,基于智能体的模型已成为经济学和其他社会科学,以及一些自然科学中的重要工具。

    基于智能体的模型对非均衡系统的动态建模(尽管它们也用于研究均衡系统)非常有用。 它们对于理解个人决策和系统行为之间的关系特别有用。

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

    9.1 谢林模型

    1971 年,托马斯谢(Thomas Schelling)发表了《隔离的动态模型》(Dynamic Models of Segregation),该模型提出了种族隔离的简单模型。 谢林模型的世界是一个网格;每个细胞代表一栋房子。 房屋被两种智能体占用,标记为红色和蓝色,数量大致相同。 大约 10% 的房屋是空的。

    在任何时候,智能体可能会高兴或不高兴,这取决于领域中的其他智能体,每个房屋的“邻居”是八个相邻细胞的集合。在一个版本的模型中,如果智能体至少有两个像他们一样的邻居,智能体会高兴,但如果是一个或零,他们就会不高兴。

    模拟的过程是,随机选择一个智能体并检查他们是否高兴。 如果是这样,没有任何事情发生。如果不是,智能体随机选择其中一个未占用的细胞并移动。

    听到这种模型导致一些隔离,你可能不会感到惊讶,但是你可能会对这个程度感到惊讶。 很快,会出现相似智能体的群落。 随着时间的推移,这些群落会不断聚合,直到有少量的大型群落,并且大多数智能体生活在同质社区中。

    如果你不知道这个过程,只看到结果,你可能会认为智能体是种族主义者,但实际上他们都会在一个混合的社区感到非常高兴。 由于他们不愿意数量过大,所以在最坏的情况下,他们可能被认为是排外的。 当然,这些智能体是真实人物的过度简化,所以这些描述可能根本不恰当。

    种族主义是一个复杂的人类问题; 很难想象这样简单的模型可以揭示它。 但实际上,它提供了一个强有力论据,有关系统及其各部分之间关系的:如果你观察真实城市的隔离,你不能总结为,个人的种族主义是直接原因,或者,城市居民是种族主义者。

    当然,我们必须牢记这个论述的局限性:谢林模型证明了隔离的一个可能原因,但没有提到实际原因。

    9.2 谢林模型的实现

    为了实现谢林模型,我编写了另一个继承Cell2D的类:

    
    class Schelling(Cell2D):
    
        def __init__(self, n, m=None, p=0.5):
            self.p = p
            m = n if m is None else m
            choices = [0, 1, 2]
            probs = [0.1, 0.45, 0.45]
            self.array = np.random.choice(choices, (n, m), p=probs)
    

    参数nm是网格的维度,p是相似邻居比例的阈值。 例如,如果p = 0.5,也就是其邻居中少于 50% 为相同颜色,则智能体将不高兴。

    array是 NumPy 数组,其中每个细胞如果为空,则为 0;如果由红色智能体占用,则为1;如果由蓝色智能体占用,则为 2。 最初,10% 的细胞是空的,45% 为红色和 45% 为蓝色。

    谢林模型的step函数比以前的step函数复杂得多。 如果你对细节不感兴趣,你可以跳到下一节。 但是如果你坚持要看,你可能需要一些 NumPy 的提示。

    首先,我将生成逻辑数组,表明哪些细胞是红色,蓝色和占用的:

    
    a = self.array
    red = a==1
    blue = a==2
    occupied = a!=0
    

    我将使用np.correlate2d来计算,对于每个细胞,红色相邻细胞的数量和被占用的细胞数量。

    options = dict(mode='same', boundary='wrap')
    
    kernel = np.array([[1, 1, 1],
                       [1, 0, 1],
                       [1, 1, 1]], dtype=np.int8)
    
    num_red = correlate2d(red, kernel, **options)
    num_neighbors = correlate2d(occupied, kernel, **options)
    

    现在对于每个细胞,我们可以计算出红色的邻居比例和相同颜色的比例:

    
    frac_red = num_red / num_neighbors
    frac_blue = 1 - frac_red
    frac_same = np.where(red, frac_red, frac_blue)
    

    frac_red只是num_rednum_neighbors的比率,而frac_bluefrac_red的补。

    frac_same有点复杂。 函数np.where就像逐元素的if表达式一样。 第一个参数是从第二个或第三个参数中选择元素的条件。

    在这种情况下,如果redTruefrac_same获取frac_red的相应元素。 在红色为False的情况下,frac_same获取frac_blue的相应元素。

    现在我们可以确定不满意的智能体的位置:

    unhappy_locs = locs_where(occupied & (frac_same < self.p))
    

    结果unhappy_locs是一个 NumPy 数组,其中每行都是占用的细胞的坐标,其中frac_same低于阈值p

    locs_wherenp.nonzero的包装函数:

    def locs_where(condition):
        return np.transpose(np.nonzero(condition))
    

    np.nonzero接受一个数组并返回所有非零元素的坐标,但结果是两个元组的形式。 np.transpose将结果转换为更有用的形式,即每行都是坐标对的数组。

    同样,empty_locs是一个数组,包含空细胞的坐标:

    empty_locs = locs_where(a==0)
    

    现在我们到达了模拟的核心。 我们遍历不高兴的智能体并移动它们:

    for source in unhappy_locs:
        i = np.random.randint(len(empty_locs))
        dest = tuple(empty_locs[i])
        a[dest] = a[tuple(source)]
        a[tuple(source)] = 0
        empty_locs[i] = source
    

    i是一个用来随机选择空细胞的索引。

    dest是一个包含空细胞的坐标的元组。

    为了移动智能体,我们将值从source复制到dest,然后将source的值设置为 0(因为它现在是空的)。

    最后,我们用source替换empty_locs中的条目,以便刚刚变为空的细胞可以由下一个智能体选择。

    9.3 隔离

    image

    图 9.1:谢林的隔离模型,n = 100,初始条件(左),2 步后(中)和 10 步后(右)

    现在让我们看看我们运行模型时会发生什么。 我将以n = 100p = 0.3开始,并运行 10 个步骤。

    grid = Schelling(n=100, p=0.3)
    for i in range(10):
        grid.step()
    

    图?展示了初始状态(左),2 步(中)后和 10 步(右)后的模拟。

    群落迅速形成,红色和蓝色的智能体移动到隔离集群中,它们由空细胞的边界分隔。

    对于每种状态,我们可以计算隔离度,它是相同颜色的邻居的比例。在所有细胞中的平均值:

    np.sum(frac_same) / np.sum(occupied)
    

    在图?中,相似邻居的比例均值在初始状态中为 55%,两步后为 71%,10 步后为 80%!

    请记住,当p = 0.3时,如果 8 个邻居中的 3 个是他们自己的颜色,那么智能体会很高兴,但他们最终居住在一个社区中,其中 6 或 7 个邻居是自己的颜色。

    image

    图 9.2:随着时间的推移,谢林模型中的隔离程度,范围为p

    图?显示了隔离程度如何增加,以及它在几个p值下的平稳位置。 当p = 0.4时,稳定状态下的隔离程度约为 88%,且大多数智能体没有不同颜色的邻居。

    这些结果令许多人感到惊讶,它们成为了个人决策与系统行为之间的,复杂且不可预测的关系的鲜明示例。

    9.4 糖域

    1996年,约书亚爱泼斯坦(Joshua Epstein)和罗伯特阿克斯特尔(Robert Axtell)提出了糖域(Sugarscape),这是一个“人造社会”的智能体模型,旨在支持经济学和其他社会科学的相关实验。

    糖域是一款多功能的模型,适用于各种主题。 作为例子,我将复制 Epstein 和 Axtell 的书《Growing Artificial Societies》的前几个实验。

    糖域最简单的形式是一个简单的经济模型,智能体在二维网格上移动,收集和累积代表经济财富的“糖”。 网格的一些部分比其他部分产生更多的糖,并且一些智能体比其他人更容易找到它。

    这个糖域的版本常用于探索和解释财富的分布,特别是不平等的趋势。

    在糖域的网格中,每个细胞都有一个容量,这是它可容纳的最大糖量。 在原始状态中,有两个高糖区域,容量为 4,周围是同心环,容量分别为 3, 2 和 1。

    image

    图 9.3:原始糖域模型的复制品:初始状态(左),2 步后(中)和 100 步后(右)。

    图?(左)展示了初始状态,最黑暗的区域表示容量最高的细胞,小圆圈表示智能体。

    最初有随机放置的 400 个智能体。 每个智能体有三个随机选择的属性:

    糖:

    每个智能体最开始都有先天的糖分,从 5 到 25 之间均匀选择。

    代谢:

    在每个时间步骤中,每个智能体都必须消耗一定数量的糖,从 1 到 4 之间均匀选择。

    视力:

    每个智能体可以“看到”附近细胞中糖量,并移动到最多的细胞,但是与其它智能体相比,一些智能体可以看到更远的细胞。 智能体看到的距离从 1 和 6 之间均匀选择。

    在每个时间步骤中,智能体以随机顺序一次移动一格。 每个智能体都遵循以下规则:

    • 智能体在 4 个罗盘方向的每一个方向上调查k个细胞,其中k是智能体的视野范围。
    • 它选择糖分最多的未占用的细胞。 在相等的情况下,选择较近的细胞;在距离相同的细胞中,它随机选择。
    • 智能体移动到选定的细胞并收获糖分,将收获增加到其积累的财富并将细胞清空。
    • 智能体根据代谢消耗其财富的一部分。 如果结果总量为负数,智能体“饿死”并被删除。

    在所有智能体完成这些步骤之后,细胞恢复一些糖,通常为 1 单位,但每个细胞中的总糖分受其容量限制。

    图?(中)显示两步后模型的状态。 大多数智能体正在移到糖最多的地区。 视力高的智能体移动速度最快;视力低的智能体往往会卡在高原上,随机游走,直到它们足够接近来看到下一个水平。

    出生在糖分最少的地区的智能体可能会饿死,除非他们的视力很好,先天条件也很高。

    在高糖地区,随着糖分的出现,智能体相互竞争,寻找和收获糖分。 消耗高或视力低的智能体最有可能挨饿。

    当糖在每个时间步骤增加 1 个单位时,就没有足够的糖来维持我们开始的 400 个智能体。 人口起初迅速下降,然后缓慢下降,在大约 250 左右停下。

    图?(右)显示了 100 个时间步后的模型状态,大约有 250 个智能体。 存活的智能体往往是幸运者,出生时视力高和/或代消耗低。 存活到这里的话,它们可能会永远存活,积累无限量的糖。

    9.5 财富的不平等

    在目前的形式下,糖域建立了一个简单的生态学模型,可用于探索模型参数之间的关系,如增长率和智能体的属性,以及系统的承载能力(在稳定状态下生存的智能体数量)。 它模拟了一种形式的自然选择的,“适应度”较高的智能体更有可能生存下来。

    该模型还表现出一种财富不平等,一些智能体积累糖的速度比其他智能体快。 但是对于财富分布,很难说具体的事情,因为它不是“静止的”。 也就是说,分布随着时间的推移而变化并且不会达到稳定状态。

    然而,如果我们给智能体有限的寿命,这个模型会产生固定的财富分布。 然后我们可以运行实验,来查看参数和规则对此分布的影响。

    在这个版本的模型中,智能体的年龄在每个时间步增加,并且从 60 到 100 之间的均匀分布中,随机选择一个寿命。如果智能体的年龄超过其寿命,它就会死亡。

    当智能体因饥饿或年老而死亡时,它由属性随机的新智能体所取代,所以总人口是不变的。

    image

    图 9.4:100, 200, 300 和 400 步(灰线)和 500 步(黑线)之后的糖(财富)的分布。 线性刻度(左)和对数刻度(右)。

    从接近承载能力的 250 个智能体开始,我运行了 500 个步骤的模型。 在每 100 步之后,我绘制了智能体积累的糖的分布。 图?在线性刻度(左)和对数刻度(右)中展示结果。

    经过大约 200 步(这是最长寿命的两倍)后,分布变化不大。 并且它向右倾斜。

    大多数智能体积累的财富很少:第 25 百分位数大约是 10,中位数大约是 20。但是少数智能体积累了更多:第 75 百分位数是大约 40,最大值大于 150。

    在对数刻度上,分布的形状类似于高斯或正态分布,但右尾被截断。 如果它在对数刻度上实际上是正态的,则分布是对数正态分布,这是一种重尾分布。 实际上,几乎每个国家和全世界的财富分布都是重尾分布。

    如果说糖域解释了为什么财富分布是重尾的,但是糖域变化中的不平等的普遍性表明,不平等是许多经济体的特征,甚至是非常简单的经济体。 一些实验表明避免或减轻并不容易,它们带有一些规则,对纳税和其他收入转移进行建模。

    9.6 实现糖域

    糖域比以前的模型更复杂,所以我不会在这里介绍整个实现。 我将概述代码的结构,你可以在 Jupyter 笔记本chap09.ipynb中查看本章的细节,它位于本书的仓库中。 如果你对细节不感兴趣,你可以跳到下一节。

    以下是带有step方法的Agent类:

    
    class Agent:
    
        def step(self, env):
            self.loc = env.look_around(self.loc, self.vision)
            self.sugar += env.harvest(self.loc) - self.metabolism
            self.age += 1
    

    在每个步骤中,智能体移动,收获糖,并增加年龄。

    参数env是环境的引用,它是一个Sugarscape对象。 它提供了方法look_around和收获:

    • look_around获取智能体的位置,这是一个坐标元组,以及智能体的视野,它是一个整数。 它返回智能体的新位置,这是糖分最多的可见细胞。
    • harvest需要智能体的(新)位置,并在移除并返回该位置的糖分。

    这里是Sugarscape类和它的step方法(不需要替换):

    class Sugarscape(Cell2D):
    
        def step(self):
    
            # loop through the agents in random order
            random_order = np.random.permutation(self.agents)
            for agent in random_order:
    
                # mark the current cell unoccupied
                self.occupied.remove(agent.loc)
    
                # execute one step
                agent.step(self)
    
                # if the agent is dead, remove from the list
                if agent.is_starving():
                    self.agents.remove(agent)
                else:
                    # otherwise mark its cell occupied
                    self.occupied.add(agent.loc)
    
            # grow back some sugar
            self.grow()
            return len(self.agents)
    

    Sugarscape继承自Cell2D,因此它与我们所见过的其他基于网格的模型相似。

    这些属性包括agents,它是Agent对象的列表,以及occupied,它是一组元组,其中每个元组包含智能体占用的细胞的坐标。

    在每个步骤中,Sugarscape以随机顺序遍历智能体。 它调用每个智能体的step,然后检查它是否已经死亡。 所有智能体都移动后,一些糖会恢复。

    如果你有兴趣更加了解 NumPy ,你可能需要仔细看看make_visible_locs,它构建一个数组,其中每行包含智能体可见的细胞坐标,按距离排序,但距离相同的细胞 是随机顺序。

    你可能想看看Sugarscape.make_capacity,它初始化细胞的容量。 它演示了np.meshgrid的使用,这通常很有用,但需要一些时间才能理解。

    9.7 迁移和波动行为

    image

    图 9.5:Sugarscape中的波动行为:初始状态(左),6 步后(中)和 12 步后(右)

    虽然Sugarscape的主要目的不是探索空间中的智能体的移动,但 Epstein 和 Axtell 在智能体迁移时,观察到一些有趣的模式。

    如果我们开始把所有智能体放在左下角,他们会迅速走向最近的高容量细胞的“山峰”。 但是如果有更多的智能体,单个山峰不足以支持它们的话,他们很快就会耗尽糖分,智能体被迫进入低容量地区。

    视野最长的那些,首先穿过山峰之间的山谷,并且像波一样向东北方向传播。 因为他们在身后留下一些空细胞,所以其他智能体不会追随,直到糖分恢复。

    结果是一系列离散的迁移波,每个波都像一个连贯的物体,就像我们在规则 110 CA 和生命游戏中看到的飞船(参见第?节)。

    图?显示了初始条件下(左),6 个步骤(中)和 12 个步骤(右)之后的模型状态。 你可以看到,前两个波到达并穿过第二个山峰,留下了一串空细胞。 你还可以看到这个模型的动画版本,其中波形更清晰可见。

    虽然这些波动由智能体组成,但我们可以将他们视为自己的实体,就像我们在“生命游戏”中想到的滑翔机一样。

    这些波动的一个有趣的属性是,它们沿对角线移动,这可能是令人惊讶的,因为这些智能体本身只是向北或向东移动,从不向东北方移动。 像这样的结果 - 团队或“集合”拥有智能体没有的属性和行为 - 在基于智能体的模型中很常见。 我们将在下一章看到更多的例子。

    9.8 涌现

    本章中的例子展示了复杂性科学中最重要的想法之一:涌现。 涌现性是系统的一个特征,由它的成分相互作用而产生,而不是它们的属性。

    为了澄清什么是涌现,考虑它不是什么会有帮助。 例如,砖墙很硬,因为砖和砂浆很硬,所以这不是涌现。 再举一个例子,一些刚性结构是由柔性部件构成的,所以这看起来像是一种涌现。 但它至多是一种弱例,因为结构特性遵循已知的力学定律。

    相反,我们在谢林模型中看到的隔离是一种涌现,因为它不是由种族主义智能体造成的。 即使智能体只是轻微排外,系统的结果与智能体的决策意图有很大不同。

    糖域中的财富分配可能是涌现,但它是一个弱例,因为我们可以根据视力,代谢和寿命的分布合理预测它。 我们在最后一个例子中看到的波动行为可能是一个更强的例子,因为波动显示出智能体显然没有的能力 - 对角线运动。

    涌现性令人惊讶:即使我们知道所有规则,也很难预测系统的行为。难度不是偶然的;事实上,它可能是涌现的决定性特征。

    正如沃尔夫勒姆在“新科学”中所讨论的那样,传统科学是基于这样的公理:如果你知道管理系统的规则,那么你可以预测它的行为。 我们所谓的“法律”通常是计算的捷径,它使我们能够预测系统的结果而不用建立或观察它。

    但是许多细胞自动机在计算上是不可减少的,这意味着没有捷径。 获得结果的唯一方法是实现该系统。

    一般而言,复杂系统可能也是如此。 对于具有多个成分的物理系统,通常没有产生解析解的模型。 数值方法提供了一种计算捷径,但仍存在质的差异。

    解析解通常提供用于预测的恒定时间算法;也就是说,计算的运行时间不取决于预测的时间尺度t。 但数值方法,模拟,模拟计算和类似方法需要的时间与t成正比。 对于许多系统来说,我们无法计算出可靠的预测。

    这些观察表明,涌现性基本上是不可预测的,对于复杂系统我们不应该期望,通过计算捷径来找到自然规律。

    对某些人来说,“涌现”是无知的另一个名字; 根据这种思维,如果我们针对它没有还原论的解释,那么这个属性就是涌现的,但如果我们在将来更好地理解它,它就不再是涌现的。

    涌现性的状况是有争议的话题,所以对此持怀疑态度是恰当的。 当我们看到明显的涌现性时,我们不应该假设永远不会有还原论解释。但我们也不应该假设必须有。

    本书中的例子和计算等价原理提供了很好的理由,认为至少有些涌现性永远不会被古典还原论模型“解释”。

    你可以在这里更加了解涌现:http://en.wikipedia.org/wiki/Emergence

    9.9 练习

    练习 1

    本章的代码位于本书仓库的 Jupyter 笔记本chap09.ipynb中。打开这个笔记本,阅读代码,然后运行单元格。你可以使用这个笔记本来练习本章的练习。我的解决方案在chap09soln.ipynb中。

    练习 2

    《The Big Sort》的作者 Bill Bishop 认为,美国社会越来越由政见所隔离,因为人们选择生活在志趣相投的邻居之中。

    Bishop 所假设的机制并不是像谢林模型中的智能体那样,如果他们是孤立的,他们更有可能移动,但是当他们出于任何原因移动时,他们可能会选择一个社区,其中的人与他们自己一样。

    修改谢林模型的实现来模拟这种行为,看看它是否会产生类似程度的隔离。

    有几种方法可以模拟 Bishop 的假设。在我的实现中,随机选择的智能体会在每个步骤中移动。每个智能体考虑k个随机选择的空位置,并选择相似邻居的比例最高的位置。隔离程度和k有什么关系?

    练习 3

    在糖域的第一个版本中,我们从不添加智能体,所以一旦人口下降,它就不会恢复。 在第二个版本中,我们只是在智能体死亡时才取代,所以人口是不变的。 现在让我们看看如果我们增加一些“人口压力”会发生什么。

    编写糖域的一个版本,在每一步结束时添加一个新的智能体。 添加代码来计算每个步骤结束时,智能体的平均视力和平均消耗。 运行模型几百步,绘制人口,平均视力和平均消耗随时间的变化。

    你应该能够通过继承SugarScape并覆盖__init__step来实现这个模型。

    练习 4

    在心灵哲学中,强人工智能是这样的理论,即受到适当编程的计算机可以拥有思想,与人类拥有的思想相同。

    约翰·塞尔(John Searle)提出了一个名为“中文房间”的思想实验,旨在表明强 AI 是虚假的。 你可以在 http://en.wikipedia.org/wiki/Chinese_room 上阅读。

    对中文房间的论述的系统回复是什么? 你对涌现的认识如何影响你对系统回复的反应?

    相关文章

      网友评论

        本文标题:复杂性思维中文第二版 九、基于智能体的模型

        本文链接:https://www.haomeiwen.com/subject/zojxkftx.html