作者|Jacob Gursky 编译|VK 来源|Towards Data Science

介绍

如果我告诉你训练神经网络不需要计算梯度,只需要前项传播你会怎么样?这就是神经进化的魔力!同时,我要展示的是,所有这一切只用Numpy都可以很容易地做到!学习统计学你会学到很多关于基于梯度的方法,但是不久前我读了Uber AI的人写的一篇非常有趣的文章,他表明在解决Atari游戏时,简单的遗传算法与最复杂的基于梯度的RL方法是挺有竞争力的。我链接了下面的来源,如果你对强化学习感兴趣,我强烈建议你读一读。

什么是神经进化

首先,对于那些还不知道的人,神经进化描述了进化和遗传算法在训练神经网络结构和权值方面的应用,它作为一种无梯度的替代方法!我们将在这里使用一个非常简单的神经进化案例,只使用一个固定拓扑网络,只关注优化权重和偏差。神经进化过程可以定义为四个基本步骤,重复这些步骤直到达到收敛,首先是一个随机生成的网络池。

  1. 评估种群的适应度
  2. 选择最适合复制的个体
  3. 使用最适合网络的副本重新填充
  4. 在网络权值中引入正态分布突变

哇,这看起来很简单!让我们把一些术语分解一下:

  • 适应度:这只是描述网络在特定任务中的表现,并允许我们确定要培育哪些网络。注意,因为进化算法是非凸优化的一种形式,因此可以与任何损失函数一起使用,而不管其可微性(或缺乏可微性)如何

  • 变异:这个可能是最简单的!为了改进我们的子网络,我们必须对网络权值引入随机变化,这些权值通常来自均匀或正态分布。有很多不同形式的突变:移位突变(将参数乘以随机数)、交换突变(将参数替换为随机数)、符号突变(更改参数的符号)等等。我们只会使用简单的加性突变,但这里有很大的创新空间!

神经进化的优势

我们还应该考虑神经进化模型的理论优势。首先,我们只需要使用网络的前向传递,因为我们只需要计算损失,以确定要复制的网络。这意味着显而易见,反向传播通常是最昂贵的!其次,在给定足够的迭代次数的情况下,进化算法保证能找到损失曲面的全局最小值,而基于凸梯度的方法则陷入局部最小值。最后,更复杂的神经进化形式使我们不仅可以优化网络的权值,还可以优化结构本身!

那为什么不一直用神经进化呢?

这是一个复杂的问题,但它可以归结为,当有足够的梯度信息时,精确的梯度下降法更有效。这意味着损失曲面越凸出,你就越想使用SGD之类的分析方法,而不是遗传算法。因此,在有监督的环境下使用遗传算法是非常罕见的,因为通常有足够的梯度信息可用,传统的梯度下降方法将工作得很好。然而,如果你是在RL环境下工作,或者是在不规则的缺失面或低凸度的情况下(如连续的GAN),那么神经进化提供了一个可行的选择!事实上,最近的许多研究发现,参数化神经进化模型在这些环境下可以做得更好。

实现

加载库

正如介绍中所述,我们将尝试在这个项目中只使用numpy,只定义我们需要的helper函数。

import numpy as np
import gym

关于数据

我们将使用来自gym的经典侧手翻环境来测试我们的网络。我们的目标是通过左右移动来观察这个网络能让杆子保持直立多久。作为一个RL任务,神经进化方法应该是一个很好的选择!我们的网络将接收4个观测结果作为输入,并将左右输出作为一个动作。

helper函数

首先,我们将定义几个帮助函数来建立我们的网络。首先是relu激活函数,我们将使用它作为隐藏层的激活函数,使用softmax函数作为网络的输出,以获得网络输出的概率估计!最后,我们需要定义一个函数,当我们需要计算分类交叉熵时,该函数生成响应向量的one-hot编码。

def relu(x):return np.where(x>0,x,0)
def softmax(x):x = np.exp(x — np.max(x))x[x==0] = 1e-15return np.array(x / x.sum())

定义我们的网络

