如何在时间循环里最优决策——时间旅行者的最优决策

文章目录

  • 每日一句正能量
  • 前言
  • 时间旅行和平行宇宙
  • 强化学习
  • 策略梯度算法
  • 代码案例
  • 推荐阅读
  • 赠书活动

每日一句正能量

做一个决定,并不难,难的是付诸行动,并且坚持到底。

前言

时间循环是一类热门的影视题材,其设定常常如下:主人公可以主动或被动的回到过去。与此同时,主人公会希望利用这样的机会改变在之前的经历中不完美的结果。为此,主人公调整自己的行为,使得结果发生变化。
在这里插入图片描述

一些和时间循环有关的电影

例如,时间循环电影开山之作《土拨鼠之日》(Groundhog Day)讲述了男主被困在土拨鼠日(2月2日)这一天,在日复一日的重复中不断调整自己的行为,终于成功追求到心爱的女主角并跳出时间循环。

试想,如果你是落入时间循环的主角,那应该如何决策才能趋利避害呢?

时间旅行和平行宇宙

在讨论决策的方法之前,首先要指出,只有在某些时间旅行设定下,才可能发挥主观能动性趋利避害。

时间旅行的设定要从时间悖论谈起。时间悖论是指由于时间旅行而引发的悖论。下面来看一个时间悖论的例子:我网购了一箱盲盒希望能抽到值钱的限量款。但是我收到盲盒并拆开后发现里面都是不值钱的普通款,并没有值钱的限量款。这时候我就可以考虑时间旅行,告诉过去的自己说别买盲盒,因为我抽不到限量款。然后过去的我听从了我的建议,导致我没有买盲盒。这就引发了悖论:我既然没有买盲盒,怎么知道我如果买了盲盒抽不到限量款?我既然不知道我买了盲盒也抽不到限量款,我怎么会告诉过去的自己这个事情?这里就有矛盾。
在这里插入图片描述

时间旅行引发的悖论

对于这样的时间悖论,有以下几种常见解释:

  • 时间不可逆。这种解释认为,时间维度和其他空间维度不同,它是不对称的、不可逆的。所以,时间旅行不存在。这种解释否认了时空旅行的存在性,悖论就不可能发生。

  • 命定悖论:命定悖论不是一个悖论,而是对时间悖论的解释。这种解释认为,时间旅行不能改变结果,所有的结果都是“命中注定的”,是已经考虑了时间旅行后的综合结果。例如,在盲盒的例子中,我是否买盲盒,已经是考虑了时间旅行的结果。即使未来的我告诉过去的我不要买盲盒,过去的我依然会固执地买了盲盒,最终知道盲盒里没有限量款。

  • 平行宇宙:这种解释认为,时间旅行者进行时间旅行时,并不是到旅行到其原来所在的宇宙,而是旅行到其他宇宙(称为“平行宇宙”)。原来宇宙中的结果不会改变,改变的只可能是其他平行宇宙中的结果。比如在盲盒的例子中,拆了盲盒的我所在的宇宙中我依然还是买了盲盒、拆了盲盒,而我是告诉另外一个宇宙的自己不要买盲盒,所以另外一个宇宙中的自己并没有买盲盒、拆盲盒。

不同的时间悖论解释对应着不同的设定。在不同的设定下我们的能做的也不相同。

在时间不可逆的设定中,时间循环不存在,所以没啥可研究的。

在命定悖论的设定中,一切都是命中注定的,一切事情是你已经发挥了主观能动性的结果,不可能存在其他不同的结果。

在平行宇宙设定中,虽然不能改变当前宇宙中的结果,但是有希望在其他宇宙中获得更好的结果,这才是值得我们讨论的设定。

强化学习

那么在平行宇宙的设定下,我们应该怎样决策才能趋利避害呢?学术界对此已经有了完美的解决方案,那就是强化学习。

强化学习的通常设定如下:在系统里有智能体和环境,智能体可以观察环境、做出动作决策,环境会在动作决策的影响下演化,并且会给出奖励信号来指示智能体的成功程度。智能体希望得到的总奖励信号尽可能多。

智能体可以一遍又一遍的和环境交互。每一轮序贯交互称为一个回合。智能体可以和环境一个回合又一个回合的交互,并在交互过程中学习并改进自己的策略。我们可以把一个训练回合看作在一个宇宙内,通过在多个宇宙的训练结果,让自己在后续宇宙中的结果更优。

强化学习有很多算法,下面我们来介绍其中的一种比较简单的算法——策略梯度算法。

策略梯度算法

