强化学习的数学原理(2)

Value iteration & Policy itreation

Value iteration algorithm
之前我们已经讲过怎么去求解贝尔曼最优公式,是利用contraction mapping theorem 来进行求解,我们知道这个contraction mapping theorem是一个迭代算法,实际上这个算法他有一个名字叫做value iteration(值迭代)

对于贝尔曼最优公式使用contraction mapping theorem算法的分析
在这里插入图片描述
这个算法实际上包含两个部分:
首先就是会给定vk来求解嵌套在这个式子中的优化问题(max),求解出Π,当Π求解出来之后我们在求解vk+1,所以就对应了两个步骤
第一个步骤叫做 policy update:它实际上就是处理右边的优化问题,然后可以得到一个Πk+1
第二个步骤叫做 value update:当我们右边求解出Πk+1之后我们再将其带到等式中,根据vk可以求出vk+1

Step 1:Policy update
在这里插入图片描述
式子Πk+1 = arg max(rΠ+γP Π vk)是policy update 的matrix-vector form,首先我们要求解出Πk+1,那么我们怎么求解呢实际上我们对每个s(s∈S)都可以得到上面的式子,我们带入vk就可以求解出qk。然后求解最优的策略,怎样求解呢,之前讲过其会选取对应qk最大的那个action,我们用ak*来表示,然后其他所有的action的概率都是0,他是一个确定性的、贪婪的策略,其只会选择最大的q-value。

Step 2:Value update
在这里插入图片描述
式子vk+1 = rΠk+1 + γ PΠk+1 vk是Value update 的matrix-vector form,我们可以对每个s都写出它的element-form,还是和上面一样我们可以通过带入vk求解出qk,再将上一步求出的策略Π带入。最后的vk+1结果就是qk中的最大值
伪代码展示
在这里插入图片描述
如何使用value iteration算法例子:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Policy iteration algorithm
这个算法是什么呢:最开始有一个initial policy我们用Π0表示,这个策略可能是任意给定的策略,也许是一个不好的策略,之后会不断的迭代就会找到一个好的策略。
实际上每次迭代会分为两个步骤:
第一个步骤叫做policy evaluation(PE):我们给定一个策略,求解它对应的贝尔曼公式,得到对应的state value ,这样的一个过程就叫policy evaluation,我们求出来的vΠk就是我们要去评估的策略
第二个步骤叫做policy improvement(PI):上一个步骤我们求出一个策略vΠk,然后去求解优化问题(max)得到一个新的策略Πk+1,Πk+1会比Πk更好所以叫做policy improvement
在这里插入图片描述
这样的一个总体过程可以用下图进行表示,不断迭代求解出更好的策略Π
在这里插入图片描述

在policy evaluation中,怎么求解state value
假定我们给定了Πk那么我们可以写出它的贝尔曼公式,然后可以有两种方式去求解它的state value 第一种方法是Closed-from solution(之前博客里面提到过),但是这个方法我们不太会用,因为在这里面涉及到一个矩阵的求解,因此经常用的是iterative solution:最开始我们对vΠk有一个猜测值,然后不断的去迭代,就可以得到这个vΠk
policy evaluation是policy iteration这个算法的其中一步,然后这一步又依赖于一个迭代的算法iterative solution,所以相当于有一个大的迭代算法里面又嵌套了一个小的迭代算法
在这里插入图片描述

在policy improvement里面为什么得到的Πk+1一定是比Πk好的?
因为vΠk+1是通过下面的式子通过vΠk求解处理的,因此vΠk+1一定是大于vΠk的,所以策略Πk+1一定是比策略Πk要好的
在这里插入图片描述

为什么这样一个迭代算法最后能够找到一个最优策略?
因为这个算法里面又有一步policy improvement,所以每一次他都在不断地改进vΠ,不断提高vΠ的值也就是state value的值
在这里插入图片描述

policy iteration和value iteration是什么关系?
其实我们返回到上一个问题,我们最终要求解出最好的策略,我们依赖的是value iteration收敛到最优的state value v*从而使policy iteration 能够最终收敛到最好的策略Π*,另外policy iteration 和value iteration 是两个极端,是Truncated policy iteration算的两个极端

