利用PyTorch实现爬山算法

 更新时间:2022年07月17日 08:46:04   作者:​ 盼小辉丶​  
这篇文章主要介绍了利用PyTorch实现爬山算法,爬山算法是一种局部择优的方法,采用启发式方法,是对深度优先搜索的一种改进,它利用反馈信息帮助生成解的决策,属于人工智能算法的一种

0. 前言

随机搜索策略中,每个回合都是独立的。因此,随机搜索中的所有回合都可以并行运行,最终选择能够得到最佳性能的权重。我们还通过绘制总奖励随回合增加的变化情况进行验证,可以看到奖励并没有上升的趋势。在本节中,我们将实现爬山算法 (hill-climbing algorithm),以将在一个回合中学习到的知识转移到下一个回合中。

1. 使用 PyTorch 实现爬山算法

1.1 爬山算法简介

在爬山算法中,我们同样从随机选择的权重开始。但是,对于每个回合,我们都会为权重添加一些噪声数据。如果总奖励有所改善,我们将使用新的权重来更新原权重;否则,将保持原权重。通过这种方法,随着回合的增加,权重也会逐步修改,而不是在每个回合中随机改变。

1.2 使用爬山算法进行 CartPole 游戏

接下来,我们使用 PyTorch 实现爬山算法。首先,导入所需的包,创建一个 CartPole 环境实例,并计算状态空间和动作空间的尺寸。重用 run_episode 函数,其会根据给定权重,模拟一个回合后返回总奖励:

import gym
import torch
from matplotlib import pyplot as plt
env = gym.make('CartPole-v0')

n_state = env.observation_space.shape[0]
print(n_state)

n_action = env.action_space.n
print(n_action)

def run_episode(env, weight):
    state = env.reset()
    total_reward = 0
    is_done = False
    while not is_done:
        state = torch.from_numpy(state).float()
        action = torch.argmax(torch.matmul(state, weight))
        state, reward, is_done, _ = env.step(action.item())
        total_reward += reward
    return total_reward

模拟 1000 个回合,并初始化变量用于跟踪最佳的总奖励以及相应的权重。同时,初始化一个空列表用于记录每个回合的总奖励:

n_episode = 1000
best_total_reward = 0
best_weight = torch.randn(n_state, n_action)

total_rewards = []

正如以上所述,我们在每个回合中为权重添加一些噪音,为了使噪声不会覆盖原权重,我们还将对噪声进行缩放,使用 0.01 作为噪声缩放因子:

noise_scale = 0.01

然后,就可以运行 run_episode 函数进行模拟。

随机选择初始权重之后,在每个回合中执行以下操作:

  • 为权重增加随机噪音
  • 智能体根据线性映射采取动作
  • 回合终止并返回总奖励
  • 如果当前奖励大于到目前为止获得的最佳奖励,更新最佳奖励和权重;否则,最佳奖励和权重将保持不变
  • 记录每回合的总奖励
for e in range(n_episode):
    weight = best_weight + noise_scale * torch.rand(n_state, n_action)
    total_reward = run_episode(env, weight)
    if total_reward >= best_total_reward:
        best_total_reward = total_reward
        best_weight = weight
    total_rewards.append(total_reward)
print('Episode {}: {}'.format(e + 1, total_reward))

计算使用爬山算法所获得的平均总奖励:

print('Average total reward over {} episode: {}'.format(n_episode, sum(total_rewards) / n_episode))
# Average total reward over 1000 episode: 62.421

2. 改进爬山算法

为了评估使用爬山算法的训练效果,多次重复训练过程,使用循环语句多次执行爬山算法,可以观察到平均总奖励的波动变化较大:

for i in range(10):
    best_total_reward = 0
    best_weight = torch.randn(n_state, n_action)
    total_rewards = []
    for e in range(n_episode):
        weight = best_weight + noise_scale * torch.rand(n_state, n_action)
        total_reward = run_episode(env, weight)
        if total_reward >= best_total_reward:
            best_total_reward = total_reward
            best_weight = weight
        total_rewards.append(total_reward)
        # print('Episode {}: {}'.format(e + 1, total_reward))

print('Average total reward over {} episode: {}'.format(n_episode, sum(total_rewards) / n_episode))

以下是我们运行10次后得到的结果:

Average total reward over 1000 episode: 200.0
Average total reward over 1000 episode: 9.846
Average total reward over 1000 episode: 82.1
Average total reward over 1000 episode: 9.198
Average total reward over 1000 episode: 9.491
Average total reward over 1000 episode: 9.073
Average total reward over 1000 episode: 149.421
Average total reward over 1000 episode: 49.584
Average total reward over 1000 episode: 8.827
Average total reward over 1000 episode: 9.369

产生如此差异的原因是什么呢?如果初始权重较差,则添加的少量噪声只会小范围改变权重,且对改善性能几乎没有影响,导致算法收敛性能不佳。另一方面,如果初始权重较为合适,则添加大量噪声可能会大幅度改变权重,使得权重偏离最佳权重并破坏算法性能。为了使爬山算法的训练更稳定,我们可以使用自适应噪声缩放因子,类似于梯度下降中的自适应学习率,随着模型性能的提升改变噪声缩放因子的大小。