强化学习有很多算法,下面我们来介绍一个比较简单的算法——策略梯度算法(Vanilla Policy Gradient,VPG)。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
当然,上述解释并不是非常严格的数学证明。按照强化学习的理论,其理论基础是策略梯度定理,有兴趣的读者可以看《强化学习:原理与Python实战》查阅其定理的内容、证明和解释。

代码案例

现在我们来通过一个代码案例,演示策略梯度算法的使用。

为了简单,我们选择了一个简单的环境:车杆平衡(CartPole-v0)。

车杆平衡问题由强化学习大师级人物Andrew Barto等人在1983年的论文《Neuronlike adaptive elements that can solve difficult learning control problem》里提出后,大量的研究人员对该环境进行了研究、大量强化学习教程收录了该环境,使得该环境成为最著名的强化学习环境之一。
在这里插入图片描述
车杆平衡CartPole问题(图片来源:https://gym.openai.com/envs/CartPole-v0/)

车杆平衡问题如图,一个小车(cart)可以在直线滑轨上移动。一个杆(pole)一头连着小车,另一头悬空,可以不完全直立。小车的初始位置和杆的初始角度等是在一定范围内随机选取的。智能体可以控制小车沿着滑轨左移或是右移。出现以下情形中的任一情形时,回合结束:

  • 杆的倾斜角度超过12度;

  • 小车移动超过2.4个单位长度;

  • 回合步数达到回合最大步数。

每进行1步得到1个单位的奖励。我们希望回合能够尽量的长。

任务CartPole-v0回合最大步数为200。

这个问题中,观察值有4个分量,分别表示小车位置、小车速度、木棒角度和木棒角速度,其取值范围如表所示。动作则取自{0,1},分别表示向左施力和向右施力。
在这里插入图片描述
用法:想要用这个环境,需要先安装Python库Gym。安装Gym库的方法可以参见

https://github.com/ZhiqingXiao/rl-book/blob/master/zh2023/setup/setupwin.md

安装好Gym库后,可以用下列代码导入环境。

代码 导入环境

import gym
env = gym.make("CartPole-v0")

在实现智能体之前,我们先来实现智能体和环境的交互函数。函数play_episode()让智能体和环境交互一个回合。这个函数有三个参数:

  • 环境对象env:它可以通过gym.make(“CartPole-v0”)直接获得。

  • 智能体对象agent:我们一会儿要实现智能体类,它就是智能体类的对象。这个智能体需要实现一些成员,包括agent.reset(mode)、agent.step(observation, reward, terminated)、agent.close()。后文会介绍如何实现这些成员。

  • 模式参数mode:字符串类型,可以是’train’和’test’。这个参数会进一步传到agent.reset(mode)中。如果是’train’那么智能体会处于训练模式,会更新参数;如果是’test‘则智能体会处于训练模式。

在函数内部,先初始化环境和智能体。然后环境和智能体不断交互,直到回合结束或截断(截断指达到了回合最大的步数)。然后返回回合步数和回合总奖励。

代码 智能体和环境交互一个回合

def play_episode(env, agent, mode=None):# 初始化observation, _ = env.reset()reward, terminated, truncated = 0., False, Falseagent.reset(mode=mode)episode_reward, elapsed_steps = 0., 0# 交互whileTrue:action = agent.step(observation, reward, terminated)if terminated or truncated:breakobservation, reward, terminated, truncated, _ = env.step(action)episode_reward += rewardelapsed_steps += 1# 结束agent.close()return episode_reward, elapsed_steps

接下来我们来看智能体类VPGAgent类。

在这里插入图片描述
除了基于PyTorch实现外,也可以基于TensorFlow来实现对应的功能。文末既给出了两套代码的链接,一套基于PyTorch,另一套基于TensorFlow,你可以任选一个。这两套代码都收录在了书籍《强化学习:原理与Python实现》中。

我们来看看基于PyTorch的类VPGAgent的详细实现。它的构造函数__init__(self, env)准备了策略函数self.policy_net是Softmax激活的线性层,指定了优化器为Adam优化器。初始化函数reset(self, mode)在训练模式下,准备好存储轨迹的列表self.trajectory,以便于后续交互时存储轨迹。交互函数step(self, observation, reward, terminated)根据观测给出动作概率,并且训练模式下存储交互记录到self.trajectory中。结束函数close(self)在训练模式下调用学习函数learn(self)。学习函数learn(self)利用self.trajectory中存储的记录进行训练:先得到得到状态张量state_tensor、动作张量action_tensor和回合奖励张量return_tensor。再利用状态张量和动作张量计算对数概率。在计算对数概率时,使用了torch.clamp()函数限制数值范围,以提升数值稳定性。利用回合奖励张量和对数概率张量进而计算得到损失张量loss_tensor,最后用优化器optimizer减小损失。

代码 智能体

import torch
import torch.distributions as distributions
import torch.nn as nn
import torch.optim as optimclass VPGAgent:def __init__(self, env):self.action_n = env.action_space.nself.policy_net = nn.Sequential(nn.Linear(env.observation_space.shape[0], self.action_n, bias=False),nn.Softmax(1))self.optimizer = optim.Adam(self.policy_net.parameters(), lr=0.005)def reset(self, mode=None):self.mode = modeif self.mode == 'train':self.trajectory = []def step(self, observation, reward, terminated):state_tensor = torch.as_tensor(observation, dtype=torch.float).unsqueeze(0)prob_tensor = self.policy_net(state_tensor)action_tensor = distributions.Categorical(prob_tensor).sample()action = action_tensor.numpy()[0]if self.mode == 'train':self.trajectory += [observation, reward, terminated, action]return actiondef close(self):if self.mode == 'train':self.learn()def learn(self):state_tensor = torch.as_tensor(self.trajectory[0::4], dtype=torch.float)action_tensor = torch.as_tensor(self.trajectory[3::4], dtype=torch.long)return_tensor = torch.as_tensor(sum(self.trajectory[1::4]), dtype=torch.float)all_pi_tensor = self.policy_net(state_tensor)pi_tensor = torch.gather(all_pi_tensor, 1, action_tensor.unsqueeze(1)).squeeze(1)log_pi_tensor = torch.log(torch.clamp(pi_tensor, 1e-6, 1.))loss_tensor = -(return_tensor * log_pi_tensor).mean()self.optimizer.zero_grad()loss_tensor.backward()self.optimizer.step()agent = VPGAgent(env)

这样我们就实现了智能体。接下来,我们进行训练和测试。为了完整性,在此附上训练和测试的代码。训练的代码不断进行回合,直到最新的几个回合总奖励的平均值超过某个阈值。测试的代码则是交互100个回合求平均。

代码 智能体和环境交互多个回合以训练智能体

import itertools
import numpy as npepisode_rewards = []
for episode in itertools.count():episode_reward, elapsed_steps = play_episode(env, agent, mode='train')episode_rewards.append(episode_reward)logging.info('训练回合 %d: 奖励 = %.2f, 步数 = %d',episode, episode_reward, elapsed_steps)if np.mean(episode_rewards[-20:]) > env.spec.reward_threshold:break
plt.plot(episode_rewards)

代码 智能体与环境交互100回合来测试智能体性能

episode_rewards = []
for episode in range(100):episode_reward, elapsed_steps = play_episode(env, agent)episode_rewards.append(episode_reward)logging.info('测试回合%d:奖励 = %.2f,步数 = %d',episode, episode_reward, elapsed_steps)
logging.info('平均回合奖励 = %.2f ± %.2f',np.mean(episode_rewards), np.std(episode_rewards))

完整的代码和运行结果参见:

  • PyTorch版本:
    https://zhiqingxiao.github.io/rl-book/en2023/code/CartPole-v0_VPG_torch.html

  • TensorFlow版本:
    https://zhiqingxiao.github.io/rl-book/en2023/code/CartPole-v0_VPG_tf.html

通过这篇文章,我们了解时间循环中可能的几种设定,并了解了在平行宇宙设定下可以使用强化学习来改进决策。最后,我们还通过一个编程小例子了解策略梯度算法。

推荐阅读

在这里插入图片描述

《强化学习:原理与Python实战》

揭密ChatGPT关键技术PPO和RLHF

理论完备:
涵盖强化学习主干理论和常见算法,带你参透ChatGPT技术要点;

实战性强:
每章都有编程案例,深度强化学习算法提供TenorFlow和PyTorch对照实现;

配套丰富:
逐章提供知识点总结,章后习题形式丰富多样。还有Gym源码解读、开发环境搭建指南、习题答案等在线资源助力自学。

购买链接:
https://item.jd.com/13815337.html

赠书活动

  • 🎁本次送书1~4本【取决于阅读量,阅读量越多,送的越多】👈
  • ⌛️活动时间:截止到2023-11月19号
  • ✳️参与方式:关注博主+三连(点赞、收藏、评论)

转载自:https://blog.csdn.net/u014727709/article/details/134304113
欢迎 👍点赞✍评论⭐收藏,欢迎指正

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Data JPA 项目配置与QueryDSL集成

一、说明 Spring Data JPA通过Spring Initializer创建时勾选相关依赖即可引入,QueryDSL需要单独引入。Spring JPA针对QueryDSL有比较好的兼容性,可以实现优雅的SQL构建。 二、设置JPA默认配置(yaml格式) spring:jpa:hibernate:…

2023.11.8 hadoop学习-概述,hdfs dfs的shell命令

目录 1.分布式和集群 2.Hadoop框架 3.版本更新 4.hadoop架构详解 5.页面访问端口 6.Hadoop-HDFS HDFS架构 HDFS副本 7.SHELL命令 8.启动hive服务 1.分布式和集群 分布式: 多台服务器协同配合完成同一个大任务(每个服务器都只完成大任务拆分出来的单独1个子任务)集 群:…

HTTP-HTTPS区别详解

一、HTTP协议 1. GET和POST的请求的区别 Post 和 Get 是 HTTP 请求的两种方法,其区别如下: 应用场景: GET 请求是一个幂等的请求,一般 Get 请求用于对服务器资源不会产生影响的场景,比如说请求一个网页的资源。而 Po…

[模版总结] - 树的基本算法1 - 遍历

树结构定义 一种非线性存储结构,具有存储“一对多”关系的数据元素集合 种类 General Tree TrieB/B 树二叉树 满/完满/完全二叉树 完美BT : 除了叶子结点外所有节点都有两个字节点,每一层都完满填充完全BT: 除最后一层以外其他每一层都完美…

VUE获取当前日期的周日和周六

<template><div><div click"handleLast()">上一周</div><div click"handleNext()">下一周</div><el-calendarref"monChild"v-model"value":first-day-of-week"7":range"[sta…

二十、W5100S/W5500+RP2040树莓派Pico<MQTT连接阿里云控制板载LED>

文章目录 1. 前言2. 简介2.1 初步了解阿里云物联网平台创建产品步骤2.2 阿里云物模型讲解 3 WIZnet以太网芯片4 示例概述4.1 流程图4.2 准备工作核心4.3 连接方式4.4 主要代码概述4.5 结果演示 5 注意事项6 相关链接 1. 前言 物联网平台提供安全可靠的设备连接通信能力&#xf…

【uniapp】签名组件,兼容vue2vue3

网上找了个源码改吧改吧&#xff0c;清除了没用的功能和兼容性&#xff0c;基于uniapp开发的 样子 vue2 使用方法&#xff0c;具体的可以根据业务自行修改 <signature ref"signature" width"100%" height"410rpx"></signature>confi…

Python---列表的循环遍历,嵌套

循环遍历就是使用while或for循环对列表中的每个数据进行打印输出 while循环&#xff1a; list1 [貂蝉, 大乔, 小乔]# 定义计数器 i 0 # 编写循环条件 while i < len(list1):print(list1[i])# 更新计数器i 1 for循环&#xff08;推荐&#xff09;&#xff1a; list1 [貂…

定义无向加权图,并使用Pytorch_geometric实现图卷积

首先定义无向边并定义边的权重 import torch import torch.nn as nn from torch_geometric.nn import GCNConv import torch.nn.functional as F from torch_geometric.data import Dataa torch.LongTensor([0, 0, 1, 1, 2, 2, 3, 4]) b torch.LongTensor([0, 1, 2, 3, 1, 5,…

高能数造电池3D打印智能制造小试线,开启全固态电池数字化新时代

在科技创新的浪潮中&#xff0c;电池制造领域又迎来了一次突破性的进展。近日&#xff0c;高能数造(西安)技术有限公司重磅推出了其最新电池数字制造装备——全固态电池3D打印智能制造小试线 &#xff0c;这一创新性的技术开启了全固态电池的数字化智造新时代&#xff0c;为全固…

scitb包1.5版本发布—增加了统计值的结果和自动判断数据是否正态分布的功能

目前&#xff0c;本人写的scitb包1.5版本已经正式在R语言官方CRAN上线&#xff0c;scitb包是一个为生成专业化统计表格而生的R包。目前只能绘制基线表一。 可以使用以下代码安装 install.packages("scitb")安装过旧版本的从新安装一次就可以升级了 scitb包1.5版本修…

微信小程序案例3-2 计算器

文章目录 一、运行效果二、知识储备&#xff08;一&#xff09;data-*自定义属性&#xff08;二&#xff09;模块 三、实现步骤&#xff08;一&#xff09;准备工作&#xff08;二&#xff09;实现页面结构&#xff08;三&#xff09;实现页面样式&#xff08;四&#xff09;实…