返回顶部
首页 > 资讯 > 后端开发 > Python >如何在Python中用遗传算法优化垃圾收集
  • 723
分享到

如何在Python中用遗传算法优化垃圾收集

2023-06-16 01:06:26 723人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

这篇文章主要讲解了“如何在python中用遗传算法优化垃圾收集”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何在Python中用遗传算法优化垃圾收集”吧!背景在其中一个章节中,Mitche

这篇文章主要讲解了“如何在python中用遗传算法优化垃圾收集”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何在Python中用遗传算法优化垃圾收集”吧!

背景

在其中一个章节中,Mitchell介绍了一个名叫Robby的机器人,他在生活中的唯一目的是捡垃圾,并描述了如何使用GA优化Robby的控制策略。下面我将解释我解决这个问题的方法,并展示如何在Python中实现该算法。有一些很好的包可以用来构造这类算法(比如DEAP),但是在本教程中,我将只使用基本Python、Numpy和TQDM(可选)。

虽然这只是一个玩具的例子,但GAs在许多实际应用中都有使用。作为一个数据科学家,我经常用它们来进行超参数优化和模型选择。虽然GAs的计算成本很高,但GAs允许我们并行地探索搜索空间的多个区域,并且在计算梯度时是一个很好的选择。

问题描述

一个名为Robby的机器人生活在一个充满垃圾的二维网格世界中,周围有4堵墙(如下图所示)。这个项目的目标是发展一个最佳的控制策略,使他能够有效地捡垃圾,而不是撞墙。

如何在Python中用遗传算法优化垃圾收集

Robby只能看到他周围上下左右四个方块以及他所在的方块,每个方块有3个选择,空的,有垃圾,或者是一面墙。因此,Robby有3⁵=243种不同的情况。Robby可以执行7种不同的动作:上下左右的移动(4种)、随机移动、捡拾垃圾或静止不动。

因此,Robby的控制策略可以编码为一个“DNA”字符串,由0到6之间的243位数字组成(对应于Robby在243种可能的情况下应该采取的行动)。

方法

任何GA的优化步骤如下:

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. 生成问题初始随机解的“种群”

  3. 个体的“拟合度”是根据它解决问题的程度来评估的

  4. 最合适的解决方案进行“繁殖”并将“遗传”物质传递给下一代的后代

  5. 重复第2步和第3步,直到我们得到一组优化的解决方案

在我们的任务中,你创建了第一代Robbys初始化为随机DNA字符串(对应于随机控制策略)。然后模拟让这些机器人在随机分配的网格世界中运行,并观察它们的性能。

拟合度

机器人的拟合度取决于它在n次移动中捡到多少垃圾,以及它撞到墙上多少次。在我们的例子中,机器人每捡到一块垃圾就给它10分,每次它撞到墙上就减去5分。然后,这些机器人以它们的拟合度相关的概率进行“交配”(即,捡起大量垃圾的机器人更有可能繁衍后代),新一代机器人诞生了。

交配

有几种不同的方法可以实现“交配”。在Mitchell的版本中,她将父母的两条DNA链随机拼接,然后将它们连接在一起,为下一代创造一个孩子。在我的实现中,我从每一个亲本中随机分配每个基因(即,对于243个基因中的每一个,我掷硬币决定遗传谁的基因)。

例如使用我的方法,在前10个基因里,父母和孩子可能的基因如下:

Parent 1: 1440623161 Parent 2: 2430661132 Child:    2440621161

突变

我们用这个算法复制的另一个自然选择的概念是“变异”。虽然一个孩子的绝大多数基因都是从父母那里遗传下来的,但我也建立了基因突变的小可能性(即随机分配)。这种突变率使我们能够探索新的可能。

Python实现

第一步是导入所需的包并为此任务设置参数。我已经选择了这些参数作为起点,但是它们可以调整,我鼓励你可以尝试调整。

