update chapter2
This commit is contained in:
@@ -38,7 +38,7 @@
|
||||
|
||||
这里我们进一步定义一些概念。
|
||||
|
||||
* 第一个是这个 `Horizon` 的概念,它说明了同一个 episode 或者是整个一个轨迹的长度,它是由有限个步数决定的。
|
||||
* 第一个是这个 `horizon` 的概念,它说明了同一个 episode 或者是整个一个轨迹的长度,它是由有限个步数决定的。
|
||||
* 另外,这里我们再定义一个 `return`。Return 说的是我们把奖励进行折扣,然后获得的这个收益。Return 可以定义为奖励的逐步叠加,然后这里有一个叠加系数,就是越往后得到的奖励,折扣得越多。这说明我们其实更希望得到现有的奖励,未来的奖励就要把它打折扣。
|
||||
* 当我们有了这个 return 过后,就可以正式定义一个状态的价值了,就是 `state value function`。然后对于这个马尔可夫奖励过程,它里面定义成是关于这个 return 的期望, $G_t$ 是我们之前定义的 discounted return。然后我们这里取了一个期望,期望就是说从这个状态开始,你有可能获得多大的价值。所以这个期望也可以看成是一个对未来可能获得奖励的它的当前价值的一个表现。就是当你进入某一个状态过后,你现在就有多大的价值。
|
||||
|
||||
@@ -47,16 +47,16 @@
|
||||
* 第一点是有些马尔可夫过程是带环的,它并没有终结,然后我们想避免这个无穷的奖励。
|
||||
* 另外,我们是想把这个不确定性也表示出来,希望尽可能快地得到奖励,而不是在未来某一个点得到奖励。
|
||||
* 另外如果这个奖励是它是有实际价值的了,我们可能是更希望立刻就得到奖励,而不是我们后面再得到奖励。
|
||||
* 在人的行为里面来说的话,其实也是大家也是想得到立刻奖励了。
|
||||
* 另外,在有些状态的时候,我们这个系数也可以把它设为 0。比如说,当我们设为 0 过后,然后我们就只关注了它当前的奖励。我们也可以把它设为 1,设为 1 的话就是对未来并没有折扣,未来获得的奖励跟我们当前获得的奖励是一样的。这个系数其实是应该可以作为强化学习 agent 的一个 hyper parameter 来进行调整,然后就会得到不同行为的 agent。
|
||||
* 在人的行为里面来说的话,其实也是大家也是想得到立刻奖励。
|
||||
* 另外,在有些时候,这个系数也可以把它设为 0。比如说,当我们设为 0 过后,然后我们就只关注了它当前的奖励。我们也可以把它设为 1,设为 1 的话就是对未来并没有折扣,未来获得的奖励跟我们当前获得的奖励是一样的。这个系数其实是应该可以作为强化学习 agent 的一个 hyper parameter 来进行调整,然后就会得到不同行为的 agent。
|
||||
|
||||

