强化学习之Sarsa算法最简单的实现代码-(环境:“CliffWalking-v0“悬崖问题)

2023-10-27

1、算法简介

直接上伪代码:

伪代码解释:

第一行:①设置动作空间A和状态空间S,以后你agent只能执行这A中有的动作,你环境的状态也就S中这么些; 

              ②初始化Q表格,也就是表格的横坐标为动作,纵坐标为状态,每个格子里面的值表示:纵坐标对应的状态s下,执行横坐标对应的动作a,后环境反馈回来的奖励值r(注意啊,这个奖励值先开是都初始化为0啥的,然后不断的episode,这整个表不断的更新,不断的确定哪个状态执行哪个动作奖励是多少,宏观上就是agent不断的确定,不断的强化,比如在这个状态,我该执行哪个动作,强化到最后,我就知道我不管在哪个状态,我都知道,我在这个当前状态我该干啥,强化,强化,强化重要的事说。。。直接点题强化学习,哈哈。。);

              ③如果当前处在终止状态terminal-state下,(你这个都终止状态了,达到目标了,或者坏了,跑出范围了,摔倒了,也不可能给终止状态上施加啥动作,所以不能有动作啊),此时奖励值r都设置为0;

                                                         

第二行:不断的循环重复回合episode,不断的训练,一次回合就是环境重置,导演说各就各位,场景开始什么样还原成开始的样子,agent刚开始在哪啥状态姿势,回到刚开始那样,然后就是开始这个回合,agent开始和环境交互搞啊搞,直到到达终止状态;  

第三行:它这个初始化状态S不是让你把状态空间S重新初始化一个新的,而是每次回合你都把环境搞乱了,现在要开始新的一个回合,你得把前一个回合搞乱的环境重置一下啊,重新各就各位一下,你这不让它各就各位,那agent每次都在学一个新的环境,回合起始学习的环境是上个环境遗留下来的终止环境,这学个毛线啊吗。说白了,就是 env.reset()。

第四行:在状态为s情况下,我要从Q表中选一个动作a执行到环境中,我采用的是(ε-greedy) ε贪婪策略,这个策略设置一个概率比如0.1。我现在采用这个策略的话,我有0.9的概率是直接从Q表中选取状态s对应的这一行,执行哪个动作给的奖励最高,我就选哪个动作(如果有多个动作给的奖励都是最高,那么我随机选这里面的一个动作a就成);有0.1的概率是随机从动作空间A中挑选动作a,用得到的动作a施加到环境中,那么施加完,环境就会从现在的状态s,转换到状态s'。

第五行:这个episode前面两行该准备的准备完了,现在执行这个episode,直到环境反馈回来的状态为终止状态terminal-state,就终止这个回合episode,否则一直循环,也就是agent不断的和环境进行交互,不断的学习。

第六行:在环境状态为s时,给环境施加一个动作a,得到环境的反馈,下一个状态s'和奖励r(这行代码体现的就是智能体与环境之间的交互)。

第七行:根据第六行,环境返回回来的下个状态s',我们再次使用(ε-greedy) ε贪婪策略,获得环境在下个状态s',要执行的s'上的动作a'(也就下一个要执行动作)。

第八行:这个就是数学公式的伪代码,到过程中就是,你现在要更新的Q表了,要更新Q表中的Q(s, a)这个格子中的奖励值,你首先先取出这个格子中老的Q(s, a)值,然后取出Q(s', a')这个格子中的奖励值,然后根据公式,直接算出新的Q(s, a)这个格子奖励值该是啥。这个α(alpha)就是用于软更新soft update的,类似机器学习中的学习率;这个γ(gamma)就是折扣因子。

第九行:都往前走一步,状态变为下一个装填s',动作变为下一个动作a'

第十行:当此时这个新的状态是终止状态时,我直接停止这轮回合。

代码:使用悬崖问题中最简单的模型"CliffWalking-v0"作为环境,其中o表示能走的路地;C表示悬崖;T表示终点;智能体agent用x表示,x从左下角起始位置,要走到终点T,进入悬崖、出界、终点都是终止状态。

#!/usr/bin/env python 
# -*- coding:utf-8 -*-
import time

import numpy as np
import gym