""" 导入包 """ import numpy as np from tqdm.notebook import tqdm  """ 设置参数 """ # 仿真设置 pop_size = 200 # 每一代机器人的数量 num_breeders = 100 # 每一代能够交配的机器人数量 num_gen = 400 # 总代数 iter_per_sim = 100 # 每个机器人垃圾收集模拟次数 moves_per_iter = 200 # 机器人每次模拟可以做的移动数  # 网格设置 rubbish_prob = 0.5 # 每个格子中垃圾的概率 grid_size = 10 # 0网格大小(墙除外)  # 进化设置 wall_penalty = -5 # 因撞到墙上而被扣除的拟合点 no_rub_penalty = -1 # 在空方块捡垃圾被扣分 rubbish_score = 10 # 捡垃圾可获得积分 mutation_rate = 0.01 # 变异的概率

接下来,我们为网格世界环境定义一个类。我们用标记“o”、“x”和“w”来表示每个单元,分别对应一个空单元、一个带有垃圾的单元和一个墙。

class Environment:     """     类,用于表示充满垃圾的网格环境。每个单元格可以表示为:     'o': 空     'x': 垃圾     'w': 墙     """     def __init__(self, p=rubbish_prob, g_size=grid_size):         self.p = p # 单元格是垃圾的概率         self.g_size = g_size # 不包括墙          # 初始化网格并随机分配垃圾         self.grid = np.random.choice(['o','x'], size=(self.g_size+2,self.g_size+2), p=(1 - self.p, self.p))                  # 设置外部正方形为墙壁         self.grid[:,[0,self.g_size+1]] = 'w'         self.grid[[0,self.g_size+1], :] = 'w'      def show_grid(self):         # 以当前状态打印网格         print(self.grid)      def remove_rubbish(self,i,j):         # 从指定的单元格(i,j)清除垃圾         if self.grid[i,j] == 'o': # 单元格已经是空             return False         else:             self.grid[i,j] = 'o'             return True      def get_pos_string(self,i,j):         # 返回一个字符串,表示单元格(i,j)中机器人“可见”的单元格         return self.grid[i-1,j] + self.grid[i,j+1] + self.grid[i+1,j] + self.grid[i,j-1] + self.grid[i,j]

接下来,我们创建一个类来表示我们的机器人。这个类包括执行动作、计算拟合度和从一对父机器人生成新DNA的方法。

