马尔可夫决策过程之贝尔曼期望方程

  • 价值函数与贝尔曼期望方程
    • 回顾
    • 策略的重要性
      • 策略的具体表现形式
      • 如何判断一个策略π\piπ的优劣性
    • 价值函数(Value Function)
      • 状态价值函数(state-value function)
      • 状态-动作价值函数(action-value function)
    • 贝尔曼期望方程(Behrman Expectation Equation)
      • Vπ(s)V_\pi(s)Vπ​(s)和qπ(s,a)q_\pi(s,a)qπ​(s,a)之间的关系
      • 贝尔曼期望方程

上一节介绍了马尔可夫奖励过程中(Markov Reward Process,MRP) 出现的概念,本节引入贝尔曼期望方程,讲述马尔可夫决策过程(Markov Decision Process, MDP)的逻辑具体是如何实现的。

价值函数与贝尔曼期望方程

回顾

在介绍马尔可夫奖励过程(MRP)内容中,讲述了马尔可夫决策过程(MDP)的逻辑场景及相关概念,在这里做一个简单回顾:

  • 在某时刻ttt的状态StS_tSt​的情况下,在该时刻选择AtA_tAt​并执行,系统必然将当前状态St→S_t \toSt​→下一个时刻状态St+1S_{t+1}St+1​,状态转移的同时返回奖励结果Rt+1R_{t+1}Rt+1​。

在本节中,重新对各概念和条件进行设定;

  • 状态(State) 设置为离散型随机变量,由nnn种状态构成,S\mathcal SS表示状态集合,S(k)S^{(k)}S(k)表示状态集合S\mathcal SS中编号为kkk的状态,s,s′s,s's,s′均表示某种具体状态;
    S={S(1),S(2),...,S(n)},s,s′∈S\mathcal S=\{S^{(1)},S^{(2)},...,S^{(n)}\},s,s' \in \mathcal SS={S(1),S(2),...,S(n)},s,s′∈S

  • 动作(Action) 设置为离散型随机变量,由mmm种动作构成,A\mathcal AA表示动作集合,A(k)A^{(k)}A(k)表示动作集合A\mathcal AA中编号为kkk的动作,a,a′a,a'a,a′表示某种具体动作;
    A={A(1),A(2),...,A(m)},a,a′∈A\mathcal A=\{A^{(1)},A^{(2)},...,A^{(m)}\},a,a' \in \mathcal AA={A(1),A(2),...,A(m)},a,a′∈A

  • 奖励(Reward) 设置为离散型随机变量,由sss种奖励构成,R\mathcal RR表示奖励集合,R(k)R^{(k)}R(k)表示奖励集合R\mathcal RR中编号为kkk的奖励,rrr表示某种具体奖励;
    R={R(1),R(2),...,R(s)},r∈R\mathcal R=\{R^{(1)},R^{(2)},...,R^{(s)}\},r \in \mathcal RR={R(1),R(2),...,R(s)},r∈R