policy iteration算法的具体实现
第一步Policy evaluation
在这里插入图片描述
第二步Policy improvement
在这里插入图片描述
过程的伪代码
在这里插入图片描述

通过例子查看算法工作流程
在这里插入图片描述
右边的s2网格是我们的target area,最优的策略显然是和b一样,在s1的时候往右走,在s2的时候静止不动。然后我们要用policy iteration 算法来得到这个最优策略。
我们可以看到初始策略a是不合适的他都是往左走
在这里插入图片描述
在这里插入图片描述

在算法中接近目标的状态的策略会先变好,远离目标的状态的抽象会后变好

Truncated policy iteration algorithm
Truncated policy iteration并不是一个特别的算法,其只是Value iteration算法和Policy iteration这两个算法的一般化推广
实际上Value iteration和Policy iteration是Truncated policy iteration的两个特殊情况

policy iteration和value iteration比较
Policy iteration是从一个初始的策略Π0(任意策略)出发
Value iteration是从一个初始值v0(任意值)出发
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
针对上面表格来比较两个算法之间有哪些相同和不同
(1)policy iteration要给定初始的策略Π0;value iteration这时候还没开始,因为他没有初始策略,他只有初始的值
(2)policy iteration通过上面给出的策略Π0通过贝尔曼公式求解出vΠ0;value iteration要给定一个初始的值v0(任意值),为了比较这里我们将v0的值设置成vΠ0
(3)policy iteration通过上面求出来的vΠ0求解优化问题求出新的策略Π1;value iteration通过上面给定的v0求解优化问题得到新的策略Π1【目前位置两个算法的每一步是相同的】
(4)policy iteration通过上面得到的Π1求解出贝尔曼公式中的vΠ1;value iteration通过前面步骤得到的Π1和v0求解出v1【此时v1和vΠ1就已经不在相同了,再往下走所得的到的策略和值也不同了】

关于policy iteration中需要求解贝尔曼公式得到vΠ1,需要一个内嵌的迭代算法进行求解
在这里插入图片描述

truncated policy iteration作为value iteration和policy iteration中间步骤,当 j = 1 的时候就变成了value iteration,当 j = ∞ 时就变成policy iteration,但是现实中是不存在policy iteration的,因为不可能与偶任何算法需要计算∞次。
在这里插入图片描述
truncated policy iteration算法伪代码
在这里插入图片描述
在这个过程中有一个很明显的问题就是我们没有计算无穷多步,所以计算出来的vk并不是vΠk,那么这时候这样的截断会不会导致整个算法不在收敛?下面给出一个简单个解释
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

基于蒙特卡洛(Monte Carlo)的强化学习方法

之前我们学习的Value iteration 和 Policy iteration 都是 model-based 的方法现在要学习的基于蒙特卡洛的强化学习方法是 model-free 的方法。在这里我们会将 Value iteration 和 Policy iteration 统称为model-based reinforcement learning(更准确的应该称作 dynamic programming 动态规划的方法)

通过 Motivating example 来介绍 蒙特卡洛强化学习的基本思想
从前面的 model-based 的 reinforcement learning 过渡到 model-free 的reinforcement learning 最重要的也是最难以理解的就是怎么样在没有模型的人情况下去估计一些量,有一个重要的思想就是蒙特卡洛(Monte Carlo Estimation),通过下面投硬币的例子讲述这个思想
我们投掷一枚硬币,我们假设投掷硬币之后产生的结果为X,并且假如正面朝上那么就记为+1,假如反面朝上那么就记为-1,要求我们计算X的平均数或者X的expectation。
在这里插入图片描述
第一种方法是基于模型的 model-based ,这里面X的这个random variable它的probability distribution 我们是知道的,比如说它正面朝上的概率是0.5背面朝上的概率也是0.5,那么它的expectation(平均数)就可以通过它的定义来简单的进行计算
这个算法比较简单,但是这样比较精确的precise distribution 的一个模型我们可能是无法知道的,因此这也是Model-based情况下的问题,那么我们是否可以考虑在没有模型的情况下去估计呢。
在这里插入图片描述
Model-free 的方法的思想就是我们做了很多次实验,这些实验的结果分别是x1,x2,x3,…,xN。我们将这些结果相加,然后再除于这个N就得到了平均值用xbar表示,然后我们将xbar与x的expectation ( E[X] ) 做一个近似,就认为xbar是E[X],这就是Monte Carlo Estimation的一个基本思想
在这里插入图片描述

