强化学习算法

在这里插入图片描述
在这里插入图片描述

  • 从上图看出,强化学习可以分成价值/策略、随机策略/确定策略、在线策略/离线策略、蒙特卡洛/时间差分这四个维度。这里分析了基础算法中除了在线策略/离线策略以外的其他维度。

(一)基础知识

一、基础概念

在这里插入图片描述

  • 重点概念:状态S、动作A、策略 π \pi π、奖励r、折扣率 γ \gamma γ、回报G、转移概率P、状态价值V(s)、状态-动作价值Q(s,a)
  • (状态、动作、策略、奖励、折扣率)是马尔科夫过程的五元组
  • 所谓的模型实际是给出了转移概率和奖励值
  • 奖励是在离开当前“情况”时获得的,这里说的“情况”包括“状态”和“动作”。因为顺序是sarsa,所以r是在动作后给出的,是一个步骤中最后给出的。
  • 回报是未来长期奖励的累计。这里有一个点需要注意,这个回报可以从任意节点开始,这里的节点可以指状态也可以指动作,分别对应状态价值和状态动作价值
    回报的定义
    在这里插入图片描述
  • 价值函数都是回报的期望
    状态价值的定义
    在这里插入图片描述
    状态-动作价值的定义
    在这里插入图片描述

二、贝尔曼期望公式(V和Q的关系)

https://zhuanlan.zhihu.com/p/110338833
在这里插入图片描述

1、用Q表示V

在这里插入图片描述

  • Q的期望是V

2、用V表示Q

在这里插入图片描述

3、用下一个V表示当前的V(V迭代)

在这里插入图片描述

  • 2带入1得到3

4、用下一个Q表示当前的Q(Q迭代)

在这里插入图片描述

  • 1带入2得到4

三、MC与TD

  • 这两种算法不是应用在某一种强化学习算法上,而是广泛的存在强化学习中,所有的算法几乎都可以利用这两种思路分成两类。在基础算法的学习中,是仅次于基于值和策略以外最应当关注的分类。

1、MC:使用采样的方法,利用平均值进行估计

在这里插入图片描述

2、TD:多采一步数据,利用下一次的计算值进行估计

在这里插入图片描述

(二)基于值的强化学习

一、V更新

1、更新公式

V n e w ( s ) = V o l d ( s ) + α [ V r e a l ( s ) − V o l d ( s ) ] V_{new}(s)=V_{old}(s)+\alpha[V_{real}(s)-V_{old}(s)] Vnew(s)=Vold(s)+α[Vreal(s)Vold(s)]

  • 上式是V更新过程的理想公式,真实价值函数值与过去价值函数值的差就是应当更新价值函数的方向
    V n e w ( s ) = V o l d ( s ) + α [ V e s t i m a t e ( s ) − V o l d ( s ) ] V_{new}(s)=V_{old}(s)+\alpha[V_{estimate}(s)-V_{old}(s)] Vnew(s)=Vold(s)+α[Vestimate(s)Vold(s)]

  • 但是我们实际上并没有真实价值函数(要不然干嘛还要更新这个价值函数呢),所以只能用不同的方法去估计这个真实价值函数值,也就是上式。采用不同的估计方法就产生了不同的基于值的强化学习算法

  • 后续Q的更新公式是一样的,思路都是一样的

2、MC

V e s t i m a t e ( s ) = G = G 1 + G 2 + … … + G n N V_{estimate}(s)=G=\frac{G_1+G_2+……+G_n}{N} Vestimate(s)=G=NG1+G2+……+Gn
V n e w ( s ) = V o l d ( s ) + α [ G − V o l d ( s ) ] V_{new}(s)=V_{old}(s)+\alpha[G-V_{old}(s)] Vnew(s)=Vold(s)+α[GVold(s)]

  • 用采样的G估计V的真实值

3、TD(TD(0))