首先,我们将为总体中的各个网络定义一个类。我们需要定义一个初始化方法,它随机分配权重和偏差,并以网络结构作为输入,一个预测方法,这样我们可以得到一个输入的概率,最后一个评估方法,返回给定输入和响应的网络的分类交叉熵!同样,我们只使用我们定义的函数或numpy中的函数。注意,初始化方法也可以将另一个网络作为输入,这就是我们将如何在代之间执行突变!

# 让我们定义一个新的神经网络类,可以与gym交互
class NeuralNet():def __init__(self, n_units=None, copy_network=None, var=0.02, episodes=50, max_episode_length=200):# 测试我们是否需要复制一个网络if copy_network is None:# Saving attributesself.n_units = n_units# 初始化空列表以容纳矩阵weights = []biases = []# 填充列表for i in range(len(n_units)-1):weights.append(np.random.normal(loc=0,scale=1,size=(n_units[i],n_units[i+1])))biases.append(np.zeros(n_units[i+1]))# 创建参数字典self.params = {'weights':weights,'biases':biases}else:self.n_units = copy_network.n_unitsself.params = {'weights':np.copy(copy_network.params['weights']),'biases':np.copy(copy_network.params['biases'])}# 突变权重self.params['weights'] = [x+np.random.normal(loc=0,scale=var,size=x.shape) for x in self.params['weights']]self.params['biases'] = [x+np.random.normal(loc=0,scale=var,size=x.shape) for x in self.params['biases']]def act(self, X):# 获取权重和偏置weights = self.params['weights']biases = self.params['biases']# 第一个输入a = relu((X@weights[0])+biases[0])# 在其他层传播for i in range(1,len(weights)):a = relu((a@weights[i])+biases[i])#获取概率probs = softmax(a)return np.argmax(probs)# 定义评估方法def evaluate(self, episodes, max_episode_length, render_env, record):# 为奖励创建空列表rewards = []# 首先,我们需要建立我们的gym环境env=gym.make('CartPole-v0')# 如果需要的话,我们可以录像if record is True:env = gym.wrappers.Monitor(env, "recording")env._max_episode_steps=1e20for i_episode in range(episodes):observation = env.reset()for t in range(max_episode_length):if render_env is True:env.render()observation, _, done, _ = env.step(self.act(np.array(observation)))if done:rewards.append(t)break# 关闭环境env.close()# 获取最终奖励if len(rewards) == 0:return 0else:return np.array(rewards).mean()

定义我们的遗传算法类

最后,我们需要定义一个类来管理我们的种群,以执行神经进化的四个关键步骤!我们需要三个方法。首先,创建一个随机网络池并设置属性的初始化方法。接下来,我们需要一个fit方法,给定一个输入,重复执行上面列出的步骤:首先评估网络,然后选择最合适的网络,创建子网络,最后修改子网络!最后,我们需要一个预测的方法,这样我们就可以使用最好的网络训练类。让我们开始测试吧!

# 定义处理网络种群的类
class GeneticNetworks():#定义我们的初始化方法def __init__(self, architecture=(4,16,2),population_size=50, generations=500,render_env=True, record=False,mutation_variance=0.02,verbose=False,print_every=1,episodes=10,max_episode_length=200):# 创建我们的网络列表self.networks = [NeuralNet(architecture) for _ in range(population_size)]self.population_size = population_sizeself.generations = generationsself.mutation_variance = mutation_varianceself.verbose = verboseself.print_every = print_everyself.fitness = []self.episodes = episodesself.max_episode_length = max_episode_lengthself.render_env = render_envself.record = record# 定义我们的fiting方法def fit(self):# 遍历所有代for i in range(self.generations):# 评估rewards = np.array([x.evaluate(self.episodes, self.max_episode_length, self.render_env, self.record) for x in self.networks])# 跟踪每一代的最佳得分self.fitness.append(np.max(rewards))# 选择最佳网络best_network = np.argmax(rewards)# 创建子网络new_networks = [NeuralNet(copy_network=self.networks[best_network], var=self.mutation_variance, max_episode_length=self.max_episode_length) for _ in range(self.population_size-1)]#设置新网络self.networks = [self.networks[best_network]]+new_networks# 如果必要输出结果if self.verbose is True and (i%self.print_every==0 or i==0):print('Generation:',i+1,'| Highest Reward:',rewards.max().round(1),'| Average Reward:',rewards.mean().round(1))# 返回最佳网络self.best_network = self.networks[best_network]

