实验四、格子世界(Grid World)

news2025/7/6 21:14:52

一、实验目的

1)熟悉动态规划算法中策略评估过程;

2)了解如何对问题进行建模处理,包括环境、状态、动作、奖惩值的初始化;

二、实验内容与要求

1)掌握动态算法基本思想,以及策略估计和策略改进过程

2)理解状态值函数及其定义:

3)掌握策略估计方法,伪代码如下:

(4)实验要求:

输入(根据Gridworld问题初始化):

 能够动态输入状态个数(例如5*5,6*6,…);

 动作空间4个(up,down,left,right);

 一般的立即奖惩值根据状态和下一动作设定为0或者-1。

输出:

根据Bellman公式计算得到的最后值和对应策略,用图形界面显示(自行设计),在每次迭代中所更新的每个状态的下一动作、立即奖惩值及值需记录在log中(使用XML文档保存)。

三、实验过程及代码

1引入要用的的库,初始化参数,接收输入的格子行数,定义起点和终点的位置,确定折扣因子,设定动作集,设定动作执行概率。

import numpy as np

import matplotlib.pyplot as plt

from matplotlib.table import Table

from xml.dom.minidom import Document

#手动输入格子的大小

WORLD_SIZE = int(input("请输入行数:"))

# 起点和终点的位置(下标从0开始,下同)

START_POS = [0,0]

END_POS = [WORLD_SIZE-1, WORLD_SIZE-1]

# 折扣因子

DISCOUNT = 0.9

# 动作集={上,下,左,右}

ACTIONS = [np.array([0, -1]),  # left

           np.array([-1, 0]),  # up

           np.array([0, 1]),   # right

           np.array([1, 0])]   # down

# 策略,每个动作等概率

ACTION_PROB = 0.25

2写好文件写入函数,方便后续调用。

def write_datato_xml(data,name):

    # 实例化一个Domcument

    dom = Document()

    # 创建根节点

    paper = dom.createElement("Paper")

    # 将根节点添加到domcument中

    dom.appendChild(paper)

    # 循环遍历所有数据,写入domcument中

    # 将sortnumber 写入

    for x in range(len(data)):

        # 创建sortnumber标签

        sortnumber = dom.createElement(name)

        # 将sortnumber加入到根节点paper

        paper.appendChild(sortnumber)

        # 取出每一个数据

        x_data = data[x]

        # 创建text标签

        sortnumber_text = dom.createTextNode(x_data)

        # 将text标签加入到sortnumber标签中

        sortnumber.appendChild(sortnumber_text)

        # 添加属性

        sortnumber.setAttribute("迭代次数",'{}'.format(x))

    with open("data.xml",'w',encoding='utf-8') as f:

        # f:文件对象,indent:每个tag前面填充的字符,addindent:每个子节点的缩进字符,newl:每个tag后填充的字符

        dom.writexml(f, indent='\t', newl='\n', addindent='\t')

        f.close()

3写好绘图函数,方便后续调用

def draw_image(image):

    fig, ax = plt.subplots()

    ax.set_axis_off()

    tb = Table(ax, bbox=[0, 0, 1, 1])

    nrows, ncols = image.shape

    width, height = 1.0/ ncols, 1.0/ nrows

    # 添加表格

    for (i, j), val in np.ndenumerate(image):

        if [i,j] == START_POS:

            tb.add_cell(i, j, width, height, text=val,

                    loc='center', facecolor='Blue')

        elif [i,j] == END_POS:

            tb.add_cell(i, j, width, height, text=val,

                    loc='center', facecolor='Red')

        else:

            tb.add_cell(i, j, width, height, text=val,

                    loc='center', facecolor='white')

    # 行标签

    for i, label in enumerate(range(len(image))):

        tb.add_cell(i, -1, width, height, text=label + 1, loc='right',

                    edgecolor='none', facecolor='none')

    # 列标签

    for j, label in enumerate(range(len(image))):

        tb.add_cell(WORLD_SIZE, j, width, height / 2, text=label + 1, loc='center',

                    edgecolor='none', facecolor='none')

ax.add_table(tb)

(4)指定步行策略,当回到起点和终点时奖励0分,并走一步,当撞墙时,奖励-1分,并原地不动,其他步行均奖励-1分并走一步。

def step(state, action):

    if state == START_POS:

        return START_POS, 0

    if state == END_POS:

        return END_POS, 0

    next_state = (np.array(state) + action).tolist()

    x, y = next_state

    # 判断是否出界

    if x < 0 or x >= WORLD_SIZE or y < 0 or y >= WORLD_SIZE:

        reward = -1.0

        next_state = state

    else:

        reward = -1.0

    return next_state, reward