class SarsaAgent(object):
    def __init__(self, obs_n, act_n, learning_rate=0.01, gamma=0.9, e_greedy=0.1):
        self.act_n = act_n       # 动作的维度, 有几个动作可选
        self.lr = learning_rate    # 学习率
        self.gamma = gamma   # 折扣因子,reward的衰减率
        self.epsilon = e_greedy   # 按一定的概率随机选动作
        self.Q = np.zeros((obs_n, act_n))   # 创建一个Q表格


    # 根据输入观察值(这个代码不区分state和observation),采样输出的动作值
    def sample(self, obs):
        if np.random.uniform(0, 1) < (1.0 - self.epsilon):    # 根据table的Q值选动作
            action = self.predict(obs)    # 调用函数获得要在该观察值(或状态)条件下要执行的动作
        else:
            action = np.random.choice(self.act_n)   # e_greedy概率直接从动作空间中随机选取一个动作
        return action


    # 根据输入的观察值,预测输出的动作值
    def predict(self, obs):
        Q_list = self.Q[obs, :]    # 从Q表中选取状态(或观察值)对应的那一行
        maxQ = np.max(Q_list)    # 获取这一行最大的Q值,可能出现多个相同的最大值

        action_list = np.where(Q_list == maxQ)[0]    # np.where(条件)功能是筛选出满足条件的元素的坐标
        action = np.random.choice(action_list)      # 这里尤其如果最大值出现了多次,随机取一个最大值对应的动作就成
        return action

    # 给环境作用一个动作后,对环境的所有反馈进行学习,也就是用环境反馈的结果来更新Q-table
    def learn(self, obs, action, reward, next_obs, next_action, done):
        """
            on-policy
            obs:交互前的obs, 这里observation和state通用,也就是公式或者伪代码码中的s_t
            action: 本次交互选择的动作, 也就是公式或者伪代码中的a_t
            reward: 本次与环境交互后的奖励,  也就是公式或者伪代码中的r
            next_obs: 本次交互环境返回的下一个状态,也就是s_t+1
            next_action: 根据当前的Q表,针对next_obs会选择的动作,a_t+1
            done: 回合episode是否结束
        """
        predict_Q = self.Q[obs, action]
        if done:
            target_Q = reward     # 如果到达终止状态, 没有下一个状态了,直接把奖励赋值给target_Q
        else:
            target_Q = reward + self.gamma * self.Q[next_obs, next_action]      # 这两行代码直接看伪代码或者公式
        self.Q[obs, action] = predict_Q + self.lr * (target_Q - predict_Q)      # 修正q



def run_episode(env, agent, render=False):
    total_steps = 0    # 记录每一个回合episode走了多少step
    total_reward = 0    # 记录一个episode获得总奖励

    obs = env.reset()   # 重置环境,重新开始新的一轮(episode)
    action = agent.sample(obs)    # 根据算法选择一个动作,采用ε-贪婪算法选取动作

    while True:
        next_obs, reward, done, info = env.step(action)    # 与环境进行一次交互,即把动作action作用到环境,并得到环境的反馈
        next_action = agent.sample(next_obs)   # 根据获得的下一个状态,执行ε-贪婪算法后,获得下一个动作

        # 训练Sarsa算法, 更新Q表格
        agent.learn(obs, action, reward, next_obs, next_action, done)

        action = next_action
        obs = next_obs   # 存储上一个观测值(这里状态和观测不区分,正常observation是state的一部分)

        total_reward += reward
        total_steps += 1

        if render:
            env.render()     # 重新画一份效果图
        if done:      # 如果达到了终止状态,则回合结束,跳出该轮循环
            break
    return total_reward, total_steps



def test_episode(env, agent):
    total_reward = 0
    obs = env.reset()

    while True:
        action = agent.predict(obs)  # greedy
        next_obs, reward, done, info = env.step(action)  # 执行一步,这是强化学习最关键的一行代码,通俗讲就是智能体采取这个动作action,环境就相应的发生了变化,得到下一个状态next_obs, 奖励reward, 是否回合结束done(True or False),其它信息info
        total_reward += reward
        obs = next_obs
        time.sleep(0.5)
        env.render()
        if done:
            print('test reward = %.lf' % (total_reward))

def main():
    env = gym.make("CliffWalking-v0")   # 悬崖边行走游戏,动作空间及其表示为:0 up , 1 right, 2 down, 3 left

    agent = SarsaAgent(
        obs_n=env.observation_space.n,
        act_n=env.action_space.n,
        learning_rate=0.1,
        gamma=0.9,
        e_greedy=0.1)

    is_render = False

    for episode in range(500):
        ep_reward, ep_steps = run_episode(env, agent, is_render)
        print('Episode %s: steps = %s, reward = %.lf' % (episode, ep_steps, ep_reward))


        # 每隔20个episode渲染一下看看效果
        if episode % 20 == 0:
            is_render = True
        else:
            is_render = False


    # 训练结束,查看算法效果
    test_episode(env, agent)



if __name__ == '__main__':
    main()

,

            

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

强化学习之Sarsa算法最简单的实现代码-(环境:“CliffWalking-v0“悬崖问题) 的相关文章