V e s t i m a t e ( s ) = γ V o l d ( s ′ ) + r ′ V_{estimate}(s)={\gamma}V_{old}(s')+r' Vestimate(s)=γVold(s)+r
V n e w ( s ) = V o l d ( s ) + α [ γ V o l d ( s ′ ) + r ′ − V o l d ( s ) ] V_{new}(s)=V_{old}(s)+\alpha[{\gamma}V_{old}(s')+r'-V_{old}(s)] Vnew(s)=Vold(s)+α[γVold(s)+rVold(s)]

  • 用下一个状态的V估计现在的V真值
  • 注意这里有一个特别的点,由S状态出发,S’有不同的可能状态,这里是使用了在这一次实验中策略函数实际给出的状态S‘。也就是对应着Q更新中的SARSA

二、Q更新

1、更新公式

Q n e w ( s ) = Q o l d ( s ) + α [ Q r e a l ( s ) − Q o l d ( s ) ] Q_{new}(s)=Q_{old}(s)+\alpha[Q_{real}(s)-Q_{old}(s)] Qnew(s)=Qold(s)+α[Qreal(s)Qold(s)]
Q n e w ( s ) = Q o l d ( s ) + α [ Q e s t i m a t e ( s ) − Q o l d ( s ) ] Q_{new}(s)=Q_{old}(s)+\alpha[Q_{estimate}(s)-Q_{old}(s)] Qnew(s)=Qold(s)+α[Qestimate(s)Qold(s)]

2、MC

Q e s t i m a t e ( s ) = G = G 1 + G 2 + … … + G n N Q_{estimate}(s)=G=\frac{G_1+G_2+……+G_n}{N} Qestimate(s)=G=NG1+G2+……+Gn
Q n e w ( s ) = Q o l d ( s ) + α [ G − Q o l d ( s ) ] Q_{new}(s)=Q_{old}(s)+\alpha[G-Q_{old}(s)] Qnew(s)=Qold(s)+α[GQold(s)]

  • 用采样的G估计Q的真实值
  • 用于估计V和Q的G,是针对不同情况(s或者(s,a))的G

3、TD

https://zhuanlan.zhihu.com/p/110338833
在这里插入图片描述

Q e s t i m a t e ( s ) = γ V o l d ( s ′ ) + r ′ Q_{estimate}(s)={\gamma}V_{old}(s')+r' Qestimate(s)=γVold(s)+r
Q e s t i m a t e ( s ) = γ ∑ a ∈ A π ( a ∣ s ′ ) Q π ( s ′ , a ) + r ′ Q_{estimate}(s)={\gamma}{\sum_{a\in A} \pi(a|s')Q_{\pi}(s',a)}+r' Qestimate(s)=γaAπ(as)Qπ(s,a)+r

  • 上面是完整的估计方法,但是计算量太大,反正都是估计了,旧的Q本来就不准。思路是用一个特别的Q代替V,使得Q一定程度上可以代替V,SARSA是使用旧策略输出动作的Q,Q-learning是选择Q最大的动作计算Q。
(1)SARSA

Q e s t i m a t e ( s ) ∝ [ γ Q π ( s ′ , π ( a ∣ s ′ ) ) + r ′ ] Q_{estimate}(s) \propto [{\gamma}{ Q_{\pi}(s',\pi(a|s'))}+r'] Qestimate(s)[γQπ(s,π(as))+r]

在这里插入图片描述
在这里插入图片描述

(2)Q-learning

Q e s t i m a t e ( s ) ∝ [ γ m a x a ∈ A ( Q π ( s ′ , π ( a ∣ s ′ ) ) ) + r ′ ] Q_{estimate}(s) \propto [{\gamma}{ max_{a\in A}(Q_{\pi}(s',\pi(a|s')))}+r'] Qestimate(s)[γmaxaA(Qπ(s,π(as)))+r]
在这里插入图片描述
在这里插入图片描述

(3)DQN=Qlearning+NN

Q e s t i m a t e ( s ) = f n n ( s ) Q_{estimate}(s)=f_{nn}(s) Qestimate(s)=fnn(s)
损失函数 L o s s = Q e s t i m a t e ( s ) − Q o l d ( s ) = f n n ( s ) − Q o l d ( s ) 损失函数Loss=Q_{estimate}(s) - Q_{old}(s) = f_{nn}(s) - Q_{old}(s) 损失函数Loss=Qestimate(s)Qold(s)=fnn(s)Qold(s)
在这里插入图片描述

  • 这里涉及到了损失函数的部分,虽然时间差分是用下一步估计这一步但是都是用的同一个Q函数,凭什么说下一步估计的更准呢?个人认为这里的思路是带奖励R的估计值会比原来的计算值更准,因为R是客观的,不断的迭代才导致最终收敛。

(三)基于策略的强化学习

  • 策略梯度的应用空间更广,不仅适用于确定、离散的问题,也适用于随机、连续的问题。
  • 策略梯度分为随机策略梯度和确定策略梯度,这一部分都是随机策略梯度的

一、更新公式(策略梯度)

https://www.zhihu.com/question/556911056/answer/3378158668
https://zhuanlan.zhihu.com/p/137416242
https://zhuanlan.zhihu.com/p/70260658
https://blog.csdn.net/weixin_40493501/article/details/110671785?spm=1001.2014.3001.5502

1、梯度上升最大化目标函数J

θ t + 1 = θ t + α ∇ J ( θ ) \theta_{t+1} = \theta_{t} + \alpha\nabla{J(\theta)} θt+1=θt+αJ(θ)

  • 梯度比较常用的做法是用梯度下降最小化损失函数。其实如果理解梯度的概念的话,就能明白不一定是损失函数,也不一定是最小化。

2、策略梯度定理推导

∇ J ( θ ) = E π [ ∇ l o g ( π θ ( s , a ) ) ∗ Q π ( s , a ) ] \nabla{J(\theta)}=E_{\pi}[\nabla{log(\pi_{\theta}(s,a))}*Q_{\pi}(s,a)] J(θ)=Eπ[log(πθ(s,a))Qπ(s,a)]

  • 问题的关键就来到了如何计算目标函数关于控制策略参数的梯度
  • 这里的目标函数定义为状态价值函数V
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

3、从物理角度的理解

∇ J ( θ ) = E π [ ∇ l o g ( π θ ( s , a ) ) ∗ Q π ( s , a ) ] \nabla{J(\theta)}=E_{\pi}[\nabla{log(\pi_{\theta}(s,a))}*Q_{\pi}(s,a)] J(θ)=Eπ[log(πθ(s,a))Qπ(s,a)]

  • 上面这个公式是策略梯度定理,可以理解为“带权重的梯度”
  • ∇ l o g ( π θ ( s , a ) ) \nabla{log(\pi_{\theta}(s,a))} log(πθ(s,a))基本可以等价于策略关于 θ \theta θ的梯度方向,是“策略的梯度”。就像y=ax+b中的x和1,代表着改进的方向,也就是说从这个方向改变参数可以尽量快的增大或者减小后面部分的效果。要区分这里的“带权重梯度”和后续DDPG中“目标函数梯度”。
  • Q π ( s , a ) Q_{\pi}(s,a) Qπ(s,a)代表着环境反馈的好与坏,如果长期奖励大于0代表好行为则沿着梯度加大,如果长期奖励小于0代表坏行为则沿着梯度减小
  • 对于这个公式不同处理和估计方式,衍生出了不同基于策略的强化学习方法,就像下面这张图中给出的:
    在这里插入图片描述

二、基于蒙特卡洛的策略梯度(REINFORCE)

∇ J ( θ ) = E π [ ∇ l o g ( π θ ( s , a ) ) ∗ Q π ( s , a ) ] \nabla{J(\theta)}=E_{\pi}[\nabla{log(\pi_{\theta}(s,a))}*Q_{\pi}(s,a)] J(θ)=Eπ[log(πθ(s,a))Qπ(s,a)]
∇ J ( θ ) = ∇ l o g ( π θ ( s , a ) ) ∗ G t \nabla{J(\theta)}=\nabla{log(\pi_{\theta}(s,a))}*G_t J(θ)=log(πθ(s,a))Gt
θ t + 1 = θ t + α ( ∇ l o g ( π θ ( s , a ) ) ∗ G t ) \theta_{t+1} = \theta_{t} + \alpha(\nabla{log(\pi_{\theta}(s,a))}*G_t) θt+1=θt+α(log(πθ(s,a))Gt)

  • 蒙特卡洛方法就是把期望用多次采样的平均数进行估计
  • 注意这里实际上做了两次蒙特卡洛,只是第二次除了去除E以外没啥作用,推导过程如下
    在这里插入图片描述

三、基于时间差分的策略梯度

1、(演员评论家AC)

https://zhuanlan.zhihu.com/p/110998399

基于蒙特卡洛的策略梯度: θ t + 1 = θ t + α ( ∇ l o g ( π θ ( s , a ) ) ∗ G t ) \theta_{t+1} = \theta_{t} + \alpha(\nabla{log(\pi_{\theta}(s,a))}*G_t) θt+1=θt+α(log(πθ(s,a))Gt)
带基线的蒙特卡洛策略梯度: θ t + 1 = θ t + α ( ∇ l o g ( π θ ( s , a ) ) ∗ ( G t − b ) ) \theta_{t+1} = \theta_{t} + \alpha(\nabla{log(\pi_{\theta}(s,a))}*(G_t-b)) θt+1=θt+α(log(πθ(s,a))(Gtb))
演员评论家: θ t + 1 = θ t + α ( ∇ l o g ( π θ ( s , a ) ) ∗ ( Q π ( s , a ) − V π ( s , a ) ) ) \theta_{t+1} = \theta_{t} + \alpha(\nabla{log(\pi_{\theta}(s,a))}*(Q_{\pi}(s,a)-V_{\pi}(s,a))) θt+1=θt+α(log(πθ(s,a))(Qπ(s,a)Vπ(s,a)))

  • 演员加评论者中的G不用蒙特卡洛算法就还是Q,而用Q的平均值作为基线b。Q的平均值就等于V,并定义Q-V为TD-error,可以参考下图
    在这里插入图片描述
    演员评论家的架构如下所示
    在这里插入图片描述
  • 评论者输入状态St输出状态价值V(St),TD-error可以作为评论者的loss。这里采用了TD的思想,也就是用下一步的V估计这一步的V,认为有客观的奖励参与的估计值比单独计算的准,所以跟一般的固定标签的神经网络不同。
  • 演员则把TD-error作为“权重梯度”中的“权重”

(四)结合策略和值的强化学习算法

资料:
DDPG原始论文:https://zhuanlan.zhihu.com/p/53613085
https://zhuanlan.zhihu.com/p/111257402
https://www.cnblogs.com/pinard/p/10345762.html
https://cheersyouran.github.io/2018/06/17/pg/
https://www.zhihu.com/question/65005739

一、DDPG

  • DDPG也是结合策略和值的强化学习算法,同样是以策略梯度作为最核心的框架,但是是从确定性策略梯度出发的。在值的部分也做了改造,使用了DQN作为Q的估计,所以也有人认为DDPG是DQN的延申,即Qlearning->DQN->DDPG
  • DDPG的特点是指定了固定的输出,也就是Actor不再输出不同动作的概率,而是输出固定的值,更像一个控制器了
  • DDPG已经是可以实际应用的算法了,所以在原始算法中使用了很多工程操作,比如缓存池、软更新等,这里不进行展开,

1、确定策略梯度

∇ J ( θ ) = E [ ∇ θ Q ( s , a ) ] = E [ α ( ∇ a Q ( s , a ) ∗ ∇ θ π ( s ) ) ] \nabla{J(\theta)} = E[ \nabla_{\theta}{Q(s,a)}]=E[ \alpha(\nabla_aQ(s,a)*\nabla_\theta{\pi(s)})] J(θ)=E[θQ(s,a)]=E[α(aQ(s,a)θπ(s))]

  • 这个公式看起来一步就推出来了,本身就是链式法则,没什么特别的
  • 但其实隐含了一个问题这个Q的梯度是在目前策略导致状态分布下计算的,更改策略后状态分布就变化了,那这个梯度方向还能保证一定是优化的方向吗?后面的证明其实就证明了仍然是优化方向

推导如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2、算法框架

算法框架如下:
在这里插入图片描述

3、算法细节

(1)Critict网络
  • Critict网络还是在拟合价值函数,不过这里拟合的就是动作状态价值函数了,也就是DQN拟合的那个函数,可以形象的理解为下面这个离散图上蒙上一块布,进而变为连续的。
    在这里插入图片描述
(2)Actor网络

在这里插入图片描述
在这里插入图片描述

  • actor实际上就是在找Q的最大值
    在这里插入图片描述
(3)算法流程

在这里插入图片描述

4、物理理解

  • 相较于随机策略梯度,确定策略梯度的物理理解比较直接,就是想找Q的梯度,直接最大化Q。

==============================================================================================
DDPG和随机策略梯度的比较:
确定策略梯度:理解为找最大的Q
∇ J ( θ ) = E [ ∇ θ Q ( s , a ) ] = E [ α ( ∇ a Q ( s , a ) ∗ ∇ θ π ( s ) ) ] \nabla{J(\theta)} = E[ \nabla_{\theta}{Q(s,a)}]=E[ \alpha(\nabla_aQ(s,a)*\nabla_\theta{\pi(s)})] J(θ)=E[θQ(s,a)]=E[α(aQ(s,a)θπ(s))]
确定策略梯度:理解为“带权重的梯度”,G为代表好坏的权重, ∇ π \nabla{\pi} π为代表方向的梯度(注意这个梯度跟目标函数梯度不同)
∇ J ( θ ) = E π [ ∇ l o g ( π θ ( s , a ) ) ∗ Q π ( s , a ) ] \nabla{J(\theta)}=E_{\pi}[\nabla{log(\pi_{\theta}(s,a))}*Q_{\pi}(s,a)] J(θ)=Eπ[log(πθ(s,a))Qπ(s,a)]

  • 二者都是基于目标函数的梯度上升延申出的算法,我不认为从DQN去理解DDPG更好。原始论文也说明,确定策略梯度是随机策略梯度的极限情况。
  • 随机策略梯度更全面,既有基于MC的REINFORCE,也有基于TD的AC。而确定策略梯度则只有基于TD的DDPG,应该是因为Q的梯度没法采样获得吧

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

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

相关文章

Android:使用Kotlin搭建MVC架构模式

一、简介Android MVC架构模式 M 层 model ,负责处理数据,例如网络请求、数据变化 V 层 对应的是布局 C 层 Controller, 对应的是Activity,处理业务逻辑,包含V层的事情,还会做其他的事情,导致 ac…

切换分支报错:Untracked Files Prevent Checkout

切换分支报错:Untracked Files Prevent Checkout 分支切换 Untracked Files Prevent Checkout 新起的项目在切换master分支到工作分支时,出现下图的问题: Untracked Files Prevent Checkout Move or commit them before checkout 网上的解决…

回溯算法05(leetcode491/46/47)

参考资料: https://programmercarl.com/0491.%E9%80%92%E5%A2%9E%E5%AD%90%E5%BA%8F%E5%88%97.html 491. 非递减子序列 题目描述: 给你一个整数数组 nums ,找出并返回所有该数组中不同的递增子序列,递增子序列中 至少有两个元素…

大数据智慧消防解决方案(24页PPT)

方案介绍: 大数据智慧消防解决方案是提升消防安全管理水平、保障人民群众生命财产安全的重要手段。通过集成物联网、云计算、大数据、人工智能等先进技术,构建集监测、预警、指挥、救援于一体的智慧消防系统,将为消防安全事业注入新的活力。…

工业级3D开发引擎HOOPS:创新与效率的融合!

在当今这个技术日新月异的时代,3D技术已成为推动各行各业发展的重要力量。从工程设计到游戏开发,从虚拟现实到增强现实,3D技术的应用无处不在,它极大地丰富了我们的生活和工作。而在这样的背景下,HOOPS作为一个强大的3…

爬虫技术升级:如何结合DrissionPage和Auth代理插件实现数据采集

背景/引言 在大数据时代,网络爬虫技术已经成为数据收集的重要手段之一。爬虫技术可以自动化地从互联网上收集数据,节省大量人力和时间成本。然而,当使用需要身份验证的代理服务器时,许多现有的爬虫框架并不直接支持代理认证。这就…

测试自动生成目录

目录 1,标题一 2,标题二 3,标题三 4,怎么做到的 1,标题一 内容11111111111111111111 2,标题二 内容22222222222222222 3,标题三 内容3333333333333333333 4,怎么做到的

递增链表去重

题目描述: 题目思路: 1.链表内的val是递增的,所以相同的值只会连续重复地出现。 2.设置三个指针: ①指向头结点指针,用于返回链表 ②指向返回链表链尾的指针,用于在新链表添加结点 ③遍历旧链表结点的…

C++ | Leetcode C++题解之第107题二叉树的层序遍历II

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<vector<int>> levelOrderBottom(TreeNode* root) {auto levelOrder vector<vector<int>>();if (!root) {return levelOrder;}queue<TreeNode*> q;q.push(root);while (!q.e…

Redis实践—全国地址信息缓存

一、背景 在涉及全国地址的应用中&#xff0c;地址信息通常被频繁地查询和使用&#xff0c;例如电商平台、物流系统等。为了提高系统性能和减少对数据库的访问压力&#xff0c;可以使用缓存来存储常用的地址信息&#xff0c;其中 Redis 是一个非常流行的选择。 本次在一个企业入…

Redis的下载、安装、启动和初尝试【超级简单】

redis最好是在Linux系统中使用&#xff0c;这是最接近生产实际的环境。 不过&#xff0c;我们初学者&#xff0c;目的是学习Redis的使用、原理&#xff0c;如果在Linux下直接学习Redis&#xff0c;很可能会因为命令不熟悉而劝退&#xff0c;这是不好的。 因此&#xff0c;我主张…

linux命令中arj使用

arj 用于创建和管理.arj压缩包 补充说明 arj命令 是 .arj 格式的压缩文件的管理器&#xff0c;用于创建和管理 .arj 压缩包。 语法 arj(参数)参数 操作指令&#xff1a;对 .arj 压缩包执行的操作指令&#xff1b;压缩包名称&#xff1a;指定要操作的arj压缩包名称。 更多…

.NET Core Web Api Swagger运行异常

遇到的问题 因为新增了一个控制器方法&#xff0c;从而导致在运行Swagger的时候直接报错&#xff0c;异常如下&#xff1a; SwaggerGeneratorException: Conflicting method/path combination "POST api/UserOperationExample" for actions - WebApi.Controllers.Us…

HTML+CSS+JS 扩散登录表单动画

效果演示 Code <!DOCTYPE html> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,us…

光明于心,自理成翼:盲人生活自理能力训练探索

在探索未知的旅途中&#xff0c;盲人朋友同样怀揣着对自由与独立的向往。随着科技的不断进步&#xff0c;一款名为“蝙蝠避障”的辅助软件以其独特的实时避障与拍照识别功能&#xff0c;成为了盲人朋友提升生活自理能力的有力工具。本文将深入探讨盲人生活自理能力训练&#xf…

代码随想录--哈希表--有效的字母异位词

题目 给定两个字符串 s 和 t &#xff0c;编写一个函数来判断 t 是否是 s 的字母异位词。 示例 1: 输入: s “anagram”, t “nagaram” 输出: true 示例 2: 输入: s “rat”, t “car” 输出: false 说明: 你可以假设字符串只包含小写字母。 思路 先看暴力的解法&am…

低功耗 DC/DC 转换器的复杂设计原理分析介绍

DC/DC 转换解决方案都是低噪声线性设计&#xff0c;易于使用&#xff0c;但有两个主要缺点。首先&#xff0c;输出电压必须始终低于输入电压&#xff1b;然而&#xff0c;线性稳压器的效率非常低&#xff0c;并且将大部分供电功率以热量的形式耗散。其次&#xff0c;根据输入和…

ZISUOJ 数据结构--图及其应用

说明 主要考察建图&#xff0c;图的遍历以及求最小生成树。都还是比较简单的&#xff0c;后面就直接上代码了。 最小生成树采用prim还是kruskal算法要看题目怎么给出数据&#xff0c;如果以邻接矩阵的形式给出&#xff0c;采用prim算法比较合适&#xff0c;如果以边和边的权重的…

盲人社会适应性训练:打开生活的新篇章

在现代社会的快节奏中&#xff0c;每一位成员都在寻求更好的方式来适应环境&#xff0c;对于盲人群体而言&#xff0c;这种适应性尤为关键。盲人社会适应性训练作为一个旨在提升盲人生活质量和独立性的系统性过程&#xff0c;正逐步受到广泛关注。在这一过程中&#xff0c;一款…

轻量SEO分析报告程序网站已开心去授权

轻量SEO分析报告程序网站已开心去授权&#xff0c;可以让你生成有洞察力的、 简洁的、易于理解的SEO报告&#xff0c;帮助你的网页排名和表现更好 网站源码免费下载地址抄笔记 (chaobiji.cn)https://chaobiji.cn/