基于 Agent 的模型入门Python实现 读书笔记
来源:互联网 发布:网络用语小白什么意思 编辑:程序博客网 时间:2024/06/11 17:02
终于回归CSDN,打算这次坚持到底!立个FLAG!
曾经在美赛中生搬硬套了这个模型,现在终于得空,打算研究一下。
在计算机科学中,基于 Agent 的模型(agent-based models)被用来评估独立(autonomous)agent(诸如个体、群组或物体)在整个系统中的影响。这个强大的分析工具常被用在实验难以开展或者费用太高的时候。在社会科学,计算机科学,经济学和商务各领域,这个模型都有着相当广泛的应用。
1.案例
Schelling提出了基于Agent的模型来解释多民族城市的种族隔离形象。
2、Schelling 隔离模型:设置和定义
基于 Agent 的模型需要三个参数:1)Agents,2)行为(规则)和 3)总体层面(aggregate level)的评估。在 Schelling 模型中,Agents 是市民,行为则是基于相似比(similarity ratio )的搬迁,而总体评估评估就是相似比。
假设城市有 n 个种族。我们用唯一的颜色来标识他们,并用网格来代表城市,每个单元格则是一间房。要么是空房子,要么有居民,且数量为 1。如果房子是空的,我们用白色标识。如果有居民,我们用此人的种群颜色来标识。我们把每个人周边房屋(上下左右、左上右上、左下右下)定义为邻居。
Schelling 的目的是想测试当居民更倾向于选择同种族的邻居(甚至多种族)时会如果发生什么。如果同种族邻居的比例上升到确定阈值(称之为相似性阈值(Similarity Threshold)),那么我们认为这个人已经满意(satisfied)了。如果还没有,就是不满意。
Schelling 的仿真如下。首先我们将人随机分配到城里并留空一些房子。对于每个居民,我们都会检查他(她)是否满意。如果满意,我们什么也不做。但如果不满意,我们把他分配到空房子。仿真经过几次迭代后,我们会观察最终的种族分布。
3.模型的实现
需要的库·:
import matplotlib.pyplot as pltimport itertoolsimport randomimport copy接下来定义类:城市的宽和高,空房子的比例,相似性阈值,迭代数和种族数
class Schelling: def __init__(self,width,height,empty_ratio,similarity_threshold,n_iterations,races=2) self.width = width self.height = height self.races = races self.empty_ratio = empty_ratio self.similarity_threshold = similarity_threshold self.n_iterations = n_iterations self.empry_house = [] self.agents={}
def populate(self): self.all_house = list(itertools.product(range(self.width).range(self.height))) random.shuffle(self.all_houses) self.n_empty = int(self.empty_ratio*len(self.all_houses)) self.empty_houses = self.all_houses[self.n_empty] self.remaining_houses = self.all_houses[self.n_empty:] houses_by_race = [self.remaining_houses[i::self.races] for i in range(self.races)] for i in range(self.races): self.agents = dict(self.agents.items()+dict(zip(house_by_race[i],[i+1]*len(houses_by_race[i]))).items()is_unsatisfied 方法把房屋的 (x, y) 坐标作为传入参数,查看同种群邻居的比例,如果比理想阈值(happiness threshold)高则返回 True,否则返回 False。
def is_unsatisfied(self,x,y): race = self.agents[(x,y)] count_similar = 0 count_different = 0 if x>0 and y>0 and (x-1,y-1)not in self.empty_houses: if self.agents[(x-1,y-1)]==race: count_similar+=1 else: count_different+=1 if y>0 and (x,y-1)not in self.empty_houses: if self.agents[(x,y-1)]==race: count_similar+=1 else: count_different+=1 if x<(self.width-1) and y>0 and(x+1, y - 1) not in self.empty_houses: if self.agents[(x+1, y - 1)] == race: count_similar += 1 else: count_different += 1 if x > 0 and (x-1, y) not in self.empty_houses: if self.agents[(x-1, y)] == race: count_similar += 1 else: count_different += 1 if x <(self.width-1) and (x+1, y) not in self.empty_houses: if self.agents[(x+1, y)] == race: count_similar += 1 else: count_different += 1 if x > 0 and y<(self.height-1) and (x-1, y + 1) not in self.empty_houses: if self.agents[(x - 1, y + 1)] == race: count_similar += 1 else: count_different += 1 if x > 0 and y < (self.height - 1) and (x , y + 1) not in self.empty_houses: if self.agents[(x , y + 1)] == race: count_similar += 1 else: count_different += 1 if x <(self.width-1) and y < (self.height - 1) and (x + 1, y + 1) not in self.empty_houses: if self.agents[(x + 1, y + 1)] == race: count_similar += 1 else: count_different += 1 if(count_similar+count_different)==0: return False else: return float(count_similar)/(count_different+count_similar)<self.happy_threshold def update(self): for i in range(self.n_iterations): self.old_agents = copy.deepcopy(self.agents) n_changes = 0 for agent in self.old_agents: agent_race = self.agents[agent] empty_house = random.choice(self.empty_houses) self.agents[empty_house]=agent_race del self.agents[agent] self.empty_houses.remove(empty_house) self.empty_houses.append(agent) n_changes+= 1 print n_changes if n_changes == 0: breakupdate 方法将查看网格上的居民是否尚未满意,如果尚未满意,将随机把此人分配到空房子中。并模拟 n_iterations 次
def update(self): for i in range(self.n_iterations): self.old_agents = copy.deepcopy(self.agents) n_changes = 0 for agent in self.old_agents: if self.is_unhappy(agent[0], agent[1]): agent_race = self.agents[agent] empty_house = random.choice(self.empty_houses) self.agents[empty_house] = agent_race del self.agents[agent] self.empty_houses.remove(empty_house) self.empty_houses.append(agent) n_changes += 1 print n_changes if n_changes == 0: breakmove_to_empty 方法把房子坐标(x, y)作为传入参数,并将 (x, y) 房间内的居民迁入空房子。这个方法被 update 方法调用,会把尚不满意的人迁入空房子。
def move_to_empty(self, x, y): race = self.agents[(x,y)] empty_house = random.choice(self.empty_houses) self.updated_agents[empty_house] = race del self.updated_agents[(x, y)] self.empty_houses.remove(empty_house) self.empty_houses.append((x, y))
plot 方法用来绘制整个城市和居民。我们随时可以调用这个方法来了解城市的居民分布。这个方法有两个传入参数:title 和 file_name。
def plot(self, title, file_name): fig, ax = plt.subplots() # 如果要进行超过 7 种颜色的仿真,你应该相应地进行设置 agent_colors = {1:'b', 2:'r', 3:'g', 4:'c', 5:'m', 6:'y', 7:'k'} for agent in self.agents: ax.scatter(agent[0]+0.5, agent[1]+0.5, color=agent_colors[self.agents[agent]]) ax.set_title(title, fontsize=10, fontweight='bold') ax.set_xlim([0, self.width]) ax.set_ylim([0, self.height]) ax.set_xticks([]) ax.set_yticks([]) plt.savefig(file_name)
4. 仿真
现在我们实现了 Schelling 类,可以模拟仿真并绘制结果。我们会按照下面的需求(characteristics)进行三次仿真:
宽 = 50,而高 = 50(包含 2500 间房子)
30% 的空房子
相似性阈值 = 30%(针对仿真 1),相似性阈值 = 50%(针对仿真 2),相似性阈值 = 80%(针对仿真 3)
最大迭代数 = 500
种族数量 = 2
创建并“填充”城市。
schelling_1 = Schelling(50, 50, 0.3, 0.3, 500, 2)schelling_1.populate() schelling_2 = Schelling(50, 50, 0.3, 0.5, 500, 2)schelling_2.populate() schelling_3 = Schelling(50, 50, 0.3, 0.8, 500, 2)schelling_3.populate()
接下来,我们绘制初始阶段的城市。注意,相似性阈值在城市的初始状态不起作用
schelling_1_1.plot('Schelling Model with 2 colors: Initial State', 'schelling_2_initial.png')
schelling_1.update()schelling_2.update()schelling_3.update() schelling_1.plot('Schelling Model with 2 colors: Final State with Similarity Threshold 30%', 'schelling_2_30_final.png')schelling_2.plot('Schelling Model with 2 colors: Final State with Similarity Threshold 50%', 'schelling_2_50_final.png')schelling_3.plot('Schelling Model with 2 colors: Final State with Similarity Threshold 80%', 'schelling_2_80_final.png')
观察以上的绘图,我们可以发现相似性阈值越高,城市的隔离度就越高。此外,我们还会发现即便相似性阈值很小,城市依旧会产生隔离。换言之,即使居民非常包容(tolerant)(相当于相似性阈值很小),还是会以隔离告终。我们可以总结出:宏观所见并非微观所为。
5. 测量隔离
以上仿真,我们只通过可视化来确认隔离发生。然而,我们却没有对隔离的计算进行定量评估。本节我们会定义这个评估标准,我们也会模拟一些仿真来确定理想阈值和隔离程度的关系。
首先在 Schelling 类中添加 calculate_similarity 方法。这个方法会计算每个 Agent 的相似性并得出均值。我们会用平均相似比评估隔离程度。
def calculate_similarity(self): similarity = [] for agent in self.agents: count_similar = 0 count_different = 0 x = agent[0] y = agent[1] race = self.agents[(x,y)] if x > 0 and y > 0 and (x-1, y-1) not in self.empty_houses: if self.agents[(x-1, y-1)] == race: count_similar += 1 else: count_different += 1 if y > 0 and (x,y-1) not in self.empty_houses: if self.agents[(x,y-1)] == race: count_similar += 1 else: count_different += 1 if x < (self.width-1) and y > 0 and (x+1,y-1) not in self.empty_houses: if self.agents[(x+1,y-1)] == race: count_similar += 1 else: count_different += 1 if x > 0 and (x-1,y) not in self.empty_houses: if self.agents[(x-1,y)] == race: count_similar += 1 else: count_different += 1 if x < (self.width-1) and (x+1,y) not in self.empty_houses: if self.agents[(x+1,y)] == race: count_similar += 1 else: count_different += 1 if x > 0 and y < (self.height-1) and (x-1,y+1) not in self.empty_houses: if self.agents[(x-1,y+1)] == race: count_similar += 1 else: count_different += 1 if x > 0 and y < (self.height-1) and (x,y+1) not in self.empty_houses: if self.agents[(x,y+1)] == race: count_similar += 1 else: count_different += 1 if x < (self.width-1) and y < (self.height-1) and (x+1,y+1) not in self.empty_houses: if self.agents[(x+1,y+1)] == race: count_similar += 1 else: count_different += 1 try: similarity.append(float(count_similar)/(count_similar+count_different)) except: similarity.append(1) return sum(similarity)/len(similarity)
similarity_threshold_ratio = {}for i in [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7]: schelling = Schelling(50, 50, 0.3, i, 500, 2) schelling.populate() schelling.update() similarity_threshold_ratio[i] = schelling.calculate_similarity() fig, ax = plt.subplots()plt.plot(similarity_threshold_ratio.keys(), similarity_threshold_ratio.values(), 'ro')ax.set_title('Similarity Threshold vs. Mean Similarity Ratio', fontsize=15, fontweight='bold')ax.set_xlim([0, 1])ax.set_ylim([0, 1.1])ax.set_xlabel("Similarity Threshold")ax.set_ylabel("Mean Similarity Ratio")plt.savefig('schelling_segregation_measure.png')
可以发现,即使相似性阈值非常小,依然会有很高的隔阂度。
6总结
在本文中,我们介绍了一个Agent模型。
参考
https://www.coursera.org/course/modelthinking
宽 = 50,而高 = 50(包含 2500 间房子)
30% 的空房子
相似性阈值 = 30%(针对仿真 1),相似性阈值 = 50%(针对仿真 2),相似性阈值 = 80%(针对仿真 3)
最大迭代数 = 500
种族数量 = 2
阅读全文
0 0
- 基于 Agent 的模型入门Python实现 读书笔记
- 基于 Agent 的模型入门:Python 实现隔离仿真
- 基于Python的Xgboost模型实现
- AlexNet模型实现(4. 基于Tensorflow的python实现)
- python实现的基于hmm模型的词性标注系统
- python入门篇1:基于flask的留言板网站实现
- 基于select模型的python echo server
- 基于用户最近邻模型的协同过滤算法的Python代码实现
- Python基于YCbCr 肤色模型的情色图片检测的简单实现
- python入门读书笔记
- 《python 入门经典》读书笔记
- lda模型的python实现
- 在python中实现基于ICE框架的client、server模型
- 基于回归曲线拟合模型的ALS(最小二乘法)推导过程以及Python实现
- python实现-恒定数量进程池的echo server模型 基于multiprocessing
- 图像情感分析(3):基于卷积神经网络的图像情感分析模型Python实现
- [读书笔记] 《Python 机器学习》- 各种模型选择方法的封装
- 基于WSAEventSelect模型的TCP服务器实现
- NKOJ训练赛 过路费(最短路)
- python pandas库详解
- Angular模板与表达式的绑定
- BZOJ1066: [SCOI2007]蜥蜴
- java工程师简历的潜规则你知道吗?
- 基于 Agent 的模型入门Python实现 读书笔记
- java-序列化与反序列化
- XRecyclerView下拉刷新,加载更多,添加头布局
- 编写高质量代码 —— 异常退出条件的判断
- new和delete操作
- 基于SSH实现员工管理系统登录权限的过滤器与拦截器的综合使用
- java 如何选择GET 或POST
- functools
- angularjs删除批量删除