随机推荐

  • openGL之API学习(八十)狭义的游戏引擎的定义

    狭义的游戏引擎的定义 wiki 图形渲染 粒子系统 物理系统 骨骼系统 角色系统 动画系统 场景管理 可视剔除 层次细节 界面模块 脚本接口 纹理模型资源管理 音频功能 网络模块 AI模块 视频功能 更新功能 多核支持 外围工具链
  • Cannot find template location: classpath:/templates/(please add some templates or check your Thymel)

    一 异常信息 Cannot find template location classpath templates please add some templates or check your Thymeleaf configuration
  • C++ shared_ptr和std::move

    以shared ptr为参数调用std move并用等于号时 会调用共享指针的移动构造函数 从而使原共享指针失效 include
  • 目标检测——Detectron2的学习笔记

    1 Detectron2的官方地址 https github com facebookresearch detectron2
  • ssh root账号远程连接出现Permission denied错误

    ssh root账号远程连接出现Permission denied错误 网上搜这个问题出来的问题大多都是修改sshd config中的PermitRootLogin yes 但在我修改之后依然无法登陆 搜到了另一个不知道原因的方法 把你要远
  • 李彦宏被《时代》周刊评为全球AI领袖

    北京时间9月7日晚 时代 周刊发布了首届全球百大AI人物 百度创始人 董事长兼首席执行官李彦宏被评为全球AI领袖 时代 肯定了李彦宏对AI的长期投入及百度在AI方面取得的多项成就 李彦宏是中国最杰出的未来主义者 长期投身于AI发展的浪潮 A
  • NLP领域的预训练模型(Transformer、BERT、GPT-2等)

    英文原文链接 https www analyticsvidhya com blog 2019 03 pretrained models get started nlp 1 介 绍 如今 自然语言处理 Natural Language Pro
  • 远景智能笔试

    第一次复习 操作系统只给一个进程一个时间片 不管你内部有多少个线程 我只给你一个 怎么分配是你的事情 第一次做 30 没有听过的题目 50 知道个大概的题目 20 有把握的题目 远景智能笔试题目链接 多线程和多进程 父子进程间遵循读时共享写
  • MySQL5.7与8.0数据库驱动配置区别

    MySQL5 7 spring datasource url jdbc mysql 192 168 31 200 3306 xxl job useUnicode true characterEncoding utf 8 useSSL fal
  • 深度学习Week9-YOLOv5-C3模块实现(Pytorch)

    本文为 365天深度学习训练营 中的学习记录博客 参考文章 Pytorch实战 第P8天 YOLOv5 C3模块实现 训练营内部成员可读 原作者 K同学啊 接辅导 项目定制 了解C3的结构 方便后续YOLOv5算法的学习 采用的数据集是天气
  • WPF疑难问题之Treeview中HierarchicalDataTemplate多级样式

    文章目录 一 问题场景 二 解决思路 一 问题场景 日常为 TreeView 自定义样式过程中 如果涉及到树形多级样式不同时 又该如何去做 例如树形显示文件夹和文件节点 TreeView 样式如下
  • React 组件生命周期

    组件的生命周期可分成三个状态 Mounting 已插入真实DOM Updating 正在被重新渲染 Unmounting 已移除真是DOM 生命周期的方法有 componentWill ount 在渲染前调用 在客户端也在服务端 compo
  • Win11 锁屏、开机画面使用window聚焦 壁纸失效解决方案

    1 设置 gt 个性化 gt 锁屏界面 gt 个性化锁屏界面 切换为图片 2 打开文件资源管理器 导航栏中点击查看 gt 显示 gt 勾选隐藏的项目 3 打开C 用户 你的用户 AppData Local Packages Microsof
  • Apache Mina学习笔记:JavaNIO框架Mina、Netty、Grizzly介绍与对比

    在开始代码编写 之前 最好先对现有的主流Java NIO框架作一个简单的了解 本文对Java NIO框架 Mina Netty Grizzly作简单的介绍与对比 我们先来看看三者之间的简介 Mina Mina Multipurpose In
  • cocos2d-x 自带动画

    cocos2d x 自带动画 声明 博文内容为自己整理笔记所用 有不对的地方还请大家指正 在cocos2dx 中的tests 项目里 已经带了 足够多的 动画事例 ActionsTest 我只是看了其中一些 自我感觉比较常用的动画 Acti
  • python的基础知识

    Python 的基础知识总结 一 元祖 Python的元组与列表类似 不同之处在于元组的元素不能修改 元组使用小括号 列表使用方括号 元组创建很简单 只需要在括号中添加元素 并使用逗号 隔开即可 例如 tup1 physics chemis
  • C++ fill()和fill_n()函数用法

    fill 和fill n函数是C Primer第十二章泛型算法部分内容 并把它们称为生成和变异算法 也就是说这两个函数只能对输入范围内已存在的元素进行操作 如果试图对空容器进行fill n操作 会导致严重的运行错误 所以在对元素进行写入操作
  • gpt 语言模型_了解gpt 3 openais最新语言模型

    gpt 语言模型 1 简介 1 Introduction If you have been following the recent developments in the NLP space then it would be almost
  • 男人副业做什么好?男生适合做啥副业?男士副业都有什么

    现在生活压力大 男人光靠自己的那点工资肯定是不行的 因为要买车要买房的 所以下班后找点副业或者兼职来做 成了很多上班族增加收入的一种方法 那么适合男人下班后的副业有哪些呢 1 游戏陪玩或者代打 比如现在蛮火的比心陪练APP就很不错 里面有英
  • 强化学习之Sarsa算法最简单的实现代码-(环境:“CliffWalking-v0“悬崖问题)

    1 算法简介 直接上伪代码 伪代码解释 第一行 设置动作空间A和状态空间S 以后你agent只能执行这A中有的动作 你环境的状态也就S中这么些 初始化Q表格 也就是表格的横坐标为动作 纵坐标为状态 每个格子里面的值表示 纵坐标对应的状态s下