测试算法

如上所述,我们将在CartPole问题上测试我们的网络,只使用一个包含16个节点的隐含层和两个表示向左或向右移动的输出节点。我们还需要多次迭代中平均,这样我们就不会不小心为下一代选择了一个糟糕的网络!我在经过一些尝试和错误之后选择了许多这样的参数,所以你的情况可能会有所不同!此外,我们将只引入方差为0.05的突变,以免破坏网络的功能。

# 让我们训练一个网络种群
from time import time
start_time = time()
genetic_pop = GeneticNetworks(architecture=(4,16,2),population_size=64, generations=5,episodes=15, mutation_variance=0.1,max_episode_length=10000,render_env=False,verbose=True)
genetic_pop.fit()
print('Finished in',round(time()-start_time,3),'seconds')
Generation: 1 | Highest Reward: 309.5 | Average Reward: 29.2
Generation: 2 | Highest Reward: 360.9 | Average Reward: 133.6
Generation: 3 | Highest Reward: 648.2 | Average Reward: 148.0
Generation: 4 | Highest Reward: 616.6 | Average Reward: 149.9
Generation: 5 | Highest Reward: 2060.1 | Average Reward: 368.3
Finished in 35.569 seconds

最初的随机网络

首先,让我们看看一个随机初始化的网络是如何执行这个任务的。很明显,这里没有策略,杆子几乎马上就倒了。请忽略下面gif图中的光标

random_network = NeuralNet(n_units=(4,16,2))
random_network.evaluate(episodes=1, max_episode_length=int(1e10), render_env=True, record=False)

5代之后……

仅仅经过5代,我们可以看到我们的网络已经几乎完全掌握了CartPole!而且只花了大约30秒的训练时间!请注意,随着进一步的训练,网络学习保持它完全直立,几乎所有的时间都是这样,但目前我们只是感兴趣的速度,5代是相当短的!我们应该把这看作是神经进化力量的一个很好的例子。

# 让我们看看我们最好的网络
genetic_pop.best_network.evaluate(episodes=3, max_episode_length=int(1e10), render_env=True, record=False)

结尾

很明显,我们可以在未来添加很多东西来进一步检验神经进化的有效性。首先,研究不同的突变操作如交叉操作的影响是很有趣的。

转移到像TensorFlow或PyTorch这样的现代深度学习平台也是一个明智的想法。请注意,遗传算法是高度并行的,因为我们所要做的就是在一个前项传播的设备上运行每个网络。不需要反映权重或复杂的分配策略!因此,每增加一个处理单元,我们的运行时间几乎会直线下降。

最后,我们应该在不同的强化学习任务中探索神经进化,甚至在梯度难以评估的其他情况下,例如在生成对抗网络或长序列LSTM网络中。

进一步的阅读

如果你对神经进化及其应用感兴趣,Uber在几篇论文中有一个精彩的页面,展示了神经进化在强化学习方面的现代优势:

https://eng.uber.com/tag/deep-neuroevolution/

这个项目的源代码可以在GitHub库中找到:

https://github.com/gursky1/Numpy-Neuroevolution

原文链接:https://towardsdatascience.com/gradient-free-reinforcement-learning-neuroevolution-using-numpy-7377d6f6c3ea

欢迎关注磐创AI博客站: http://panchuang.net/

sklearn机器学习中文官方文档: http://sklearn123.com/

欢迎关注磐创博客资源汇总站: http://docs.panchuang.net/

