其他
【他山之石】不会强化学习,只会numpy,能解决多难的RL问题?
“他山之石,可以攻玉”,站在巨人的肩膀才能看得更高,走得更远。在科研的道路上,更需借助东风才能更快前行。为此,我们特别搜集整理了一些实用的代码链接,数据集,软件,编程技巧等,开辟“他山之石”专栏,助你乘风破浪,一路奋勇向前,敬请关注。
地址:https://www.zhihu.com/people/zhou-bo-54-20
强化学习能够解决的问题难度一直在提升,从入门级别的cartpole,到后来的Atari,Mujoco 一系列复杂环境,但不会深度学习框架,更别说实现PPO/IMPALA等复杂的算法,那还有希望继续解决这些很复杂的问题吗?答案是可以的---进化算法。
今天的主题是进化算法用于强化学习问题。进化算法(Evolution Strategies) 作为搜索算法一个大分支,最早是在上个世纪90年代提出来的,较为大家熟知的遗传算法就是其中的代表。以往的进化算法是直接作用于解的空间,直接寻找更优的决策方式,比如在解决经典的旅行商TSP问题过程中,直接搜索新的旅行轨迹。OpenAI[1]直接把这类算法应用在神经网络参数的搜索上,简单来说就是以下几个步骤:
初始化神经网络参数
在原始参数的基础上,增加多组噪声,得到多组新的神经网络参数
在环境中评估每一组新参数的效果(跑一个episode看reward)
根据reward来挑选出可以提升模型效果的噪声,作为模型更新参数的方向
以下这个图可以对ES算法的更新过程一目了然:
ES 算法更新过程
算法示例
predict:根据当前状态预测observation get_flat_weights: 获取当前参数,拍平成一个向量,用于增加噪声 set_flat_weights: 设定当前参数,一般传入增加噪声后的参数或者经过梯度更新后的参数。 learn:根据对于增加噪声后的参数的评估结果以及添加的噪声方向,计算出梯度更新参数。
class CartpoleAgent(object):
def __init__(self, obs_dim, act_dim):
# init weights
self.w = np.random.random((act_dim, obs_dim)) * 0.1
self.b = np.zeros(act_dim)
self.weights_total_size = self.w.size + self.b.size
def predict(self, obs):
out = np.dot(self.w, obs) + self.b
action = np.argmax(out)
return action
def get_flat_weights(self):
flat_weights = np.concatenate(([self.w.ravel(), self.b]), axis=0)
return flat_weights
def set_flat_weights(self, flat_weights):
self.w = flat_weights[:self.w.size].reshape(self.w.shape)
self.b = flat_weights[self.w.size:]
def learn(self, rewards, noises):
# 根据reward、noise计算梯度的加权求和,得出总的梯度更新方向
gradient = np.dot(
np.asarray(rewards, dtype=np.float32),
np.asarray(noises, dtype=np.float32))
gradient /= rewards.size
flat_weights = self.get_flat_weights()
learning_rate = 0.1
# Compute the new weights.
new_weights = flat_weights + learning_rate * gradient
self.set_flat_weights(new_weights)
跑一百个epoch,每个epoch里面跑10次进化 每次进化是通过增加一个均值为0、标准差为0.05的高斯噪声 之后再评估每次进化的模型效果(直接跑一个episode测试下结果就好),记录添加的噪声以及相应的评估reward 根据上一步记录的reward和noise
for epoch in range(100):
rewards = []
noises = []
lastest_flat_weights = agent.get_flat_weights()
for episode in range(10):
noise = np.random.randn(agent.weights_total_size)
perturbation = noise * 0.05 # 产生均值为0,标准差为0.05的噪声
agent.set_flat_weights(lastest_flat_weights + perturbation)
# 跑一个episode,评估下新参数下的效果
ep_reward = evaluate(env, agent)
noises.append(noise)
rewards.append(ep_reward)
normalized_rewards = reward_normalize(rewards)
agent.set_flat_weights(lastest_flat_weights) # 恢复进化前的参数
agent.learn(normalized_rewards, noises)# 根据进化噪声以及其结果,计算进化的梯度
代码以及效果
“他山之石”历史文章
技术总结《OpenAI Gym》
ROC和CMC曲线的理解(FAR, FRR的理解)
pytorch使用hook打印中间特征图、计算网络算力等
Ray和Pytorch Lightning 使用指北
如何在科研论文中画出漂亮的插图?
PyTorch 源码解读之 torch.optim:优化算法接口详解
AI框架基础技术之深度学习中的通信优化
SimCLR:用于视觉表征的对比学习框架
Pytorch Autograd与计算图
tensorflow2.4性能调优最佳实践
PyTorch | DDP系列:入门教程、实现原理与源代码解析、实战与技巧
教你用PyTorch玩转Transformer英译中翻译模型!
深度学习工程技巧之网格调参
PyTorch使用预训练模型进行模型加载
深度学习调参经验总结
更多他山之石专栏文章,
请点击文章底部“阅读原文”查看
分享、点赞、在看,给个三连击呗!