|
||||
|
||||
这里我们再来看一看,在这个马尔可夫奖励过程里面,如何计算它的价值。这个马尔可夫奖励过程依旧是这个状态转移。它的奖励函数是定义成这样,它在进入第一个状态的时候,它会得到 5 的奖励,进入第七个状态的时候会得到 10 的奖励,其它状态都没有奖励。我们现在可以计算每一个轨迹得到的奖励,比如我们这里对于这个 $s_4,s_5,s_6,s_7$ 轨迹的奖励进行计算,我们这里折扣系数是 0.5。我们在 $s_4$ 的时候,并没有任何奖励,所以这里是零。下一个状态 $s_5$ 的时候,因为我们已经到了下一步了,所以我们要把 $s_5$ 进行一个折扣,$s_5$ 本身也是没有奖励的。然后是到$s_6$ ,然后也没有任何奖励。折扣系数应该是下两步,所以我们要再乘以 $\frac{1}{2}$ 。然后这里终于我们到达$s_7$ ,然后我们获得了一个奖励。但是因为 $s_7$ 这个状态是未来才获得的奖励,所以我们要进行三次折扣。所以对于这个轨迹,它的 return 就是一个 1.25,类似地,我们可以得到其它轨迹的 return 。
|
||||
|
||||
这里就引出了一个问题,当我们有了一些轨迹的实际 return,怎么计算它的价值函数。比如说我们现在想知道 $s_4$ 状态的价值,就是当你进入 $s_4$ 后,它的价值到底如何。
|
||||
这里就引出了一个问题,当我们有了一些轨迹的实际 return,怎么计算它的价值函数。比如说我们想知道 $s_4$ 状态的价值,就是当你进入 $s_4$ 后,它的价值到底如何。
|
||||
|
||||
一个可行的做法就是说我们可以产生很多轨迹,然后把这里的轨迹都叠加起来。比如我们现在可以从 $s_4$ 开始,然后采样生成很多轨迹,然后都把它的 return 计算出来,然后可以直接把它取一个平均,然后作为你进入 $s_4$ 它的价值,这其实是一种计算价值函数的一个办法,通过这个蒙特卡罗采样的办法计算 $s_4$ 的状态。我们接下来会进一步介绍这个蒙特卡洛算法。
|
||||
一个可行的做法就是说我们可以产生很多轨迹,然后把这里的轨迹都叠加起来。比如我们可以从 $s_4$ 开始,然后采样生成很多轨迹,然后都把它的 return 计算出来,然后可以直接把它取一个平均,然后作为你进入 $s_4$ 它的价值。这其实是一种计算价值函数的一个办法,通过这个蒙特卡罗采样的办法计算 $s_4$ 的状态。接下来会进一步介绍这个蒙特卡罗算法。
|
||||
|
||||

|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
|
||||

|
||||
|
||||
Bellman Equation 定义了状态之间迭代关系。假设我们现在有一个马尔可夫转移矩阵是右边这个样子。然后 Bellman Equation 描述的就是当前状态到未来状态的一个转移。你可以发现,假设我们当前是在 $s_1$, 那么它只可能去到三个未来的状态。一个是它有 0.1 的概率留在它当前这个位置,另外有 0.2 的概率,它去到才 $s_2$ 状态。另外 0.7 的概率去到 $s_4$ 的状态,所以我们要把这个转移乘以它的这个未来的状态,再加上它的 immediate reward 就会得到它当前状态的价值。所以 Bellman Equation 定义的就是当前状态跟未来状态的一个迭代的关系。
|
||||
Bellman Equation 定义了状态之间迭代关系。假设我们现在有一个马尔可夫转移矩阵是右边这个样子。然后 Bellman Equation 描述的就是当前状态到未来状态的一个转移。假设我们当前是在 $s_1$, 那么它只可能去到三个未来的状态:它有 0.1 的概率留在它当前这个位置,有 0.2 的概率去到 $s_2$ 状态,有 0.7 的概率去到 $s_4$ 的状态,所以我们要把这个转移乘以它未来的状态的价值,再加上它的 immediate reward 就会得到它当前状态的价值。所以 Bellman Equation 定义的就是当前状态跟未来状态的一个迭代的关系。
|
||||
|
||||

|
||||
|
||||
@@ -78,25 +78,25 @@ V = R+ \gamma PV
|
||||
$$
|
||||
|
||||
|
||||
让我们可以直接得到一个`解析解(analytic solution)`,就通过矩阵求逆的过程,就可以把这个 V 的这个价值直接求出来。但是一个问题是这个矩阵求逆的过程的复杂度是 $O(N^3)$。所以就当我们状态非常多的时候,比如说从我们现在十个状态到一千个状态,到一百万个状态。那么当我们有一百万个状态的时候,这个转移矩阵就会是个一百万乘以一百万的一个矩阵。这样一个大矩阵的话求逆是非常困难的,所以这种通过解析解去解,只能对于很小量的马尔可夫奖励过程。
|
||||
我们可以直接得到一个`解析解(analytic solution)`,就通过矩阵求逆的过程,就可以把这个 V 的这个价值直接求出来。但是一个问题是这个矩阵求逆的过程的复杂度是 $O(N^3)$。所以就当我们状态非常多的时候,比如说从我们现在十个状态到一千个状态,到一百万个状态。那么当我们有一百万个状态的时候,这个转移矩阵就会是个一百万乘以一百万的一个矩阵。这样一个大矩阵的话求逆是非常困难的,所以这种通过解析解去解,只能对于很小量的马尔可夫奖励过程。
|
||||
|
||||