无梯度强化学习:使用Numpy进行神经进化相关推荐

  1. 基于深度强化学习的机器人运动控制研究进展 | 无模型强化学习 | 元学习

    1.基于深度强化学习的机器人运动控制研究进展 1.1 深度强化学习 1.1.1 强化学习简介: 强化学习(Reinforcement Learning, RL)利用试错机制与环境进行交互,旨在通过最大 ...

  2. 论文笔记-连续HVAC控制的无模型强化学习算法的实验评估

    本文在一个模拟的数据中心中对四种actor-critic算法进行了实验评估.性能评估基于它们在提高能效的同时保持热稳定性的能力,以及它们对天气动态的适应性.与在EnergyPlus中实施的基于模型的控 ...

  3. 【零基础学机器学习 3】机器学习类型简介:监督学习 - 无监督学习 - 强化学习

  4. 《强化学习周刊》第25期:DeepMind提出无模型风险敏感强化学习、谷歌发布 RLDS数据集生态系统...

    No.25 智源社区 强化学习组 强 化 学  习 研究 观点 资源 活动 关于周刊 强化学习作为人工智能领域研究热点之一,其研究进展与成果也引发了众多关注.为帮助研究与工程人员了解该领域的相关进展和 ...

  5. [论文]基于强化学习的无模型水下机器人深度控制

    基于强化学习的无模型水下机器人深度控制 摘要 介绍 问题公式 A.水下机器人的坐标框架 B.深度控制问题 马尔科夫模型 A.马尔科夫决策 B.恒定深度控制MDP C.弯曲深度控制MDP D.海底追踪的 ...

  6. 强化学习(四) - 无模型学习(MC、TDL)

    上一节讲的是在已知模型的情况下,通过动态规划来解决马尔科夫决策过程(MDP)问题.具体的做法有两个:一个是策略迭代,一个是值迭代. 从这一节开始,我们将要进入模型未知的情况下,如何去解决MDP问题. ...

  7. 基于值的深度强化学习算法

    目录 DQN2013 -- Playing Atari with Deep Reinforcement Learning DQN2015 -- Human-level control through ...

  8. 《强化学习周刊》第28期:UNCC提出全新脑-机交互学习模式:内在互动强化学习...

    No.28 智源社区 强化学习组 强 化 学  习 研究 观点 资源 活动 关于周刊 强化学习作为人工智能领域研究热点之一,其研究进展与成果也引发了众多关注.为帮助研究与工程人员了解该领域的相关进展和 ...

  9. 《强化学习周刊》第21期:EMNLP 2020-2021强化学习的最新研究与应用

    No.21 智源社区 强化学习组 强 化 学  习 研究 观点 资源 活动 关于周刊 强化学习作为人工智能领域研究热点之一,其研究进展与成果也引发了众多关注.并且诸多研究成果发表于EMNLP 2020 ...

最新文章

  1. java nio原理 epoll_多路复用 Select Poll Epoll 的实现原理(BIO与NIO)
  2. ServerSocket01
  3. 不错的Android开发网站
  4. Android Binder的使用
  5. [日常] 算法-旋转字符串-暴力移位法
  6. 第 10 章 容器监控 - 078 - Docker 最常用的监控方案
  7. 关闭sublime更新提示
  8. POJ 3254 Corn Fields [DP]
  9. 【实用工具】windows/linux下时间统计函数
  10. Byobu(tmux)的使用与定制
  11. 使用php建立评论系统
  12. 计算机忘记密码WIN7,win7忘记密码强制重置方法
  13. python--mysql创建数据库
  14. 在python中安装包出现Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None))
  15. 搭建MYS-SAM9X5开发环境
  16. 订单管理_02修改订单信息流程
  17. 朴实无华!注意力机制神经网络解析
  18. 2018云原生技术实践峰会CNBPS 重新定义云原生
  19. YUV420SP/YUV420P
  20. mac framework

热门文章

  1. mysql 5.5升级5.6报错:ERROR 1193 (HY000) at line 84: Unknown system variable 'have_csv'
  2. LNK 1104 无法打开文件“XXX.lib”
  3. 微信小程序分享文件给好友
  4. 边缘智能:边缘计算和人工智能的深度融合
  5. Jar包发布Docker一键部署脚本
  6. 07.绑定微博用户接口
  7. 人毁谤、侮辱、骂时,“阿弥陀佛,谢谢,消灾免难”
  8. Python编程:毫秒数换算成常见的小时数、分钟数、秒数
  9. Android蓝叠模拟器在哪,Bluestacks怎么用 蓝叠安卓模拟器使用教程
  10. Linux -ssh登录 详解