(5)使用迭代策略评估计算每个单元格的状态价值函数,遍历执行动作,转移到后继状态,并获得立即惩奖值,求解贝尔曼方程,每一轮迭代都会产生一个new_value,直到new_value和value很接近即收敛为止,迭代终止条件设定为delta小于0.0001,求解出的16个最终状态价值如下图所示。

def grid_world_value_function():

    # 状态价值函数的初值

    value = np.zeros((WORLD_SIZE, WORLD_SIZE))

    episode = 0

    history = {}

    status = [];

    while True:

        episode = episode + 1

        new_value = np.zeros_like(value)

        for i in range(WORLD_SIZE):

            for j in range(WORLD_SIZE):

                for action in ACTIONS:

                    (next_i, next_j), reward = step([i, j], action)

                    # bellman equation

                    # 由于每个方向只有一个reward和s'的组合,这里的p(s',r|s,a)=1

                    # 贝尔曼期望方程

                    new_value[i, j] += ACTION_PROB * (reward + DISCOUNT * value[next_i, next_j])

        delta  = np.sum(np.abs(new_value - value))

        history[episode] = delta

        # 迭代终止条件: delta小于1e-4

        if delta  < 1e-4:

            draw_image(np.round(new_value, decimals=2))

            plt.title('$v_{\pi}$')

            plt.show()

            plt.close()

            break

        # 观察每一轮次状态价值函数及其delta的变化情况

        value1 = f"第{episode}轮-delta:{np.round(delta ,decimals=5)}:\n{np.round(new_value,decimals=2)}";

        status.append(value1);

#         print(f"{episode}-{np.round(delta ,decimals=5)}:\n{np.round(new_value,decimals=2)}")

        value = new_value

    write_datato_xml(status,"grid_world_value_function")

return history, value

6)通过迭代求解贝尔曼函数,计算每个格子往各个方向的动作值,并取每个格子的最大值作为该格子的最优动作值,通过该数值可知每个格子该往哪个方向前进。求解出的16个最终的动作值如下图所示。

(7)通过本图可以发现,所有包含且仅包含2个-1.0,两个-1.9,一个-2.71的路径都是最优路径。

def grid_world_optimal_policy():

    value = np.zeros((WORLD_SIZE, WORLD_SIZE))

    # 通过一个数组来表示每一个格子的最优动作,1表示在相应的方向上最优的

    optimal_policy = np.zeros((WORLD_SIZE, WORLD_SIZE, len(ACTIONS)))

    episode = 0

    while True:

        episode = episode + 1

        # keep iteration until convergence

        new_value = np.zeros_like(value)

        for i in range(WORLD_SIZE):

            for j in range(WORLD_SIZE):

                # 保存当前格子所有action下的state value

                action_values = []

                for action in ACTIONS:

                    (next_i, next_j), reward = step([i, j], action)

                    # 缓存动作值函数 q(s,a) = r + γ*v(s')

                    action_values.append(reward + DISCOUNT * value[next_i, next_j])

                # 根据贝尔曼最优方程,找出最大的动作值函数 q(s,a) 进行更新

                new_value[i, j] = np.max(action_values)

                # optimal_policy[i, j] = get_optimal_actions(action_values)

        delta  = np.sum(np.abs(new_value - value))

        #迭代终止条件: delta小于1e-4

        if delta  < 1e-4:

            draw_image(np.round(new_value, decimals=2))

            plt.title('$v_{*}$')

            plt.show()

            plt.close()

            break

        # 观察每一轮次状态价值函数及其delta的变化情况

        print(f"第{episode}轮-delta:{np.round(delta ,decimals=5)}:\n{np.round(new_value,decimals=2)}")

        value = new_value

绘制迭代策略评估的曲线

def plot_his(history, title):

    index, delta  = history.keys(), history.values()

    plt.plot(index, delta )

    plt.title(title)

    plt.xlabel("episode")

    plt.ylabel("delta ")

    if len(history) != 1:

        plt.legend(["grid_world_value_function", "grid_world_value_function_in_place"])

plt.show()

(8)写入xml文件的每次迭代的数据如下:

四、实验分析及总结