|
||||
|
||||
另外求解这个价值函数,我们有这个迭代的方法来解这种状态非常多的这个马尔可夫奖励过程,这里迭代的方法就有几种。比如说我们可以通过动态规划(Dynamic Programming)的方法,然后也可以通过蒙特卡罗的办法,就通过采样的办法去计算它。另外我们也可以通过 Temporal-Difference Learning 的那个办法。这个 Temporal-Difference Learning 叫 TD Leanring,就是动态规划和蒙特卡罗的一个结合。
|
||||
接下来我们来求解这个价值函数。我们有这个迭代的方法来解这种状态非常多的这个马尔可夫奖励过程。这里迭代的方法就有几种,比如说我们可以通过动态规划的方法,也可以通过蒙特卡罗的办法,就通过采样的办法去计算它。另外我们也可以通过 Temporal-Difference Learning 的那个办法。这个 `Temporal-Difference Learning` 叫 `TD Leanring`,就是动态规划和蒙特卡罗的一个结合。
|
||||
|
||||

|
||||
|
||||
首先我们来看一个蒙特卡罗的一个办法来计算它的一个价值函数,这个蒙特卡罗就跟我们之前采用的这个方法是很类似,就说我们当得到一个马尔可夫奖励过程过后,我们可以从某一个状态开始,然后让它让把这个小船放进去,让它随波逐流,这样就会产生一个轨迹。产生了一个轨迹过后,人们就会得到一个奖励,那么就直接把它的 Discounted 的奖励 $g$ 直接算出来。算出来过后就可以把它积累起来,当积累到一定的轨迹数量过后,然后直接除以这个轨迹,然后就会得到它的这个价值。
|
||||
首先我们来看蒙特卡罗的办法来计算它的一个价值函数。蒙特卡罗就跟我们之前采用的这个方法是很类似,就说我们当得到一个马尔可夫奖励过程过后,我们可以从某一个状态开始,然后让它让把这个小船放进去,让它随波逐流,这样就会产生一个轨迹。产生了一个轨迹过后,就会得到一个奖励,那么就直接把它的 Discounted 的奖励 $g$ 直接算出来。算出来过后就可以把它积累起来,当积累到一定的轨迹数量过后,然后直接除以这个轨迹,然后就会得到它的这个价值。
|
||||
|
||||
比如说我们要算 $s_4$ 状态的一个价值,就可以从 $s_4$ 状态开始,随机产生很多轨迹,就产生很多小船,然后扔到这个转移矩阵里面去,然后它就会随波逐流,然后产生轨迹。每个轨迹,我们可以算到它的这个 return 。那么每个轨迹都会得到一个 return,让我们得到大量的 return 。比如说一百个、一千个的 return ,然后直接取一个平均,那么就可以等价于它现在 $s_4$ 这个价值。因为 $s_4$ 的价值 $V(s_4)$ 就是定义了你未来可能得到多少的这个奖励。这就是蒙特卡罗采样的方法。
|
||||
比如说我们要算 $s_4$ 状态的一个价值,就可以从 $s_4$ 状态开始,随机产生很多轨迹,就产生很多小船,然后扔到这个转移矩阵里面去,然后它就会随波逐流,产生轨迹。每个轨迹,我们可以算到它的这个 return 。那么每个轨迹都会得到一个 return,让我们得到大量的 return 。比如说一百个、一千个的 return ,然后直接取一个平均,那么就可以等价于它现在 $s_4$ 这个价值。因为 $s_4$ 的价值 $V(s_4)$ 定义了你未来可能得到多少的奖励。这就是蒙特卡罗采样的方法。
|
||||
|
||||
我们也可以用这个动态规划的一个办法,就通过这种一直去迭代它的 Bellman Equation ,然后让它最后收敛,我们就可以得到它的一个状态。所以在这里算法二就是一个迭代的算法,通过这个 bootstraping 的办法,然后去不停地迭代这个 Bellman Equation。当这个最后更新的状态跟你上一个状态变化并不大的时候,这个更新就可以停止。那么我们就可以输出最新的这个 $V'(s)$ 作为它当前的状态。所以这里就是利用到了 Bellman Equation,就把 Bellman Equation 变成一个 Bellman Update,这样就可以得到它的一个价值。
|
||||
我们也可以用这个动态规划的办法,就通过这种一直去迭代它的 Bellman Equation,让它最后收敛,我们就可以得到它的一个状态。所以在这里算法二就是一个迭代的算法,通过这个 bootstraping 的办法,然后去不停地迭代这个 Bellman Equation。当这个最后更新的状态跟你上一个状态变化并不大的时候,这个更新就可以停止。那么我们就可以输出最新的这个 $V'(s)$ 作为它当前的状态。所以这里就是利用到了 Bellman Equation,就把 Bellman Equation 变成一个 Bellman Update,这样就可以得到它的一个价值。
|
||||
|
||||
## Markov Decision Process(MDP)
|
||||
|
||||