问题:使用一个平均数来近似E[X]是否是准确的呢?
实际上当我们的试验次数N比较小的时候是不太准确的,但是当试验次数N逐渐增大的时候会越来越精确
在这里插入图片描述
数学证明(大数定理)
在这里插入图片描述

The simplest MC-based RL algorithm
要理解这个算法我们要理解的非常核心的一个问题是我们怎么把 Policy iteration(依赖于模型的model-based) 这个算法变成 model-free。需要将里面Model-based的地方替换成Model-free的版块

Policy iteration 算法怎么变成Model-free
通过之前的学习我们知道 Policy iteration 有两个步骤,分别是通过Πk计算出相应vΠk的 Policy evaluation 以及通过前一步计算出的vΠk进行优化更好的Πk+1的 Policy improvement。然后我们可以将第二步 Policyimprovement 这一步写成下面蓝色字体的形式,然后只需要带入最大的那个qΠk就可以完成优化,因此这里面你你最重要最核心的就是qΠk(s,a)
在这里插入图片描述
这里面计算qΠk有两种方法
第一种方法是依赖于模型的,这就是 Value iteration 算法所使用的。其中它第一步得到了vΠk,并且已经知道相应的模型p(r|s,a),p(s`|s,a),所以我们就可以求出来qΠk
在这里插入图片描述
另一种方法就是不依赖于模型,但是这种方法依赖于qΠk也就是action value 最原始的定义(我们从s(St = s)出发,采取action a(At = a)然后得到一个return(Gt)这个return 是一个random variable我们求它的平均或者求expectation )。所以model-free的强化学习的算法和基于蒙特卡洛的方法的核心思想是使用下面方法二的式子而不是用上图的式子
在这里插入图片描述
具体如何进行求解:首先我们从任意的一个s和a的一个组合(s,a)出发然后我们根据当前的策略Πk得到一个episode;我们计算出这个episode所对应的discounted return 用g(s,a)表示,g(s,a)就是action value 的定义,Gt是得到的discounted return,这是一个random variable,g(s,a)是这个random variable 的一个采样,如果我们有很多这样的采样,有一个集合,我们就可以利用这些采样求一个平均值来估计这个Gt的平均值,这就是 Monte Carlo Estimation
没有数据的时候的有模型,因此没有模型的时候我们就依赖于数据,这里的数据在统计或者概率里面叫做sample,在强化学习当中他有一个特殊的名字叫experience(经验)
在这里插入图片描述

我们可以清晰的看到The MC Basic algorithm 和Policy iteration 的第二步是一样的,唯一多的区别就是在第一步,Policy iteration在第一步求解state value 然后再得到action value ,MC basic这个算法是直接通过数据得到这个qΠk
在这里插入图片描述
伪代码
在这里插入图片描述

  • MC basic这个算法实际上是非常有用的,它能够清晰地揭示怎么把model-based变成model-free这样一个过程,但是他并不实用,因为它的效率是比较低的,之后的两个算法会逐渐地去提高它的效率
  • MC basic当中他是直接来估计action value 而在policy iteration 中他是先估计了state value 然后再装成了 action value ,这是因为如果要去估计 state value 那之后还要再转一遍,然后再转的时候从 state value 到 action value 又需要以来这个模型,那肯定是不行的,所以需要直接把action value 给估计出来
  • 我们知道Policy iteration 是收敛的,那么 MC basic 和 Policy iteration 实际上是一模一样的,只不过他估计action value 的方法是有些差别,但是它的收敛性仍然是能够保证的

通过例子学习 MC basic
我们可以看到下面的例子给出了一个初始策略Π0,在这个策略中只是在s1和s3这个策略不太好,其他的状态这个策略都还不错,下面我们从Π0出发,应用MC basic的算法找到一个最优的策略
在这里插入图片描述
在这个例子里面一共有9个state,每个state又对应5个action所以一共有45个state action pair,所以我们要找到45个qΠk。假设我们从每一个s和a出发我们都要有n条轨迹,最后我们求n条轨迹的平均的return那我们一共要有45*N条轨迹,然后找到qΠk之后第二步就是做policy improvement
在这里插入图片描述
由于 时间原因我们不可能把45个qΠk给找到,这里我们就找5个s1的qΠk
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

MC Exploring Starts
MC Exploring Starts算法其实是MC basic的推广,算法的我效率变得更高效
MC Basic算法的好处:帮我我们很好的理解怎么样用蒙特卡洛的方法来实现不需要模型的强化学习;坏处:考虑的比较少,相对来说效率比较低,在实际当中不太实用。
那怎么实现呢,首先我们考虑这样一个例子,在网格世界中遵循一个策略Π得到了下图这样一个episode
在这里插入图片描述
这里需要引入一个简单的概念Visit(就是在episode当中,它每出现一次这个state-action pair(s1 --a2–>),它都称对这个state-action pair优劣一个visit 有了一次访问)
在MC Basic中我们用的策略是 Initial-visit(对于这个episode只考虑(s1,a2),然后用剩下的所得到的这个return来估计(s1,a2)的action value,然后来估计qΠ(s1,a2) )它的问题就是没有充分利用这个episode,它里面还有很多数据被浪费了
在这里插入图片描述
我们可以从下图看到我们可以用原始的episode来估计出(s1,a2),然后前面的我们就可以不要生成新的一个episode,然后用新的episode来估计(s1,a4),然后依次按照这个流程就可以估计出(s1,s2),(s2,a3),(s5,a1)…这样数据就利用的非常充分
这里面还是有两种方法 first-visit 和 every-visit,他俩的区别就是在这个估计的过程中,我们以原始的episode为例,它第一次估计的是(s1,a2),在后面的episode中还有一次是需要估计(s1,a2)的,这个时候every-visit会再估计一次;对于first-visit的话它就不会再估计,就会使用第一次所估计的结果
在这里插入图片描述
除了如何更高效的利用数据,还有两种方法来解决如何更加高效地更新策略
第一种方法于是在MC Basic中所使用的,就是把所有的episode从一个state-action pair出发的全部给收集在一起,然后做一个average return,来估计action value 但是这个问题就是他需要等所有的episode全部都得到了才行,但是这就导致时间浪费,效率低。
另一种方法就是我们得到了一个episode,我们就用这个episode的return 来立刻估计action value,然后就开始改进策略,这样就是我得到一个episode就改进策略,这样效率就得到了提升
在这里插入图片描述

问题:本来需要用很多episode来回估计action value 现在只用了一个episode显然估计是不准的,那这到底行不行呢?
实际上这样的思想在truncated policy iteration(分为两个步骤,第一个步骤是做policy evaluation,在这里面要求出对当前策略的 state value ,但求state value 要求解贝尔曼公式有需要无穷多步迭代才行,当时我们就只做了有限步的迭代,这时候有限步的迭代是得不到非常精确的state value 但是这个算法还是可以行之有效的)的时候已经介绍过。
这一些方法他有一个名字generalized policy iteration简称GPI,它主要是一种思想,就是在policy evaluation 和 policy improvement中间不断地进行切换,而且在policy evaluation不需要非常精确地估计action value和state value
有了上面的思考我们就可以得到一个新的算法,这个算法叫做MC Exploring Starts
在这里插入图片描述

我们为什么要exploring starts这个条件,他为什么是必要的?
为了理解这个问题我们只需要了解exploring starts这俩单词就行, exploring 指的是从每个(s,a)出发都要有episode,只有这样才能用后面生成的这些reward来估计return,然后进一步估计action value,如果恰恰有一个state action 没有被访问到,那就可能把那个action给漏掉了,但那个action可能又是最优的,所以为了得到最优的我们还是要确保每一个(s,a)都能够被访问到,这个就是exploring的含义。starts指的是我要访问每个(s,a)从它后边能够生成reward的这些数据有两种方法,第一种方法是从(s,a)开始一个episode就是start,第二种方法是从i你其他的(s,a)开始但是也能够经过当前的(s,a)后面的这些数据也可以用来估计当前(s,a)的return,这叫visit。这两种情况都是可以的,但是目前visit是没办法确保的,因为它依赖于策略、依赖于环境,不能确保从其他的(s,a)开始一定能够经过所有剩下的这些(s,a),就只能用比较笨的方法就是确保从每个(s,a)开始一定能够有一个episode,下面要介绍的这种算法就是要改变这种策略使得这个visit也可以实现,这样就可以避免这种必须要从每个(s,a)都开始episode这这个条件
exploring starts是非常重要和必要的但是在实际中是难以实现的,比如在一个网格世界中我们有一个实际的机器人在那,它要从不同的(s,a)出发的时候,我们必须给他搬运过去,设置好程序等等比较麻烦,所以理论和实际存在一个鸿沟,那么我们能不能把这个exploring starts这个条件给去掉或者转化掉用其他的形式实现,这就需要用到soft policies,这就引出了下面将要介绍的 MC without exploring starts

MC without exploring starts ------ MC ε-Greedy
怎么样把exploring starts这个条件去掉,去掉的方法就是需要引入soft policy,什么是soft policy呢,就是他对每一个action都有可能去做选择。之前就介绍policy分为两种,一种是greedy policy 就是deterministic;还有一种是stochastic ,soft policy 和 MC ε-Greedy都是stochastic policy
为什么要引入soft policy呢?
就是因为如果从一个state-action pair (s,a)出发若后面的episode特别长,因为它是探索性的实际上我们能够确保任何一个(s,a)都能够被这个episode访问到,这样的话我们就可以去掉exploring starts这个条件,我不需要从每个(s,a)都出发了,我们只需要从一个或者几个出发,就能够覆盖到其他的。这里面我们就需要用到soft policy 中的MC ε-Greedy

什么是 MC ε-Greedy
在一个状态s它有一个greedy action,它所对应的这个qΠ(s,a*)是最大的,这时候的ε-Greedy就会给这个greedy action一个选择的概率,给其他的不是greedy action的action另外的概率(如下图),ε是从0到1的正数 |A(s)| 就是s所对应的action的个数。在这当中我们发现greedy action有较大的概率去做选择,但是其他的action也有概率去做选择,只是概率比较小
在这里插入图片描述
其中的性质:选择greedy action的概率始终会比其他任何一个action的概率都要大
为什么要选择使用ε-Greedy?
就是因为它能够去平衡exploitation和exploration,exploitation指的是充分利用,字面意思是剥削,比如说在一个状态我们有很多个action,我们也知道有些action的action value 是比较大的,那么我们应该下一个时刻就去采用那个最大的action,来确保后面我们收到的reward是最大的,这个就称为充分利用;exploration就是我现在虽然知道那个action能给我带来很多reward,但是现在的信息不一定是完备的,可能我们去让探索一下其他的action可能会发现更好的action拥有更大的action value 这个就叫exploration 探索。
对于ε-Greedy这样的策略,如果ε = 0,这时候ε-Greedy就变成了greedy这时候的探索就会弱一些,但是充分利用就会强一些;如果ε = 1,拿着时候对每个action它的选择的概率就全都相同了,所以这时候就变成了一个均匀分布,这时候的探索性会更强,充分利用性会更弱一些。

如何将ε-Greedy和基于蒙特卡洛的强化学习问题结合在一起
之前学习的 MC basic 和 MC Exploring Starts 这两个算法当中的policy improvement 这个步骤如下图所示,就是在第一步我们先求出这个qΠk,随后在求解一个优化问题(max)得到一个新的策略,在求解这个优化问题的时候这个Π应该是在所有可能的策略中去做选择
在这里插入图片描述
求解出来的最优策略就是如下的greedy policy
在这里插入图片描述
对于现在来说其实也很简单,我们只需要将ε-Greedy嵌入到这个算法中,
那么怎么嵌入呢,就是在求解优化问题(max)的时候我们不是在所有的策略里面去找,而只是在大Πε(大Πε代表所有的ε-Greedy的策略)中去找,这时候得到的最优策略如下 ,还是会将较大的概率给到greedy action ,但是还是会给其他action一个相同的较小的概率
在这里插入图片描述
这样的话我们就得到了一个MC ε-Greedy算法,这个算法和 MC Exploring Starts基本上是一模一样的,除了在 MC Exploring-Starts里面我们是用的greedy的这个策略,就是因为使用这样一个策略我们就不需要exploring starts这样一个条件所以才使用这个greedy的策略
伪代码:
在这里插入图片描述

例1,介绍ε-Greedy的探索性
第一个情况 ε = 1,这时候ε的值就是最大的,这时候的policy就变成了一个均匀分布,在这个例子里面每个状态有5个action,那么就代表每个action都给了0.2的概率。图(a)、图(b)、图©分别是从(1,1)点出发,使用这个策略只有100步、1000步、10000步的探索情况;图(d)是探索100万的时候每一个state-action pair它被访问的次数是多少,横轴是代表state-action pair的索引。这个例子就说明了当ε比较大的时候,探索性是比较强的,那么我们就不在需要用exploring starts这样一个条件了
在这里插入图片描述
下图是当比较小的时候其探索性比较弱哦,即使我们将探索的步数增加到10000步,也还是有action没有被访问到
在这里插入图片描述

例2,ε-Greedy结合蒙特卡洛算法能带来什么样的最优策略
在例子中每一个iteration需要用当前的这个ε-Greedy的策略生成一个episode,这一个episode是非常长的,它有100万步,然后我勇这个episode去更新所有的state-action pair他们相对应的action value以及更新策略,想要通过这个例子展示这个算法确实避开了exploring starts这个条件。因为只要episode足够长即使它从一个state-action pair 出发他仍然能够访问所有的其他的state-action pair。
图(a)是最初的策略(不好的策略),在每个状态都有相同的肥肉概率去选择所有的action,使用这样的策略去生成一个100万步长的一个episode,然后去更新策略,就得到了图(b)的策略,但是图(b)策略还是不太好,他还是有些点保持不懂,然后我们再用图(b)策略去得到一个100万步长的episode,然后再去更新策略就得到了图©的策略,对于图©的策略相对来说是比较合理的,但是在有些状态上他会穿过障碍物,因此从这个角度上看他还不只是最优的。这里就是增强了其探索性,但是丢弃了一些最优性
在这里插入图片描述
因此在实际中可以让这个ε逐渐减小,开始的时候ε比较大就拥有比较强的探索能力然后让ε逐渐趋向于0,最后得到的策略就又有很好的最优性

例3,说明ε-Greedy的最优性
在例子中我们首先给出策略,通过求解贝尔曼公式更可以得到它的state value,第一个策略对应的ε = 0,它实际上是一个greedy的策略,并且它是在这个情况下最优的策略。第二个策略ε = 0.1,第二个策略和第一个策略是一致的,但是第二个策略的state value要比第一个策略的state value要小(就是因为在很多地方它采取了不该采取的措施,他在每个状态只是给了很大概率给到最好的action,其他不好的action它也有小概率会发生),随着ε变大,state value逐渐变小。因为state value的大小可以衡量一个策略的好坏,因此我们可以了解到,虽然所有的策略和最优的greedy的策略保持一致,但是他们的最优性在越来越差,我们也注意到在最好的greedy策略里面target area 的state value是最大的,但是ε最大的时候其值反而是最小的,就是因为在ε比较大的时候target area有比较大的概率进入到forbidden area
在这里插入图片描述

例4,MC ε-Greedy算法求解例子
下面已经给出最好的greedy策略以及相对应的optimal state value,我们可以看到随着ε不断变大,所产生的ε-Greedy策略越来越和greedy策略走偏,在实际过程中我们是希望将ε-Greedy直接转换为greedy,并且希望这个ε-Greedy策略和greedy策略是一致的,因此我们如果想要使用MC ε-Greedy,那么我们设置的ε不能太大,或者是最开始的时候ε设置比较大,探索性比较强最后将ε逐渐减小到0就可以得到一个最优的策略
在这里插入图片描述

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

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

相关文章

Android中OkHttp3中超时时间概述

目录 前言connectTimeoutreadTimeoutwriteTimeoutcallTimeoutpingInterval拓展 前言 可以看到,使用还是很简单的。主要相关的有这五个参数,其中我们常用到是就是connectTimeout、readTimeout和writeTimeout。 再看上图,可以看到默认下connec…

独立游戏《星尘异变》UE5 C++程序开发日志6——实现存档和基础设置系统

目录 一、存档类 1.创建一个SaveGame类 2.存储关卡内数据 3.加载关卡数据 4.关于定时器 5.存储全局数据 6.加载全局数据 二、存档栏 1.存档栏的数据结构 2.创建新存档 3.覆盖已有存档 4.删除存档 三、游戏的基础设置 1.存储游戏设置的数据结构 2.初始化设置 3.…

链表面试练习习题集(Java)

1. 思路&#xff1a; 因为杨辉三角是由二维数组构成&#xff0c;所以要先创建一个二维数组&#xff0c;如何用顺序表表示二维数组&#xff0c;可以通过List<List<Interger>>来表示一个二维数组&#xff0c;可以这样理解&#xff1a;先创建一个一维数组List&#x…

智慧消防建设方案(完整方案参考PPT)

智慧消防系统建设方案旨在通过物联网、大数据与云计算技术&#xff0c;集成火灾自动报警、智能监控、应急指挥等功能于一体。方案部署智能传感器监测火情&#xff0c;实时数据分析预警&#xff0c;实现火灾早发现、早处置。构建可视化指挥平台&#xff0c;优化应急预案&#xf…

Redis之List列表

目录 一.列表讲解 二.列表命令 三.内部编码 四.应用场景 Redis的学习专栏&#xff1a;http://t.csdnimg.cn/a8cvV 一.列表讲解 列表类型是用来存储多个有序的字符串&#xff0c;如下所示&#xff0c;a、b、c、d、e五个元素从左到右组成了一个有序的列表&#xff0c;列表中的…

android R ext4 image打包脚本介绍

一、Android R打包指令使用介绍 &#xff08;1&#xff09;mkuserimg_mke2fs #./mkuserimg_mke2fs --help usage: mkuserimg_mke2fs [-h] [--android_sparse] [--journal_size JOURNAL_SIZE][--timestamp TIMESTAMP] [--fs_config FS_CONFIG][--product_out PRODUCT_OUT][--b…

目标检测入门:4.目标检测中的一阶段模型和两阶段模型

在前面几章里&#xff0c;都只做了目标检测中的目标定位任务&#xff0c;并未做目标分类任务。目标检测作为计算机视觉领域的核心人物之一&#xff0c;旨在从图像中识别出所有感兴趣的目标&#xff0c;并确定它们的类别和位置。现在目标检测以一阶段模型和两阶段模型为代表的。…

常见漏洞之SSRF

一、SSRF简介 服务器端请求伪造&#xff08;SSRF&#xff09;是一种安全漏洞&#xff0c;允许攻击者通过构造恶意请求并利用存在缺陷的Web应用作为代理&#xff0c;向内外网发送请求&#xff0c;以实现攻击目的。SSRF攻击主要利用了服务端提供的某些功能&#xff0c;这些功能能…

基于jeecgboot-vue3的Flowable流程仿钉钉流程设计器-支持VForm3表单的选择与支持

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 1、初始化的时候加载表单 /** 查询表单列表 */ const getFormList () > {listForm().then(res > formOptions.value res.result.records) } 2、开始节点的修改&#xff0c;增加表…

【转盘案例-开始选号按钮-旋转 Objective-C语言】

一、接下来,我们来说这个“开始选号”按钮, 1.我们之前已经可以自旋转了,当我点击开始选号按钮之后,我让它快速的去旋转,5圈儿,然后停在最上方, 我先把ViewController的startRotate这句话啊,注释掉,先不让它自旋转呢, 把这句话注释掉, 接下来,我们command + R, …

Java---抽象类

乐观学习&#xff0c;乐观生活&#xff0c;才能不断前进啊&#xff01;&#xff01;&#xff01; 我的主页&#xff1a;optimistic_chen 我的专栏&#xff1a;c语言 &#xff0c;Java 欢迎大家访问~ 创作不易&#xff0c;大佬们点赞鼓励下吧~ 文章目录 抽象类什么的抽象类&…

stm32入门-----EXTI外部中断(上 ——理论篇)

目录 前言 一、中断系统 1.基本概念 2.执行过程 二、stm32中断 1.stm32中断类型 2.NVIC总管 3.NVIC的优先级分组 三、EXIT外部中断 1.基本概念 2.AFIO复用IO口 3.EXIT执行过程 前言 本期我们就开始进入到学习stm32的中断系统了&#xff0c;在此之前我们学习过51的知道中…

KAFKA搭建教程

KAFKA搭建教程 期待您的关注 KAFKA学习笔记 帮助更多人 目录 KAFKA搭建教程 1.下载Kafka并解压 2.添加环境变量 3.修改 server.properties 文件 4.将kafka复制到其它节点 5.修改node1、node2节点的broker.id 6.将master的环境变量同步到node1、 node2 7.启动zookeeper…

乐鑫ESP-IoT-Bridge方案简化设备智能联网通信,启明云端乐鑫代理商

随着物联网技术的快速发展&#xff0c;设备联网已成为实现智能化的关键一步。然而&#xff0c;不同设备之间的通信协议、接口等差异&#xff0c;使得设备联网变得复杂且困难。 乐鑫推出的ESP-IoT-Bridge联网方案&#xff0c;正是为了解决这一难题&#xff0c;为物联网场景下的…

【iOS】类对象的结构分析

目录 对象的分类object_getClass和class方法isa流程和继承链分析isa流程实例验证类的继承链实例验证 类的结构cache_t结构bits分析实例验证属性properties方法methods协议protocolsro类方法 类结构流程图解 对象的分类 OC中的对象主要可以分为3种&#xff1a;实例对象&#xf…

HTML2048小游戏(最新版)

比上一篇文章的2048更好一点。 控制方法&#xff1a;WASD键&#xff08;小写&#xff09;或页面上四个按钮 效果图如下&#xff1a; 源代码在图片后面 源代码 HTML <!DOCTYPE html> <html lang"en"> <head><meta charset&…

Qt日志库QsLog使用教程

前言 最近项目中需要用到日志库。上一次项目中用到了log4qt库&#xff0c;这个库有个麻烦的点是要配置config文件&#xff0c;所以这次切换到了QsLog。用了后这个库的感受是&#xff0c;比较轻量级&#xff0c;嘎嘎好用&#xff0c;推荐一波。 下载QsLog库 https://github.c…

Python、Rust与AI的未来展望

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 非常期待和您一起在这个小…

leetcode简单题27 N.119 杨辉三角II rust描述

// 直接生成杨辉三角当前行 pub fn get_row(row_index: i32) -> Vec<i32> {let mut row vec![1; (row_index 1) as usize];for i in 1..row_index as usize {for j in (1..i).rev() {row[j] row[j] row[j - 1];}}row } // 空间优化的方法 pub fn get_row2(row_ind…

【C#】计算两条直线的交点坐标

问题描述 计算两条直线的交点坐标&#xff0c;可以理解为给定坐标P1、P2、P3、P4&#xff0c;形成两条线&#xff0c;返回这两条直线的交点坐标&#xff1f; 注意区分&#xff1a;这两条线是否垂直、是否平行。 代码实现 斜率解释 斜率是数学中的一个概念&#xff0c;特别是…