class Robot:     """     用于表示垃圾收集机器人     """     def __init__(self, p1_dna=None, p2_dna=None, m_rate=mutation_rate, w_pen=wall_penalty, nr_pen=no_rub_penalty, r_score=rubbish_score):         self.m_rate = m_rate # 突变率         self.wall_penalty = w_pen # 因撞到墙上而受罚         self.no_rub_penalty = nr_pen # 在空方块捡垃圾的处罚         self.rubbish_score = r_score # 捡垃圾的奖励         self.p1_dna = p1_dna # 父母2的DNA         self.p2_dna = p2_dna # 父母2的DNA                  # 生成字典来从场景字符串中查找基因索引         con = ['w','o','x'] # 墙,空,垃圾         self.situ_dict = dict()         count = 0         for up in con:             for right in con:                 for down in con:                     for left in con:                         for pos in con:                             self.situ_dict[up+right+down+left+pos] = count                             count += 1                  # 初始化DNA         self.get_dna()      def get_dna(self):         # 初始化机器人的dna字符串         if self.p1_dna is None:             # 没有父母的时候随机生成DNA             self.dna = ''.join([str(x) for x in np.random.randint(7,size=243)])         else:             self.dna = self.mix_dna()      def mix_dna(self):         # 从父母的DNA生成机器人的DNA         mix_dna = ''.join([np.random.choice([self.p1_dna,self.p2_dna])[i] for i in range(243)])          #添加变异         for i in range(243):             if np.random.rand() > 1 - self.m_rate:                 mix_dna = mix_dna[:i] + str(np.random.randint(7)) + mix_dna[i+1:]          return mix_dna      def simulate(self, n_iterations, n_moves, debug=False):         # 仿真垃圾收集         tot_score = 0         for it in range(n_iterations):             self.score = 0 # 拟合度分数             self.envir = Environment()             self.i, self.j = np.random.randint(1,self.envir.g_size+1, size=2) # 随机分配初始位置             if debug:                 print('before')                 print('start position:',self.i, self.j)                 self.envir.show_grid()             for move in range(n_moves):                 self.act()             tot_score += self.score             if debug:                 print('after')                 print('end position:',self.i, self.j)                 self.envir.show_grid()                 print('score:',self.score)         return tot_score / n_iterations # n次迭代的平均得分      def act(self):         # 根据DNA和机器人位置执行动作         post_str = self.envir.get_pos_string(self.i, self.j) # 机器人当前位置         gene_idx = self.situ_dict[post_str] # 当前位置DNA的相关索引         act_key = self.dna[gene_idx] # 从DNA中读取行动         if act_key == '5':             # 随机移动             act_key = np.random.choice(['0','1','2','3'])          if act_key == '0':             self.mv_up()         elif act_key == '1':             self.mv_right()         elif act_key == '2':             self.mv_down()         elif act_key == '3':             self.mv_left()         elif act_key == '6':             self.pickup()      def mv_up(self):         # 向上移动         if self.i == 1:             self.score += self.wall_penalty         else:             self.i -= 1      def mv_right(self):         # 向右移动         if self.j == self.envir.g_size:             self.score += self.wall_penalty         else:             self.j += 1      def mv_down(self):         # 向下移动         if self.i == self.envir.g_size:             self.score += self.wall_penalty         else:             self.i += 1      def mv_left(self):         # 向左移动         if self.j == 1:             self.score += self.wall_penalty         else:             self.j -= 1      def pickup(self):         # 捡垃圾         success = self.envir.remove_rubbish(self.i, self.j)         if success:             # 成功捡到垃圾             self.score += self.rubbish_score         else:             # 当前方块没有捡到垃圾             self.score += self.no_rub_penalty

最后是运行遗传算法的时候了。在下面的代码中,我们生成一个初始的机器人种群,让自然选择来运行它的过程。我应该提到的是,当然有更快的方法来实现这个算法(例如利用并行化),但是为了本教程的目的,我牺牲了速度来实现清晰。

# 初始种群 pop = [Robot() for x in range(pop_size)] results = []  # 执行进化 for i in tqdm(range(num_gen)):     scores = np.zeros(pop_size)          # 遍历所有机器人     for idx, rob in enumerate(pop):         # 运行垃圾收集模拟并计算拟合度         score = rob.simulate(iter_per_sim, moves_per_iter)         scores[idx] = score      results.append([scores.mean(),scores.max()]) # 保存每一代的平均值和最大值      best_robot = pop[scores.argmax()] # 保存最好的机器人      # 限制那些能够交配的机器人的数量     inds = np.argpartition(scores, -num_breeders)[-num_breeders:] # 基于拟合度得到顶级机器人的索引     subpop = []     for idx in inds:         subpop.append(pop[idx])     scores = scores[inds]      # 平方并标准化     nORM_scores = (scores - scores.min()) ** 2      norm_scores = norm_scores / norm_scores.sum()      # 创造下一代机器人     new_pop = []     for child in range(pop_size):         # 选择拟合度优秀的父母         p1, p2 = np.random.choice(subpop, p=norm_scores, size=2, replace=False)         new_pop.append(Robot(p1.dna, p2.dna))      pop = new_pop

虽然最初大多数机器人不捡垃圾,总是撞到墙上,但几代人之后,我们开始看到一些简单的策略(例如“如果与垃圾在一起,就捡起来”和“如果挨着墙,就不要移到墙里”)。经过几百次的反复,我们只剩下一代不可思议的垃圾收集天才!

结果

下面的图表表明,我们能够在400代机器人种群中“进化”出一种成功的垃圾收集策略。

如何在Python中用遗传算法优化垃圾收集