|
||||
|
||||
相对于马尔可夫奖励过程,马尔可夫决策过程多了一个 decision,其它的定义跟马尔可夫奖励过程都是类似的。这里我们多了一个决策,多了一个 action ,那么这个状态转移也多了一个 condition,就是它多了一个你采取某一种行为,然后你未来的状态会不同,它不仅是依赖于你当前的状态,也依赖于在当前状态你这个 agent 它采取的这个行为会决定它未来的这个状态走向。对于这个价值函数,它也是多了一个条件,多了一个你当前的这个行为,就说你可以得到的奖励是基于你当前的状态以及你采取的行为会决定你在当前可能得到的奖励多少。
|
||||
相对于马尔可夫奖励过程,马尔可夫决策过程多了一个 `decision`,其它的定义跟马尔可夫奖励过程都是类似的。这里我们多了一个决策,多了一个 action ,那么这个状态转移也多了一个 condition,就是你采取某一种行为,然后你未来的状态会不同。它不仅是依赖于你当前的状态,也依赖于在当前状态你这个 agent 它采取的这个行为会决定它未来的这个状态走向。对于这个价值函数,它也是多了一个条件,多了一个你当前的这个行为,就是说你当前的状态以及你采取的行为会决定你在当前可能得到的奖励多少。
|
||||
|
||||

|
||||
|
||||
@@ -104,7 +104,7 @@ Policy 定义了在某一个状态应该采取什么样的行为,当我们知
|
||||
|
||||