为了使噪声具有自适应性,执行以下操作:

  • 指定初始噪声缩放因子
  • 如果回合中的模型性能有所改善,则减小噪声缩放因子,本节中,每次将噪声缩放因子减小为原来的一半,同时设置缩放因子最小值为 0.0001
  • 而如果回合中中的模型性能下降,则增大噪声缩放因子,本节中,每次将噪声缩放因子增大为原来的 2 倍,同时设置缩放因子最大值为 2
noise_scale = 0.01
best_total_reward = 0
best_weight = torch.randn(n_state, n_action)
total_rewards = []
for e in range(n_episode):
    weight = best_weight + noise_scale * torch.rand(n_state, n_action)
    total_reward = run_episode(env, weight)
    if total_reward >= best_total_reward:
        best_total_reward = total_reward
        best_weight = weight
        noise_scale = max(noise_scale/2, 1e-4)
    else:
        noise_scale = min(noise_scale*2, 2)
    total_rewards.append(total_reward)
    print('Episode {}: {}'.format(e + 1, total_reward))

可以看到,奖励随着回合的增加而增加。训练过程中,当一个回合中可以运行 200 个步骤时,模型的性能可以得到保持,平均总奖励也得到了极大的提升:

print('Average total reward over {} episode: {}'.format(n_episode, sum(total_rewards) / n_episode))
# Average total reward over 1000 episode: 196.28

接下来,为了更加直观的观察,我们绘制每个回合的总奖励的变化情况,如下所示,可以看到总奖励有明显的上升趋势,然后稳定在最大值处:

plt.plot(total_rewards, label='search')
plt.xlabel('episode')
plt.ylabel('total_reward')
plt.legend()
plt.show()

多次运行训练过程过程,可以发现与采用恒定噪声缩放因子进行学习相比,自适应噪声缩放因子可以得到稳定的训练结果。

接下来,我们测试所得到的模型策略在 1000 个新回合中的性能表现:

n_episode_eval = 1000
total_rewards_eval = []
for episode in range(n_episode_eval):
    total_reward = run_episode(env, best_weight)
    print('Episode {}: {}'.format(episode+1, total_reward))
    total_rewards_eval.append(total_reward)

print('Average total reward over {} episode: {}'.format(n_episode_eval, sum(total_rewards_eval)/n_episode_eval))
# Average total reward over 1000 episode: 199.98

可以看到在测试阶段的平均总奖励接近 200,即 CartPole 环境中可以获得的最高奖励。通过多次运行评估,可以获得非常一致的结果。

到此这篇关于利用PyTorch实现爬山算法的文章就介绍到这了,更多相关PyTorch爬山算法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • python实现下载pop3邮件保存到本地

    python实现下载pop3邮件保存到本地

    这篇文章主要为大家详细介绍了python实现下载pop3邮件保存到本地的代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-06-06
  • Python线性点运算数字图像处理示例详解

    Python线性点运算数字图像处理示例详解

    这篇文章主要为大家介绍了数字图像处理基本运算如何用Python详细点运算来处理数字图像有需要的朋友可以借鉴参考下,希望能够有所帮助
    2021-09-09
  • Python Mysql自动备份脚本

    Python Mysql自动备份脚本

    测试系统环境 Windows 2003 python 2.5.1 mysql 5.0.1 应该只适用于Win,因为调用了CMD。 增量备份,因为自用,数据库不大。
    2008-07-07
  • Python实现爬取腾讯招聘网岗位信息

    Python实现爬取腾讯招聘网岗位信息

    这篇文章主要介绍了如何用python爬取腾讯招聘网岗位信息保存到表格,并做成简单可视化。文中的示例代码对学习Python有一定的帮助,感兴趣的可以了解一下
    2022-01-01
  • python读取和保存为excel、csv、txt文件及对DataFrame文件的基本操作指南

    python读取和保存为excel、csv、txt文件及对DataFrame文件的基本操作指南

    最近在做一个项目,必须把结果保存到excel文件中,下面这篇文章主要给大家介绍了关于python读取和保存为excel、csv、txt文件及对DataFrame文件的基本操作指南的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-08-08
  • Django发送邮件和itsdangerous模块的配合使用解析

    Django发送邮件和itsdangerous模块的配合使用解析

    这篇文章主要介绍了Django发送邮件和itsdangerous模块的配合使用解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-08-08
  • Python安装第三方库的3种方法

    Python安装第三方库的3种方法

    这篇文章主要介绍了Python安装第三方库的3种方法,本文讲解了通过setuptools来安装python模块、通过pip来安装python模块、直接从网上下载下可执行文件来安装三种方法,需要的朋友可以参考下
    2015-06-06
  • 用python写测试数据文件过程解析

    用python写测试数据文件过程解析

    这篇文章主要介绍了用python写测试数据文件过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09
  • 详解python opencv、scikit-image和PIL图像处理库比较

    详解python opencv、scikit-image和PIL图像处理库比较

    这篇文章主要介绍了详解python opencv、scikit-image和PIL图像处理库比较,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • 简述 Python 的类和对象

    简述 Python 的类和对象

    这篇文章主要介绍了Python 的类和对象的相关资料,帮助大家更好的理解和学习python,感兴趣的朋友可以了解下
    2020-08-08

最新评论