强化学习过程可以看做一系列的state、reward、action的组合。在学习中,我们关注的不仅仅是当前的reward,因状态的转移可能对未来的收益都有影响,所以我们关注的是总体reward之和。为了数学上使得reward之和收敛,此处选择了一个折扣因子 discount 。当discount =1时,表明未来以及现在的reward具有相同的权重,可以说此时的agent是一个 far-sighted,当discount =0时,表明完全不考虑未来的reward,只考虑当下,可以说此时的agent是一个 myopic。当我们从当前状态 s 转移到下一时刻状态时,对下一时刻每一个状态s’ 存在一个从状态s 到 s’的状态转移概率 Pss′,那么当前状态的价值函数可以表示为当前状态的reward 加上带discount的下一时刻状态s与状态转移概率 Pss′乘积的累加和。策略表示在状态s下采取动作a的概率,每个动作都伴随着状态的转移,所以找出最优的状态价值函数就意味着, 找出了最优策略。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/109240.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为机试_HJ27 查找兄弟单词【中等】

目录 描述 输入描述&#xff1a; 输出描述&#xff1a; 解题过程 提交代码 学习代码 代码一 收藏点 描述 定义一个单词的“兄弟单词”为&#xff1a;交换该单词字母顺序&#xff08;注&#xff1a;可以交换任意次&#xff09;&#xff0c;而不添加、删除、修改原有的字…

Linux系统 PHP安装expect扩展详解

今天继续给大家介绍服务器运维相关知识&#xff0c;本文主要内容是Linux系统 PHP安装expect扩展详解。 一、expect简介 expect是基于tcl语言开发的&#xff0c;用于实现自动和交互式任务进行通信&#xff0c;而无须人的干预。expect是建立在tcl基础上的一个工具&#xff0c;还…

Navicat--对比和同步MySQL表结构的方法

原文网址&#xff1a;Navicat--对比和同步MySQL表结构的方法_IT利刃出鞘的博客-CSDN博客 简介 本文介绍如何使用Navicat对比和同步MySQL表结构的方法。 实际项目中会遇到这样的场景&#xff1a;将测试环境的表结构同步到生产环境。 工具> 结构同步 选择源数据库和目标数据…

tensorflow 基本概念和基本操作

op和tensor之间的关系 op是graph上的节点&#xff0c;线就是tensor。 op输入tensor&#xff0c;同时也产出下游的tensor 作为每一个tensor&#xff0c;都会有一个op的属性(attribute)&#xff0c;该op就代表着这个tensor是被什么计算产出的。举个例子&#xff1a; In [74]: w…

Redis6 主从复制

Redis6 主从复制1. 什么是主从复制2. 能做什么3. 配置1主2从3.1 配置3.2 启动redis3.3 配置主从关系4.常见问题4.1 一主二仆5. 主从复制原理6. 薪火相传7. 反客为主1. 什么是主从复制 主机数据更新后根据配置和策略&#xff0c; 自动同步到备机的master/slaver机制&#xff0c…

C++--数据结构--最短路径--Dijkstra--Bellman-Ford算法--Floyd-Warshall算法--高阶0713 14

注&#xff1a;本篇所用的某些未在本文中实现的函数&#xff0c;或不明确的类&#xff0c;均在上篇博客中有详细过程&#xff0c;因篇幅问题不再赘述。 C--数据结构--图的相关概念及模拟实现--高阶0712_Gaze&#xff01;的博客-CSDN博客 1. Dijkstra算法 Dijkstra算法需要开辟…

spring-boot 接收form表单 多文件加多字段数据(postman在form-data格式下传数组和集合)

前言 该博客多用于记录自己的问题 在写项目的时候遇到这种业务情况&#xff1a; 需要保存整个页面的数据&#xff0c;数据包含多个字段信息和多个文件 结合网上的处理思路&#xff0c;我最终实现了这种业务需求并整理一下 前端单独提交字段和文件比较方便简单&#xff0c;本人…

带你读AI论文丨针对文字识别的多模态半监督方法

摘要&#xff1a;本文提出了一种针对文字识别的多模态半监督方法&#xff0c;具体来说&#xff0c;作者首先使用teacher-student网络进行半监督学习&#xff0c;然后在视觉、语义以及视觉和语义的融合特征上&#xff0c;都进行了一致性约束。本文分享自华为云社区《一种针对文字…

构建高性能内存队列:Disruptor

1、 背景 Java中有哪些队列 ArrayBlockingQueue 使用ReentrantLock LinkedBlockingQueue 使用ReentrantLock ConcurrentLinkedQueue 使用CAS 等等 我们清楚使用锁的性能比较低&#xff0c;尽量使用无锁设计。接下来就我们来认识下Disruptor。 2、Disruptor简单使用 github地…