|
||||
|
||||
这里说明了马尔可夫决策过程跟马尔可夫奖励过程的之间的一个转换,就是当我们已知一个马尔可夫决策过程以及一个 policy $\pi$ 的时候,那我们可以把马尔可夫决策过程转换成马尔可夫奖励过程。我们这里在马尔可夫决策过程里面,它的转移函数 $P(s'|s,a)$ 是基于它当前状态以及它当前的 action,因为我们现在已经已知它的这个 policy function,就是说在每一个状态,我们知道它可能采取的行为的概率,那么就可以直接把这个 action 进行加和,直接把这个 a 去掉,那我们就可以得到一个对于马尔可夫奖励过程的一个转移。这里就并没有 action 在这个里面,对于这个奖励函数,我们也可以把这个 action 拿掉,这样就会得到一个类似于马尔可夫奖励过程的一个奖励函数。
|
||||
这里说明了马尔可夫决策过程跟马尔可夫奖励过程的之间的一个转换,就是当我们已知一个马尔可夫决策过程以及一个 policy $\pi$ 的时候,那我们可以把马尔可夫决策过程转换成马尔可夫奖励过程。我们这里在马尔可夫决策过程里面,它的转移函数 $P(s'|s,a)$ 是基于它当前状态以及它当前的 action,因为我们现在已知它的这个 policy function,就是说在每一个状态,我们知道它可能采取的行为的概率,那么就可以直接把这个 action 进行加和,直接把这个 a 去掉,那我们就可以得到一个对于马尔可夫奖励过程的一个转移。这里就并没有 action 在这个里面,对于这个奖励函数,我们也可以把这个 action 拿掉,这样就会得到一个类似于马尔可夫奖励过程的一个奖励函数。
|
||||
|
||||

|
||||
|
||||
@@ -130,7 +130,7 @@ Bellman Expectation Equation 定义了你当前状态跟未来状态之间的一
|
||||
|
||||

|
||||
|
||||
这里有一个概念叫 `Backup`。Backup 类似于 bootstraping(拔靴自助) 之间这个迭代关系,就对于某一个状态,它的当前这个价值是跟它未来价值线性相关的,你可以看到我们这里有两层加和。第一层加和就是这个叶子节点,然后往上走一层的话,我们就可以把未来的这个价值,$s'$ 的这个价值 backup 到黑色的节点。然后再有一层加和,第二层加和,这个加和是把 action 进行加和。得到黑色节点的价值过后,再往上 backup 一层,然后就会推到根节点的价值,根节点就是我们当前状态。所以这个 Backup Diagram 定义了你未来下一时刻的状态跟你上一时刻的状态之间的一个关联。
|
||||
这里有一个概念叫 `Backup`。Backup 类似于 bootstraping(拔靴自助) 之间这个迭代关系,就对于某一个状态,它的当前这个价值是跟它未来价值线性相关的,你可以看到我们这里有两层加和。第一层加和就是这个叶子节点,然后往上走一层的话,我们就可以把未来的这个价值,$s'$ 的这个价值 backup 到黑色的节点。然后再有一层加和,第二层加和,这个加和是把 action 进行加和。得到黑色节点的价值过后,再往上 backup 一层,然后就会推到根节点的价值,根节点就是我们当前状态。所以这个 `Backup Diagram` 定义了你未来下一时刻的状态跟你上一时刻的状态之间的一个关联。
|
||||
|
||||

|
||||
|
||||
@@ -140,11 +140,11 @@ Bellman Expectation Equation 定义了你当前状态跟未来状态之间的一
|
||||
|
||||

|
||||
|
||||
这里一个概念是 `policy evaluation`。Policy evaluation 的概念是说当我们知道一个马尔可夫决策过程以及我们要采取的策略 $\pi$ ,那我们计算价值函数的过程。这个就是叫 policy evaluation,就像我们在评估这个策略,我们会得到多大的这个奖励。这个 policy evaluation 在有些地方也是被 叫做 prediction,也就是在预测你当前采取的这个策略最终会产生多少的价值。
|
||||
这里一个概念是 `policy evaluation`。Policy evaluation 的概念是说当我们知道一个马尔可夫决策过程以及我们要采取的策略 $\pi$ ,那我们计算价值函数的过程。这个就是叫 policy evaluation,就像我们在评估这个策略,我们会得到多大的这个奖励。这个 policy evaluation 在有些地方也被叫做 `prediction`,也就是预测你当前采取的这个策略最终会产生多少的价值。
|
||||
|
||||

|
||||
|
||||
这个马尔可夫决策过程,你其实可以把它想象成一个摆渡的一个人,就在这个船上面,其实有一个人它可以控制这个船的移动,这样就避免了这个船随波逐流。因为你在每一个时刻,这个人会决定采取什么样的一个行为,这样会把这个船进行导向。这样就相对于马尔可夫奖励过程跟马尔可夫链的过程的话,这个纸的小船只在一个随波逐流,然后产生轨迹。这里MDP 的这个不同就是我们有一个主体,这个 agent 去控制这个船,然后这样我们就可以尽可能多地获得奖励。
|
||||
马尔可夫决策过程,你其实可以把它想象成一个摆渡的人,就在这个船上面,其实有一个人它可以控制这个船的移动,这样就避免了这个船随波逐流。因为你在每一个时刻,这个人会决定采取什么样的一个行为,这样会把这个船进行导向。这样就相对于马尔可夫奖励过程跟马尔可夫链的过程的话,这个纸的小船只在一个随波逐流,然后产生轨迹。这里 MDP 的不同就是我们有一个主体,这个 agent 去控制这个船,然后这样我们就可以尽可能多地获得奖励。
|
||||
|
||||

|
||||
|
||||
@@ -152,7 +152,7 @@ Bellman Expectation Equation 定义了你当前状态跟未来状态之间的一
|
||||
|
||||

|
||||
|
||||
我们再来看另外一个情况,就是如果我们这里有折扣了,这个折扣因子是 0.5,我们就可以通过这个等式进行迭代:
|
||||
我们再来看另外一个情况,就是如果我们这里有折扣了,这个折扣因子是 0.5,我们可以通过这个等式进行迭代:
|
||||
$$
|
||||
v_{t}^{\pi}(s)=\sum_{a} P(\pi(s)=a)\left(r(s, a)+\gamma \sum_{s^{\prime} \in S} P\left(s^{\prime} \mid s, a\right) v_{t-1}^{\pi}\left(s^{\prime}\right)\right)
|
||||
$$
|
||||
@@ -232,7 +232,7 @@ Policy evaluation 是说我们给定一个 MDP 以及给定一个 policy,然
|
||||
|
||||

|
||||
|
||||
这里和我们再来看一下第二个步骤 policy improvement,我们是如何改进它的这个策略。当我们等到这个 v 值过后,我们就可以通过这个 reward function 以及状态转移把它的这个 Q-function 算出来。对于每一个状态,第二个步骤会得到它的一个新一轮的这个 policy ,就在每一个状态,我们去取使它得到最大值的 action。你可以把这个 Q 函数看成一个 Q-table。横轴是它的所有状态,纵轴是它的可能的 action。Q 函数得到过后,Q-table 就得到了。
|
||||
这里再来看一下第二个步骤 `policy improvement`,我们是如何改进它的这个策略。当我们等到这个 v 值过后,我们就可以通过这个 reward function 以及状态转移把它的这个 Q-function 算出来。对于每一个状态,第二个步骤会得到它的一个新一轮的这个 policy ,就在每一个状态,我们去取使它得到最大值的 action。你可以把这个 Q 函数看成一个 Q-table。横轴是它的所有状态,纵轴是它的可能的 action。Q 函数得到过后,`Q-table` 就得到了。
|
||||
|
||||
那么对于某一个状态,每一列里面我们会取最大的那个值,最大值对应的那个 action 就是它现在应该采取了更佳的action。所以你看这里下面这个 arg max 操作就说在每个状态里面,我们去采取一个 action,这个 action 就是能使这一列的 Q 最大化的那个动作。
|
||||
|
||||
@@ -307,15 +307,15 @@ Value iteration 这个算法目的是为了得到一个最佳的一个策略。
|
||||
|
||||

|
||||
|
||||
我们再来看用 value iteration 来解 MDP,点第 3 行 value iteration, 当它的这个值确定下来过后,然后它会产生它的最佳状态,这个最佳状态跟这个 policy iteration 得出来的最佳策略是一致的,就可以得到一个最佳的一个策略,然后在每个状态,我们跟着这个最佳策略走,然后就会到达最多可以得到奖励的一个状态。
|
||||
我们再来看用 value iteration 来解 MDP,点第 3 个 value iteration。 当它的这个值确定下来过后,然后它会产生它的最佳状态,这个最佳状态跟这个 policy iteration 得出来的最佳策略是一致的,就可以得到一个最佳的一个策略,然后在每个状态,我们跟着这个最佳策略走,然后就会到达最多可以得到奖励的一个状态。
|
||||
|
||||

|
||||
|
||||
这个 Demo 里面是一个代码,就是为了解一个叫 FrozenLake 的一个例子,这个例子是 OpenAI Gym里的一个环境,跟 gridworld 很像,不过它每一个状态转移是一个 probability。
|
||||
这个 Demo 里面是一个代码,就是为了解一个叫 `FrozenLake` 的一个例子,这个例子是 OpenAI Gym里的一个环境,跟 gridworld 很像,不过它每一个状态转移是一个 probability。
|
||||
|
||||

|
||||
|
||||
然后我们再来看一下 policy iteration 和 value iteration 的一个对比,这两个算法都是为了解 MDP 的控制问题,policy iteration 是由两部分组成的:policy evaluation 和 policy improvement。它很清楚的把这个过程分成了两步,就首先对于当前的这个已经搜索到的策略函数,然后对它进行一个估值,得到估值过后,把 Q 函数算出来,我们进一步进行改进。
|
||||
我们再来看一下 policy iteration 和 value iteration 的一个对比,这两个算法都是为了解 MDP 的控制问题,policy iteration 是由两部分组成的:policy evaluation 和 policy improvement。它很清楚的把这个过程分成了两步,就首先对于当前的这个已经搜索到的策略函数,然后对它进行一个估值,得到估值过后,把 Q 函数算出来,我们进一步进行改进。
|
||||
|
||||
但对于 value iteration 的话,它是直接把 Bellman Optimality Equation 拿进来,然后直接去寻找最佳的 value function,这里没有 policy function 在这里面,当我们把这个 optimal value function 算出来过后,那我们可以在最后再执行一步这个提取过程,最佳策略提取过程。这样就可以把它的最佳策略抽取过来。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user