为了评估进化控制策略的质量,我手动创建了一个基准策略,其中包含一些直观合理的规则:

  • 如果垃圾在当前方块,捡起来

  • 如果在相邻的方块上可以看到垃圾,移到那个方块

  • 如果靠近墙,则向相反方向移动

  • 否则,随意移动

平均而言,这一基准策略达到了426.9的拟合度,但我们最终的“进化”机器人的平均拟合度为475.9。

战略分析

这种优化方法最酷的一点是,你可以找到反直觉的解决方案。机器人不仅能够学习人类可能设计的合理规则,而且还自发地想出了人类可能永远不会考虑的策略。一种先进的技术出现了,就是使用“标记物”来克服近视和记忆不足。

例如,如果一个机器人现在在一个有垃圾的方块上,并且可以看到东西方方块上的垃圾,那么一个天真的方法就是立即捡起当前方块上的垃圾,然后移动到那个有垃圾的方块。这种策略的问题是,一旦机器人移动(比如向西),他就无法记住东边还有1个垃圾。为了克服这个问题,我们观察了我们的进化机器人执行以下步骤:

  • 向西移动(在当前方块留下垃圾作为标记)

  • 捡起垃圾往东走(它可以看到垃圾作为标记)

  • 把垃圾捡起来,搬到东边去

  • 捡起最后一块垃圾 

如何在Python中用遗传算法优化垃圾收集

从这种优化中产生的另一个反直觉策略的例子如下所示。Openai使用强化学习(一种更复杂的优化方法)教代理玩捉迷藏。我们看到,这些代理一开始学习“人类”策略,但最终学会了新的解决方案。

感谢各位的阅读,以上就是“如何在Python中用遗传算法优化垃圾收集”的内容了,经过本文的学习后,相信大家对如何在Python中用遗传算法优化垃圾收集这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

--结束END--

本文标题: 如何在Python中用遗传算法优化垃圾收集