Web3中文|可判115年监禁的FTX创始人SBF即将被引渡到美国

巴哈马总检察长办公室在宣布逮捕FTX前CEO Sam Bankman-Fried时&#xff0c;指出他很可能应美国要求被引渡。 一个多星期后&#xff0c;美国广播公司新闻报道称 &#xff0c;SBF于12月20日签署了引渡文件。 另据彭博社12月20日的一份报告称&#xff0c;该交易所创始人SBF于12月…

Centos7安装配置Minio

Background 官方下载地址&#xff1a;https://github.com/minio/minio/releases 这里给出本次使用的一个版本&#xff1a;minio-2021-05-11T23:27:41Z&#xff0c;提取码&#xff1a;king 1、下载minio文件夹 其他的版本的相关命令可能发生变化&#xff0c;这里只是针对我提供…

基于GIS的生态安全格局构建之生态阻力面的建立

GIS前沿 一、数据来源介绍 &#xff08;一&#xff09;土地利用数据 土地利用数据来自国土资源三次调查数据&#xff08;2018年&#xff09;&#xff0c;根据研究需要对其进行分析处理。 &#xff08;二&#xff09;生态安全等级数据 利用对从生态属性和生态干扰两方面选择的…

Junit5 + YAML 轻松实现参数化和数据驱动,让 App 自动化测试更高效(一)

登录&#xff1a;不同的用户名&#xff0c;不同的密码&#xff0c;不同的组合都需要做登录场景的测试&#xff0c;正常的排列组合下可能会产生多个用例 搜索&#xff1a;不同的搜索条件产生不同的搜索结果&#xff0c;搜索也是常见的测试项&#xff0c;单个搜索参数或者多种搜…

Java---正则表达式

目录 一、正则表达式的介绍 二、正则表达式的基本语法 &#xff08;1&#xff09;字符类 &#xff08;2&#xff09;预定义符 &#xff08;3&#xff09;数量词 三、正则表达式的具体实例 &#xff08;1&#xff09;判断电话号码是否符合规则 &#xff08;2&#xff09;…

git push踩坑记录【看注意事项】

记录一次git push的踩坑过程&#xff08;详细在注意事项里&#xff0c;列出了具体的解决办法&#xff09;。 push远程仓库命令 使用命令 git init git add . git commit -m "提交说明写在这里" git remote add origin gitgithub.com:xxx/surgical-robot.git git p…

4、常用类和对象

文章目录4、常用类和对象4.1 Object4.2 数组4.3 二维数组4.4 二维数组 九层妖塔4.5 冒泡排序4.6 选择排序4.7 二分法查找4.8 字符串4.9 字符串拼接4.10 字符串比较4.11 字符串截断4.12 字符串替换4.13 字符串大小写转换4.14 字符串查询4.15 StringBuilder4.16 包装类4.17 日期类…

windows环境下python和gdal绑定方法

作者:朱金灿 来源:clever101的专栏 为什么大多数人学不会人工智能编程?>>> 编译和安装gdal 此篇介绍的方法并不需要用到pip工具,可依据自己编译的gdal库来灵活绑定。 安装gdal主要是设置两个环境变量:一是gdal的动态库路径加入到path环境变量下,如下图: 二是…

vim的常规操作

Linux系统内置vi文本编辑器&#xff0c;vim是vi的增强版 vi和vim的三种模式 正常模式&#xff1a;默认模式&#xff0c;可以使用“上下左右”键来移动光标&#xff0c;也可以用删除、复制、粘体等功能插入模式&#xff1a;按i,I,o,O,a,A,r,R等任何一个字母进入命令行模式&…

django logging的StreamHandler的一个小用法

首先先了解下&#xff0c;logging的大致结构&#xff0c;它有一个内置处理器&#xff0c;还有一个django提供的内置记录器。基本上&#xff0c;日志模块就是由这俩组成的&#xff0c;他俩的关系&#xff0c;有点水渠理论的意思。就是说&#xff0c;处理器&#xff0c;和记录器&…

MCU-51:独立按键控制LED灯的动作

目录一、独立按键二、独立按键控制LED亮灭二、消除按键抖动2.1 按键的抖动2.2 控制LED灯状态-消除按键抖动三、独立按键控制LED显示二进制四、独立按键控制LED灯移位一、独立按键 轻触按键&#xff1a;相当于是一种电子开关&#xff0c;按下时开关接通&#xff0c;松开时开关断…