针对“状态转移过程中”转移到各状态的具体概率(当前状态转移到其他状态(含自身)的概率信息):

  • 若概率分布是离散的 →\to→ 称为状态转移矩阵(State Transition Matrix)。
  • 若概率分布是连续的 →\to→ 称为动态特性函数(Dynamic Characteristics Function)。
  • 综合上述设定,在本节使用p(s′,r∣s,a)p(s',r\mid s,a)p(s′,r∣s,a)表示状态转移矩阵,即:
    p(s′,r∣s,a)=P(St+1=s′,Rt+1=r∣St=s,At=a)p(s',r\mid s,a) = P(S_{t+1}=s',R_{t+1}=r\mid S_t=s,A_t=a)p(s′,r∣s,a)=P(St+1​=s′,Rt+1​=r∣St​=s,At​=a)

策略的重要性

策略的具体表现形式

马尔可夫决策过程(MDP)的核心在于执行过程中,找到最优的策略π(a∣s)\pi(a \mid s)π(a∣s);
策略是如何表示/描述的?
我们从动作(Action)的角度解释策略;
上一节中,我们介绍了两种策略:

  • 确定性策略(Deterministic Policy)
  • 随机性策略(Stochastic Policy)

通过对确定性策略/随机性策略的描述,我们发现任意动作aaa都不是独立存在并发生的,而是伴随着状态sss而产生的;
换句话说,是在状态sss的条件下→\to→选择某种动作aaa作为当前时刻的待执行动作

示例:
前提条件:某决策过程中,动作集合A\mathcal AA中包含3种动作;状态集合S\mathcal SS中包含2种状态;
A={A(1),A(2),A(3)},S={S(1),S(2)}\mathcal A = \{A^{(1)},A^{(2)},A^{(3)}\},\mathcal S = \{S^{(1)},S^{(2)}\}A={A(1),A(2),A(3)},S={S(1),S(2)}
假设一:确定性策略;
若当前状态是S(1)S^{(1)}S(1),只能唯一确定地选择A(3)A^{(3)}A(3);
基于上述假设,根据确定性策略,S(1)S^{(1)}S(1)状态下动作选择的概率分布如下表:

动作(Action) 概率(Probability)
A(1)A^{(1)}A(1) 0.0
A(2)A^{(2)}A(2) 0.0
A(3)A^{(3)}A(3) 1.0

表格中描述的概率分布就是一种确定性策略(Deterministic Policy)
假设二:随机性策略:
若当前状态是S(2)S^{(2)}S(2),动作集合A\mathcal AA中存在2种动作可以选择→A(1),A(3)\to A^{(1)},A^{(3)}→A(1),A(3),并且各动作被选择的概率分布如下:

动作(Action) 概率(Probability)
A(1)A^{(1)}A(1) 0.2
A(3)A^{(3)}A(3) 0.8

同假设一,上述表格描述的也是一种策略 →\to→ 随机性策略(Stochastic Policy)

如何判断一个策略π\piπ的优劣性

在判定一个策略π\piπ的优劣性时,假设状态转移矩阵p(s′,r∣s,a)=1→p(s',r\mid s,a)=1 \top(s′,r∣s,a)=1→此时是一种确定性环境(Deterministic Environment)→\to→只能唯一地选择下一个确定的状态;
基于上述条件下,可以直接使用回报(Return)GtG_tGt​直接作为评价标准 →\to→ 哪个状态的回报结果大,就选择该状态对应的策略;
但在实际情况中,由于状态转移概率的存在(下一时刻状态的选择存在概率分布),智能体从当前状态到最终状态可能存在多种状态序列 →\to→ 每个状态序列内有若干不同的回报GtG_tGt​,因而没有办法直接用GtG_tGt​比较的方式来确定策略。

换一种思路:
根据状态转移矩阵的定义 →\to→当前状态StS_tSt​到下一时刻状态St+1S_{t+1}St+1​的可能性的分布;我们将这种可能性作为权重,使用回报的期望(回报可能性的加权和)作为策略的评价指标:
期望值越大 →\to→ 选择高回报状态的概率就越大 →\to→ 引入价值函数(Value Function) 来改进策略。

价值函数(Value Function)

价值函数表示当前时刻ttt状态StS_tSt​确定的情况下,对策略π(a∣s)\pi(a \mid s)π(a∣s)的综合性考量。我们从2种角度对策略进行评判:

状态价值函数(state-value function)

状态价值函数表示当前时刻ttt状态St=sS_t=sSt​=s开始,智能体采取策略π(a∣s)\pi(a \mid s)π(a∣s)得到的期望回报
Vπ(s)=Eπ[Gt∣St=s]V_\pi(s)=E_\pi[G_t \mid S_t=s]Vπ​(s)=Eπ​[Gt​∣St​=s]
我们称Vπ(s)V_\pi(s)Vπ​(s)是策略π(a∣s)\pi(a \mid s)π(a∣s)的状态价值函数。可以发现,状态价值函数只包含1个变量sss,因此状态价值函数是由状态sss所具有的价值决定的

状态-动作价值函数(action-value function)

状态动作价值函数表示从当前时刻ttt状态St=sS_t=sSt​=s开始,智能体遵循策略π(a∣s)→\pi(a \mid s) \toπ(a∣s)→ 执行动作aaa之后的期望回报
qπ(s,a)=Eπ[Gt∣St=s,At=a]=∑s′,rp(s′,r∣s,a)[Gt∣St=s,At=a]\begin{aligned} q_\pi(s,a) & =E_\pi[G_t \mid S_t=s,A_t=a] \\ & = \sum_{s',r} p(s',r \mid s,a)[G_t \mid S_t=s,A_t=a] \\ \end{aligned}qπ​(s,a)​=Eπ​[Gt​∣St​=s,At​=a]=s′,r∑​p(s′,r∣s,a)[Gt​∣St​=s,At​=a]​
我们称qπ(s,a)q_\pi(s,a)qπ​(s,a)是策略π\piπ的状态动作价值函数。可以发现该函数中包含两个变量sss、aaa,因此状态动作价值函数是由当前状态sss和动作aaa的共同价值决定的

贝尔曼期望方程(Behrman Expectation Equation)

Vπ(s)V_\pi(s)Vπ​(s)和qπ(s,a)q_\pi(s,a)qπ​(s,a)之间的关系

我们通过观察发现,qπ(s,a)q_\pi(s,a)qπ​(s,a)就是在Vπ(s)V_\pi(s)Vπ​(s)的基础上选择了某个具体动作aaa产生的回报结果;换句话说,Vπ(s)V_\pi(s)Vπ​(s)是sss状态下的策略中所有可能发生的动作aaa对应的qπ(s,a)q_\pi(s,a)qπ​(s,a)的加权平均。
通过上面的推演,我们获得Vπ(s)V_\pi(s)Vπ​(s)和qπ(s,a)q_\pi(s,a)qπ​(s,a)之间的关系:
Vπ(s)=∑a∈Aπ(a∣s)[Gt∣St=s,At=a]=∑a∈Aπ(a∣s)qπ(s,a)\begin{aligned} V_\pi(s) & = \sum_{a \in \mathcal A} \pi(a \mid s) [G_t \mid S_t=s,A_t=a] \\ & = \sum_{a \in \mathcal A} \pi(a \mid s) q_\pi(s,a)\\ \end{aligned}Vπ​(s)​=a∈A∑​π(a∣s)[Gt​∣St​=s,At​=a]=a∈A∑​π(a∣s)qπ​(s,a)​
此时,Vπ(s)V_\pi(s)Vπ​(s)可以使用qπ(s,a)q_\pi(s,a)qπ​(s,a)表示了,反过来,qπ(s,a)q_\pi(s,a)qπ​(s,a)是否可以用Vπ(s)V_\pi(s)Vπ​(s)表示呢?
继续观察:
按照逻辑场景,在执行aaa之后,系统必然将当前状态St=sS_{t}=sSt​=s转移到下一时刻状态St+1S_{t+1}St+1​,假设下一时刻状态转移到s′s's′,我们观察St+1S_{t+1}St+1​的状态价值函数是如何表示的?
Vπ(St+1=s′)=Eπ[Gt+1∣St+1=s′]V_\pi(S_{t+1}=s')=E_\pi[G_{t+1} \mid S_{t+1} =s']Vπ​(St+1​=s′)=Eπ​[Gt+1​∣St+1​=s′]
从公式组成上和Vπ(s)V_\pi(s)Vπ​(s)没什么区别,只是下标增加了1。我们将Gt+1G_{t+1}Gt+1​进行展开:
Gt+1=Rt+2+γRt+3+γ2Rt+4+...G_{t+1} = R_{t+2} + \gamma R_{t+3} + \gamma^2 R_{t+4} + ...Gt+1​=Rt+2​+γRt+3​+γ2Rt+4​+...
再类比一下GtG_{t}Gt​的展开式:
Gt=Rt+1+γRt+2+γ2Rt+3+...G_{t} = R_{t+1} + \gamma R_{t+2} + \gamma^2 R_{t+3} + ...Gt​=Rt+1​+γRt+2​+γ2Rt+3​+...
我们发现,实际上GtG_tGt​和Gt+1G_{t+1}Gt+1​之间存在如下关系:
Gt=Rt+1+γGt+1G_t = R_{t+1} + \gamma G_{t+1}Gt​=Rt+1​+γGt+1​
得到如下关系,重新对qπ(s,a)q_\pi(s,a)qπ​(s,a)进行展开:
qπ(s,a)=Eπ[Gt∣St=s,At=a]=∑s′,rp(s′,r∣s,a)[Gt∣St=s,At=a]=∑s′,rp(s′,r∣s,a)[r+γGt+1∣St+1=s′,At+1=a′]=∑s′,rp(s′,r∣s,a)(r+γVπ(s′))\begin{aligned} q_\pi(s,a) & =E_\pi[G_t \mid S_t=s,A_t=a] \\ & = \sum_{s',r} p(s',r \mid s,a)[G_t \mid S_t=s,A_t=a] \\ & = \sum_{s',r} p(s',r \mid s,a)[r + \gamma G_{t+1} \mid S_{t+1}=s',A_{t+1}=a'] \\ & = \sum_{s',r} p(s',r \mid s,a)(r + \gamma V_\pi(s'))\\ \end{aligned}qπ​(s,a)​=Eπ​[Gt​∣St​=s,At​=a]=s′,r∑​p(s′,r∣s,a)[Gt​∣St​=s,At​=a]=s′,r∑​p(s′,r∣s,a)[r+γGt+1​∣St+1​=s′,At+1​=a′]=s′,r∑​p(s′,r∣s,a)(r+γVπ​(s′))​
其中Vπ(s′)V_\pi(s')Vπ​(s′)表示下一时刻状态St+1=s′S_{t+1}=s'St+1​=s′的状态价值函数。
细心的朋友发现,

  • 期望中的条件怎么突然从St=s,At=aS_t=s,A_t=aSt​=s,At​=a变成了St+1=s′,At+1=a′S_{t+1}=s',A_{t+1}=a'St+1​=s′,At+1​=a′;
  • Vπ(s′)V_\pi(s')Vπ​(s′)和Vπ(s)V_\pi(s)Vπ​(s)用的根本不是相同的策略,一个是π(a∣s)\pi(a\mid s)π(a∣s),另一个是π(a′∣s′)\pi(a' \mid s')π(a′∣s′)(a′a'a′表示下一时刻选择的某个动作,和当前时刻的aaa区分开)

首先解答第一个问题
当Gt→Gt+1G_t \to G_{t+1}Gt​→Gt+1​时,公式中函数的后验部分不包含任何关于ttt时刻的信息 →\to→ 而是t+1t+1t+1时刻的信息;自然需要转换成t+1t+1t+1时刻的条件。
新的疑问:St+1=s′,At+1=a′S_{t+1}=s',A_{t+1}=a'St+1​=s′,At+1​=a′是随便说换就换的吗?

该问题和第二个问题一同解答:
→\to→ 我们需要回溯之前GtG_tGt​和Gt+1G_{t+1}Gt+1​之间关系的公式
看起来GtG_tGt​和Gt+1G_{t+1}Gt+1​之间关系是很容易能够归纳出来,但内部的条件是很苛刻的。

我们知道,GtG_tGt​是ttt时刻St=sS_t=sSt​=s状态下动作的回报;而Gt+1G_{t+1}Gt+1​是t+1t+1t+1时刻St+1=s′S_{t+1}=s'St+1​=s′状态下动作回报;
→\to→ 如何使2种相邻时刻并且状态确定的回报产生必然的联系?

总结起来就一句话:我们如何能够在St=sS_t=sSt​=s的情况下使得St+1=s′S_{t+1}=s'St+1​=s′?

  • 如果当前时刻状态St=sS_t=sSt​=s顺利地转移到下一时刻状态St+1=s′S_{t+1}=s'St+1​=s′,那么状态,动作可以变化的同时,还可以执行下一时刻的策略π(a′∣s′)\pi(a' \mid s')π(a′∣s′);

至少需要4个条件:

  • St=sS_t=sSt​=s是确定的(这个是必然的,因为它是前提条件);
  • At=aA_t=aAt​=a
  • Rt+1=rR_{t+1}=rRt+1​=r
  • St+1=s′S_{t+1}=s'St+1​=s′

但凡这4个条件有1个不是确定的→\to→必然不能满足Gt=Rt+1+γGt+1G_t = R_{t+1} + \gamma G_{t+1}Gt​=Rt+1​+γGt+1​
换句话说,4个条件全部确定,才能保证t→t+1t \to t+1t→t+1时刻路径的唯一性。

回顾上式:
=∑s′,rp(s′,r∣s,a)[Gt∣St=s,At=a]=∑s′,rp(s′,r∣s,a)[r+γGt+1∣St+1=s′,At+1=a′]\begin{aligned} & = \sum_{s',r} p(s',r \mid s,a)[G_t \mid S_t=s,A_t=a] \\ & = \sum_{s',r} p(s',r \mid s,a)[r+ \gamma G_{t+1} \mid S_{t+1}=s',A_{t+1}=a'] \\ \end{aligned}​=s′,r∑​p(s′,r∣s,a)[Gt​∣St​=s,At​=a]=s′,r∑​p(s′,r∣s,a)[r+γGt+1​∣St+1​=s′,At+1​=a′]​
该式子中的St=s,At=a,Rt+1=r,St+1=s′S_t=s,A_t=a,R_{t+1}=r,S_{t+1}=s'St​=s,At​=a,Rt+1​=r,St+1​=s′都是确定的,该步骤才能成立。
最后一步,根据期望的性质(CCC表示常数):

  • E(C)=CE(C)=CE(C)=C
  • E(CX)=CE(X)E(CX)=CE(X)E(CX)=CE(X)

根据这2条性质,上式可以写成:
=∑s′,rp(s′,r∣s,a)[Gt∣St=s,At=a]=∑s′,rp(s′,r∣s,a)[r+γGt+1∣St+1=s′,At+1=a′]=∑s′,rp(s′,r∣s,a)(r+γ[Gt+1∣St+1=s′,At+1=a′])=∑s′,rp(s′,r∣s,a)(r+γVπ(s′))\begin{aligned} & = \sum_{s',r} p(s',r \mid s,a)[G_t \mid S_t=s,A_t=a] \\ & = \sum_{s',r} p(s',r \mid s,a)[r + \gamma G_{t+1} \mid S_{t+1}=s',A_{t+1}=a'] \\ & = \sum_{s',r} p(s',r \mid s,a)(r + \gamma[G_{t+1} \mid S_{t+1}=s',A_{t+1}=a']) \\ & = \sum_{s',r} p(s',r \mid s,a)(r + \gamma V_\pi(s'))\\ \end{aligned}​=s′,r∑​p(s′,r∣s,a)[Gt​∣St​=s,At​=a]=s′,r∑​p(s′,r∣s,a)[r+γGt+1​∣St+1​=s′,At+1​=a′]=s′,r∑​p(s′,r∣s,a)(r+γ[Gt+1​∣St+1​=s′,At+1​=a′])=s′,r∑​p(s′,r∣s,a)(r+γVπ​(s′))​

贝尔曼期望方程

根据上一节,我们获取了Vπ(s)V_\pi(s)Vπ​(s)和qπ(s,a)q_\pi(s,a)qπ​(s,a)之间的关联关系:
Vπ(s)=∑a∈Aπ(a∣s)qπ(s,a)V_\pi(s)= \sum_{a \in \mathcal A} \pi(a \mid s) q_\pi(s,a)Vπ​(s)=a∈A∑​π(a∣s)qπ​(s,a)
qπ(s,a)=∑s′,rp(s′,r∣s,a)(r+γVπ(s′))q_\pi(s,a) = \sum_{s',r} p(s',r \mid s,a)(r + \gamma V_\pi(s'))qπ​(s,a)=s′,r∑​p(s′,r∣s,a)(r+γVπ​(s′))
最终将上述2个关系式进行相互套娃,就得到了如下式子:
Vπ(s)=∑a∈Aπ(a∣s)∑s′,rp(s′,r∣s,a)(r+γVπ(s′))V_\pi(s) = \sum_{a \in \mathcal A}\pi(a \mid s)\sum_{s',r}p(s',r \mid s,a)(r + \gamma V_\pi(s'))Vπ​(s)=a∈A∑​π(a∣s)s′,r∑​p(s′,r∣s,a)(r+γVπ​(s′))
qπ(s,a)=∑s′,rp(s′,r∣s,a)(r+γ(∑a′∈Aπ(a′∣s′)qπ(s′,a′)))q_\pi(s,a)=\sum_{s',r} p(s',r \mid s,a)(r + \gamma (\sum_{a' \in \mathcal A}\pi(a' \mid s') q_\pi(s',a')))qπ​(s,a)=s′,r∑​p(s′,r∣s,a)(r+γ(a′∈A∑​π(a′∣s′)qπ​(s′,a′)))

这两个式子都是不动点方程,满足不动点定理,为后续的基于DP,MC的强化学习提供有效的理论支撑。

下一节继续介绍贝尔曼最优方程

相关参考:
【强化学习】马尔科夫决策过程【白板推导系列】
马尔科夫决策过程之Bellman Equation(贝尔曼方程)
深度强化学习原理、算法pytorch实战 - 刘全,黄志刚编著

贝尔曼期望方程(Bellman Expectation Equation)相关推荐

  1. 强化学习(一)- 强化学习介绍、Markov决策过程和贝尔曼期望方程

    强化学习(英语:Reinforcement learning,简称RL)是机器学习中的一个领域,强调如何基于环境而行动,以取得最大化的预期利益.其灵感来源于心理学中的行为主义理论,即有机体如何在环境给 ...

  2. 迭代法求解贝尔曼期望方程的数学证明

    强化学习的核心是用迭代法求解马尔可夫决策过程(MDP)的贝尔曼期望方程(Bellman Optimality Equation): V(s)=Rs+γ∑s′∈SPss′V(s′)V(s) = R_s ...

  3. 贝尔曼最优方程(Bellman Optimality Equation)

    贝尔曼最优方程 目录 回顾 + 补充 逻辑场景设置 贝尔曼最优方程 最优策略与最优价值函数 最优状态价值函数 最优状态-动作价值函数 小小的题外话 - 最大值/期望值 最大值和期望值之间的大小关系 最 ...

  4. 强化学习2——有模型强化学习MDP(搬砖马尔科夫,贝尔曼等式)

    文章目录 强化学习--马尔科夫系列 前言 马尔科夫决策过程(MDP) 1 马尔科夫过程(MP) 1.1 马尔科夫性质 1.2 马尔科夫过程 1.3 马尔科夫的一个例子 2 马尔科夫奖励过程(MRP) ...

  5. 强化学习理论基础(MDP、值函数与贝尔曼公式以及表格式Agent)

    强化学习理论基础(MDP.值函数与贝尔曼公式以及表格式Agent) 前言 一.MDP策略与环境模型 二.值函数与贝尔曼公式 1. 值函数 2. 贝尔曼公式 三.表格式Agent 1. 概念介绍 2. ...

  6. 了解贝尔曼·福特算法

    文章目录 为什么在现实生活中会有负权重的边? 为什么我们要留意负权重? 贝尔曼·福特算法如何工作 贝尔曼·福特伪码 Bellman Ford vs Dijkstra C示例 贝尔曼·福特算法的复杂度 ...

  7. 算法-贝尔曼-福特算法

    算法-贝尔曼-福特算法 注:该文是本博主记录学习之用,没有太多详细的讲解,敬请谅解! 一.简介 贝尔曼-福特算法(Bellman–Ford algorithm )用于计算出起点到各个节点的最短距离,支 ...

  8. 最优策略(Optimal Policy)及贝尔曼最优方程(Bellman Optimally Equation)

    文章目录 1.最优策略(Optimal Policy) 2.贝尔曼最优方程(Bellman Optimally Equation) 3.参考文献 1.最优策略(Optimal Policy) 强化学习 ...

  9. C++实现bellman ford贝尔曼-福特算法(最短路径)(附完整源码)

    C++实现bellman ford贝尔曼-福特算法 实现bellman ford贝尔曼-福特算法的完整源码(定义,实现,main函数测试) 实现bellman ford贝尔曼-福特算法的完整源码(定义 ...

最新文章

  1. CSDN-屏蔽广告详细方法 仅对谷歌浏览器有效!
  2. linux网络编程二:基础socket, bind, listen, accept, connect
  3. js事件流的三个阶段
  4. ELF格式文件特点的简单说明
  5. 中引入文件报错_关于前端开发中的模块化
  6. SAP Fiori launchpad的PageChipInstance实现
  7. 红帽7 su命令与sudo服务
  8. The following SDK components were not installed: extra-google-m2repository and platform-tools
  9. 国外著名java技术资料网站
  10. 【C语言】强迫症是不是病QAQ
  11. 公众号jdk 获取手机号_怎样快速获取使用国庆节公众号文章的素材和模板
  12. 百度地图 绘制运动轨迹_百度地图创新破局:声音个性表达、出行精准预估与全球无碍...
  13. iphone app开发实战很重要:《iPhone App开发实战手册》读后感
  14. java 静态成员 概念_Java成员变量、局部变量、静态变量、成员方法、全局方法等概念的区别...
  15. 148. Sort List (java 给单链表排序)
  16. jquery获取所有选中的checkbook
  17. Koo叔说Shader—最基本的Shader
  18. python dataframe重新索引_Concat DataFrame重新索引仅对唯一值索引对象有效
  19. CSDN 第六期编程竞赛做题记录
  20. 【工具】Excel表格数据不能编辑

热门文章

  1. 怎么在图片中添加表格?
  2. python实现千牛客服自动回复语_千牛客服自动回复话术
  3. 苹果电脑服务器连接显示器,苹果电脑如何外接显示器 苹果电脑外接显示器设置方法...
  4. 出入库与库存系统的模型问题
  5. 九宫格拼图android代码,Android 多图上传后将图片进行九宫格展示的实例代码
  6. 【发布】哔哩哔哩bilibili替换旧版播放(稍后再看)
  7. 如何将录音m4a转换为mp3格式?
  8. 常用设计模式系列(四)—建造者模式
  9. 抖音用什么编程语言_抖音app开发者的心路历程:论开发者的一些经验之谈
  10. 盘古开源:2022年全球汽车产能仍受制于芯片短缺,中国减产量占一成