本文链接: https://lsjlt.com/news/282064.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 如何在Python中用遗传算法优化垃圾收集
    这篇文章主要讲解了“如何在Python中用遗传算法优化垃圾收集”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何在Python中用遗传算法优化垃圾收集”吧!背景在其中一个章节中,Mitche...
    99+
    2023-06-16
  • js中垃圾回收机制如何优化
    这篇文章主要介绍js中垃圾回收机制如何优化,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1、数组array优化将[]赋值给一个数组对象,是清空数组的捷径(例如: arr = [];),但是需要注意的是,这种方式又创建...
    99+
    2023-06-15
  • Java中如何使用垃圾收集器
    Java中如何使用垃圾收集器,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。Java垃圾收集器使用小诀窍,垃圾收集器(Garbage Collector,GC)是现代软件虚拟机技...
    99+
    2023-06-17
  • 如何优化Go语言中的垃圾回收
    在Go语言编程中,垃圾回收(Garbage Collection)是一个非常重要的主题,它负责管理和释放不再被程序使用的内存空间,确保程序在运行过程中不会出现内存泄漏的情况。尽管Go语...
    99+
    2024-04-02
  • java中GC算法和垃圾收集器怎么使用
    在Java中,GC(垃圾回收)算法和垃圾收集器是自动管理内存的关键组件。以下是关于如何使用GC算法和垃圾收集器的一些基本指南:1. ...
    99+
    2023-08-24
    java
  • 如何利用遗传算法库DEAP优化交易策略
    这篇文章给大家分享的是有关如何利用遗传算法库DEAP优化交易策略的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。优化的对象就是这样一个list数组 [16, 8, 24, 1, 13, 8, 1],其实就...
    99+
    2023-06-02
  • 如何使用Python实现遗传算法
    本篇内容介绍了“如何使用Python实现遗传算法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!遗传算法是模仿自然界生物进化机制发展起来的随机...
    99+
    2023-07-05
  • 如何分析Java性能优化中的垃圾回收机制
    这篇文章将为大家详细讲解有关如何分析Java性能优化中的垃圾回收机制,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。★JVM 的内存空间  在 Java 虚拟机规范中,提及了如下几种类型的内存...
    99+
    2023-06-02
  • 如何使用Go语言进行内存优化与垃圾回收
    要使用Go语言进行内存优化与垃圾回收,可以采取以下几个步骤:1. 避免创建过多的对象:Go语言的垃圾回收器会自动回收不再使用的对象,...
    99+
    2023-10-08
    Golang
  • python遗传算法之geatpy如何安装使用
    这篇文章主要介绍了python遗传算法之geatpy如何安装使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇python遗传算法之geatpy如何安装使用文章都会有所收获,下面我们一起来看看吧。1. geat...
    99+
    2023-07-06
  • 如何利用Go语言进行内存优化和垃圾回收实践
    要利用Go语言进行内存优化和垃圾回收实践,可以遵循以下几个步骤:1. 避免内存分配:Go语言在内存分配方面表现出色,但频繁的内存分配...
    99+
    2023-10-08
    Golang
  • 如何使用Go语言进行高效的内存优化和垃圾回收
    使用Go语言进行高效的内存优化和垃圾回收有以下几个方面的技巧和建议:1. 减少内存分配:避免频繁的对象创建和销毁操作,尽量重用已有的...
    99+
    2023-10-12
    Go语言
  • 如何用Python从零开始实现简单遗传算法
    今天就跟大家聊聊有关如何用Python从零开始实现简单遗传算法,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。遗传算法是一种随机全局优化算法。连同人工神经网络,它可能是最流行和广为人知...
    99+
    2023-06-15
  • 如何利用Go语言进行内存优化和高效的垃圾回收管理
    要利用Go语言进行内存优化和高效的垃圾回收管理,可以采取以下几个策略:1. 使用指针:Go语言通过指针进行内存管理,使用指针可以减少...
    99+
    2023-10-08
    Golang
  • python如何实现使用遗传算法进行图片拟合
    小编给大家分享一下python如何实现使用遗传算法进行图片拟合,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!引言算法思路假设我们有这样一个生物族群,他们的每个基因片段都是一个个三角形(即只含三个点和颜色信息),他们每个个体...
    99+
    2023-06-29
  • 如何在编程算法中优化Python和Bash的使用?
    Python和Bash是两种非常流行的编程语言,很多程序员都会使用它们来编写算法。在编写算法时,如何优化Python和Bash的使用呢?本文将为您介绍几种优化方法,帮助您更高效地编写算法。 一、使用Python的内置函数 Python是一种...
    99+
    2023-06-24
    bash 编程算法 编程算法
  • 如何使用Python地图四色原理的遗传算法着色
    小编给大家分享一下如何使用Python地图四色原理的遗传算法着色,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1 任务需求  ...
    99+
    2023-06-29
  • 如何在 Python 编程算法中优化实时接口?
    Python 是一种高级编程语言,因其易读、易写、易学等特点而备受青睐。在 Python 编程中,算法是一个非常重要的部分。随着现代技术的发展和应用,实时接口已经成为了许多应用场景中必不可少的一部分。在这篇文章中,我们将介绍如何在 Pyth...
    99+
    2023-10-02
    编程算法 接口 实时
  • 如何在 Python 中优化算法以通过 leetcode 测试?
    如何在 Python 中优化算法以通过 LeetCode 测试? LeetCode 是一个相当流行的在线编程平台,许多人使用它来提高编程技能和解决算法问题。然而,在 LeetCode 上编写的算法可能会遇到一些挑战,例如运行时间过长或者内存...
    99+
    2023-07-23
    编程算法 leetcode 文件
  • NumPy 在 PHP 中的应用:如何优化编程算法?
    NumPy 是一款基于 Python 的开源数值计算库,它提供了高效的多维数组和矩阵运算功能,使得 Python 成为了一个强大的科学计算平台。但是,很多 PHP 开发者并不知道如何在 PHP 中使用 NumPy,并且在编写算法时也没有充分...
    99+
    2023-06-02
    numy 编程算法 npm
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作