DQN (Deep Q-Network) 学习

DQN学习

本文为知乎:DQN 从入门到放弃 系列文章整理,仅用于学习故整理在此,侵删。
原文出处:https://zhuanlan.zhihu.com/p/21340755


目录

  1. 强化学习 Reinforcement Learning
  2. MDP
  3. 价值函数与Bellman方程
  4. 动态规划与Q-Learning
  5. 参考链接

1. 强化学习 Reinforcement Learning

DQN(Deep Q-Network)是深度强化学习(Deep Reinforcement Learning )。
  在人工智能领域,一般用智能体Agent来表示一个具备行为能力的物体.比如机器人,无人车,人等等。那么增强学习考虑的问题就是智能体Agent和环境Environment之间交互的任务。

  再举玩游戏的例子,比如我们玩极品飞车游戏,我们只看到屏幕,这就是环境,然后我们输出动作(键盘操作)来控制车的运动。

那么,不管是什么样的任务,都包含了一系列的 动作Action,观察Observation 还有 反馈值Reward。

所谓的Reward就是Agent执行了动作与环境进行交互后,环境会发生变化,变化的好与坏就用Reward来表示。如上面的例子,如果玩赛车游戏赛车越来越偏离跑道,那么Reward就是负的。

接下来这里用了Observation观察一词而不是环境那是因为Agent不一定能得到环境的所有信息,比如机械臂上的摄像头就只能得到某个特定角度的画面。因此,只能用Observation来表示Agent获取的感知信息。
在这里插入图片描述

在每个时间点time-step Agent都会从可以选择的动作集合A中选择一个动作 a t {a_t} at执行,
这个动作集合可以是连续的:比如机器人的控制,也可以是离散的: 比如游戏中的几个按键
动作集合的数量将直接影响整个任务的求解难度.因此DeepMind才从玩最简单的游戏做起, DQN算法(不考虑其变种)仅适用于离散输出问题。

那么知道了整个过程,任务的目标就出来了,那就是要能获取尽可能多的Reward.

没有目标,控制也就无从谈起,因此,获取Reward就是一个量化的标准,Reward越多,就表示执行得越好。

每个时间片,Agent都是根据当前的观察来确定下一步的动作。
观察Observation的集合就作为Agent的所处的状态State,因此,状态State动作Action存在映射关系.
也就是一个state可以对应一个action,或者对应不同动作的概率( 常常用概率来表示,概率最高的就是最值得执行的动作)。

状态与动作的关系其实就是输入与输出的关系,而状态State到动作Action的过程就称之为一个策略Policy,一般用 π \pi π 表示,也就是需要找到以下关系(s:输入;a:输出):
a = π ( s ) a = \pi \left( s \right) a=π(s) 或者 π ( a ∣ s ) \pi \left( {a|s} \right) π(as)
其中a是actions是state。第一种是一一对应的表示,第二种是概率的表示。

增强学习的任务就是找到一个最优的策略Policy从而使Reward最多。

我们一开始并不知道最优的策略是什么,因此往往从随机的策略开始,使用随机的策略进行试验,就可以得到一系列的状态,动作和反馈
{ s 1 , a 1 , r 1 , s 2 , a 2 , r 2 , ⋯   , s t , a t , r t } \left\{ {{s_1},{a_1},{r_1},{s_2},{a_2},{r_2}, \cdots ,{s_t},{a_t},{r_t}} \right\} {s1,a1,r1,s2,a2,r2,,st,at,rt}
这就是一系列的样本Sample
增强学习的算法就是需要根据这些样本来改进Policy,从而使得得到的样本中的Reward更好。
由于这种让Reward越来越好的特性,所以这种算法就叫做增强学习Reinforcement Learning。

MDP马尔科夫决策过程的知识,是构建增强学习算法的基础。

2.MDP

增强学习的世界观以及随之而来的MDP马尔科夫决策过程。

可能很少有人用世界观来看增强学习甚至人工智能的一些问题,但实际上任何问题的建立都是在一个基本的假设下进行构建的,也就是这个领域的世界观。

增强学习的研究依然建立在经典物理学的范畴上,也就是没有量子计算也没有相对论。这个世界的时间是可以分割成一个一个时间片的,并且有完全的先后顺序,因此可以形成:
{ s 0 , a 0 , r 0 , s 1 , a 1 , r 1 , ⋯   , s t , a t , r t } \left\{ {{s_0},{a_0},{r_0},{s_1},{a_1},{r_1}, \cdots ,{s_t},{a_t},{r_t}} \right\} {s0,a0,r0,s1,a1,r1,,st,at,rt}
这样的状态,动作和反馈系列。这些数据样本是进行增强学习的基础。
另一个很重要的假设就是: 上帝不掷筛子!

在增强学习的世界,我们相信如果输入是确定的,那么输出也一定是确定的。

试想一下,有一个机械臂在练习掷筛子,以掷出6点作为目标。但是如果无论机械臂如何调整其关节的角度及扭矩,掷出的点数永远是随机的,那么无论如何也不可能通过算法使机械臂达成目标。因此,增强学习算法要有用,就是相信在增强学习中每一次参数的调整都会对世界造成确定性的影响。

以上两点便是增强学习算法建立的基础。当然了,基本上人工智能的研究都是在这样的基础上进行研究,探讨其世界观的意义并不是很大,但是意识到这一点可以有助于理解当前人工智能研究的局限性。

那么有了时间和确定性的假设,MDP(Markov Decision Process)便是为了描述这个世界而提出的概念。

MDP(Markov Decision Process)马尔科夫决策过程

MDP基于这样一种假设: 未来只取决于当前
什么意思呢?

就是如果我们站在上帝视角下看,我们知道这个世界的每个物体的状态,那么未来的变化只跟当前的状态相关,和过去没有关系。

用数学的话来描述就是:

一个状态 S t {S_t} St是Markov 当且仅当
P ( s t + 1 ∣ s t ) = P ( s t + 1 ∣ s t , s t − 1 , ⋯   , s 1 , s 0 ) P\left( {{s_{t + 1}}|{s_t}} \right) = P\left( {{s_{t + 1}}|{s_t},{s_{t - 1}}, \cdots ,{s_1},{s_0}} \right) P(st+1st)=P(st+1st,st1,,s1,s0)

P为概率。简单的说就是下一个状态仅取决于当前的状态和当前的动作。注意这里的状态是完全可观察的全部的环境状态(也就是上帝视角)。

当然,对于一些游戏比如围棋在游戏的世界中就是完全可观察的。
上面的公式可以用概率论的方法来证明。

这里,我们说一个更通俗易懂的方式:举个栗子,在理想环境中有一个球,以某一个速度v斜向上45度抛出,受重力G影响,求这个球的运行轨迹?初中的物理题。显然,我们知道了球的初速度,受力情况,我们可以完全计算出球在每一个时间点上位置和速度。而且我们只要知道某一个时间点上球的速度和受力情况,下一个时间点的速度和位置就可以求出。这就是一个MDP 过程。

往大的说,如果宇宙起始于大爆炸的奇点。那么奇点状态确定,如果上帝不掷筛子的话,那么宇宙就是一个MDP的过程,它的每一步都是确定的,推到人身上就是每个人的命运也都是确定的。换句话讲,我们现在的所思所想不过是由我们身上的每个细胞导致的精神状态,意识以及周围的环境所完全确定的。所以MDP的宇宙大概没什么意思,还好还有量子力学和相对论,我也相信这个世界是不确定的。

回到增强学习的范畴,增强学习的问题 都可以模型化为MDP的问题

一个基本的MDP可以用(S,A,P)来表示,S表示状态,A表示动作,P表示状态转移概率: 也就是根据当前的状态 s t {s_t} st a t {a_t} at转移到 s t + 1 {s_{t + 1}} st+1的概率。如果我们知道了转移概率P,也就是称为我们获得了模型Model,有了模型,未来就可以求解,那么获取最优的动作也就有可能,这种通过模型来获取最优动作的方法也就称为Model-based 的方法。但是现实情况下,很多问题是很难得到准确的模型的,因此就有 Model-free 的方法来寻找最优的动作。

关于具体的方法这里不具体讨论。在以后的文章中我们会通过分析具体的算法对此有个明确的认识。

回报Result:
  既然一个状态对应一个动作,或者动作的概率,而有了动作,下一个状态也就确定了。这就意味着每个状态可以用一个确定的值来进行描述。可以由此判断一个状态是好的状态还是不好的状态。比如,向左边走就是悬崖,悬崖肯定不是好的状态,再走一步可能就挂了,而向右走就是黄金,那么右边的状态就是好的状态。(这个意思是,由动作得到的下一个状态是用来描述当前状态的值?)

那么状态的好坏其实等价于对未来回报的期望。因此,引入回报Return来表示某个时刻t的状态将具备的回报:
G t = R t + 1 + λ R t + 2 + … = ∑ k = 0 ∞ λ k R t + k + 1 {G_t} = {R_{t + 1}} + \lambda {R_{t + 2}} + \ldots = \sum\limits_{k = 0}^\infty {{\lambda ^k}{R_{t + k + {\rm{1}}}}} Gt=Rt+1+λRt+2+=k=0λkRt+k+1

上面R是Reward反馈,λ是discount factor(折扣因子),一般小于1,就是说一般当下的反馈是比较重要的,时间越久,影响越小。

那么实际上除非整个过程结束,否则显然我们无法获取所有的reward来计算出每个状态的Return,因此,再引入一个概念: 价值函数Value Function,用value function : v ( s ) v\left( s \right) v(s)来表示一个状态未来的潜在价值。 还是上面的例子,这里就变成是向左看感觉左边是悬崖那么左边的状态的估值就低。

从定义上看,value function就是回报的 期望:
v ( s ) = E [ G t ∣ S t = s ] v\left( s \right) = {\rm E}\left[ {{G_t}|{S_t} = s} \right] v(s)=E[GtSt=s]


期望 E ( x ) {\rm E}\left( x \right) E(x) 是均值的另一种说法,那么,期望公式就是每个数值与其概率的乘积之和: E ( x ) = ∑ x p {\rm E}\left( x \right) = \sum {xp} E(x)=xp


引出价值函数,对于获取最优的策略Policy这个目标,我们就会有两种方法:

  • 直接优化策略 a = π ( s ) a = \pi \left( s \right) a=π(s) 或者 π ( a ∣ s ) \pi \left( {a|s} \right) π(as)使得回报更高
  • 通过估计value function来间接获得优化的策略。道理很简单,既然我知道每一种状态的优劣,那么我就知道我应该怎么选择了,而这种选择就是我们想要的策略。

当然了,还有第三种做法就是融合上面的两种做法,这也就是以后会讲到的actor-critic算法。但是现在为了理解DQN,我们将只关注第二种做法,就是估计value function的做法,因为DQN就是基于value function的算法。


有关评论:关于reward应该归入哪个时刻的问题,我最初也疑惑了很久。比较过多个来源的资料后。

我认为这样理解MDP过程比较易于理解:

初始状态下:

1、agent感知环境,得到state

2、agent根据policy决策,做出一个动作action

3、envirnment根据state和action,给出reward以及一个新的state

然后返回步骤1进行循环

state0, action0 --> reward1, state1, action1 --> reward2, state2, action2 --> …reward_n-1, staten-1, action_n-1 --> reward_n

这里特别的是,t0时刻是没有reward0的,此时agent还没有任何动作,自然也无所谓reward。另外最终时刻,可以只有reward,而不再需要有state更新与多余的动作。

以围棋为例,开局为t0时刻,你还没有落子,自然无所谓reward。你分析了盘面,得到state0,然后在角上落了一个黑子,这是action0。然后白棋在中央处下了一子,envirnment更新了状态,agent得到state1(此时期盼上有2个子,分别落在角上以及中央),同时envirnment给出了一个reward1,数值为0. (按照alphago的规则,终局胜利才给1reward)。

虽然有的书本将reward1写作reward0,将第一个reward归入t0时刻发生的事情。但是我认为reward的给出,是与state1更加相关,所以归入t1时刻更加合理。另外在终局阶段,你在tn时刻下了一个黑子,完成动作actionn,envirnment判定你赢得此局。此时envirnment给出你的reward_n,之后也不需要再更新states了。


3.价值函数与Bellman方程

MDP只需要用一句话就可以说明白,就是“未来只取决于当前”,专业点说就是下一步的状态只取决于当前的状态,与过去的状态没有关系。

这里大家要注意这里所说的状态是完全可观察的,也就是上帝眼中的世界。再举例说明一下完全可观察的意思就是比如我们的眼睛看到的世界,那就是不完全可观察的,我们并不清楚的知道眼前的每一个物体,比如人,车,动物的真实物理位置,因此也就是无法准确知道它们下一个时刻的状态(比如车的位置)只能通过估算的方法来估计。而在上帝眼中,那么每一个物体的位置和速度信息都是确定的,也因此下一个时刻的状态也就是完全确定的。

在引出了MDP之后,由于每一个时刻的状态是确定的,因此我们可以用Value Function价值函数来描述这个状态的价值,从而确定我们的决策方式。

有知友表示不是很理解Value Function,那么下面我们再具体探讨一下。

Value Function 价值函数

我们用一个例子来说明Value Function的含义与重要性。

这是一个投资决策问题:假如我们有一笔X美刀的资金,我们眼前有三种选择来使用这笔资金:
1.使用资金进行股票投资
2.使用资金进行买房投资
3.使用资金购买书籍,科研设备等提升资金

那么,我们就面临如何做选择的问题。这里假设我们只能选择其中的一个做选择。

我们先来解释一下直接基于 Policy的方法 是怎样的。
直接基于Policy的意思就是我们有一套Policy策略,我们基于这个策略进行操作,比如可以有如下所示的策略:

if 资金X > 500000:
   选择股票投资
else if 资金X > 100000:
   选择房产投资
else:
   选择买书,买设备自我提升

那么上面的伪代码就是表示一个极其简单的策略。这个策略只考虑资金量,输入资金量,输出决策方式。如果把Policy策略看做是一个黑箱,那么基于策略的方法就是:
在这里插入图片描述
那么如果不是基于Policy策略直接做出决策,我们还有什么办法呢?

显然有,而且大家可以从上面的简单策略看到一个最大的缺陷,就是上面的策略完全不考虑每一种选择未来的价值。我们做决策是有目的的,那就是为了最大化未来的回报Result是不是?那么对于上面的投资选择问题,我们的目标就是希望我们的投资回报率最高。因此,上面的简单策略竟然完全不考虑每一种选择的价值,而仅考虑资金量,显然是一种欠考虑的方法。因此,我们是不是应该评估一下每一种选择的潜在价值呢?耶,价值Value出来了,是不是?通过对价值的评估,我们也就可以有如下的做决策的方法

在这里插入图片描述
我们就评估每一种状态(选择+资金量)的价值,然后选择价值最高的作为最后的决策。比如说:

if 投资股市:
    因为股市低迷,价值为-100
if 投资房产 + 资金量 > 100000:
    因为房产泡沫还没破,各地房价还在涨,价值为+500
if 提升自己 + 资金量 < 100000:
    当前人工智能潜力巨大,资金又不算太大,投资自己价值为+1000
...(更多的评估价值的方法)

OK, 假设现在我们有50000的资金,那么根据我们的价值估算方法,选择投资自己的价值最大,为+1000,因此我们就选择投资自己作为决策结果。
从数学的角度,我们常常会用一个函数 v ( s ) v\left( s \right) v(s) 来表示一个状态的价值,也可以用 Q ( s , a ) Q\left( {s,a} \right) Q(s,a)来表示状态及某一个动作的价值。我们上面的例子就是来评估某一个状态下动作的价值,然后根据价值做出判断。实际上我们这里也是有策略的,我们的策略更简单:

if 某一个决策的价值最大:
    选择这个决策

这就是价值函数的意义。在后面的文章当中,我们还会发现,其实我们还可以同时使用策略加价值评估的方法来联合给出决策,这种算法就是所谓的Actor-Critic算法。这里就不多加介绍了。

再谈增强学习的意义
从上面的例子想必大家会发现,增强学习面向的决策与控制问题与我们的行为息息相关。我们想要让计算机自己能够学习做出某种决策,并且是可以不断改进的决策。对于人工智能,最大的目的不就是要创造智能,会自己思考,能模仿人类的行为,从而能够代替人类做事情吗?增强学习的目的就是希望计算机能够模仿人类的行为。这样一看,知友们是不是马上觉得增强学习意义非常之大。

实际上增强学习的算法都是基于人类的行为而构建的。比如上面的Value Function价值函数,实际上人类自己做决策的时候也就是那么做的。这里只不过是把它数学化了而已。

按照DeepMind的David Silver,也就是AlphaGo的第一作者所言:

DL + RL = AI

DL深度学习给了计算机“神经网络大脑”,RL给了计算机学习机制。这两者结合起来,就能创造智能!

接下来,我们介绍Bellman方程,增强学习领域最重要的一个方程。很多算法都是基于Bellman方程衍生而来。
Bellman方程
在上文我们介绍了Value Function价值函数,所以为了解决增强学习的问题,一个显而易见的做法就是---- 我们需要估算Value Function

是的,只要我们能够计算出价值函数,那么最优决策也就得到了。因此,问题就变成了如何计算Value Function?

怎么估算价值呢?

我们还是先想想我们人是怎么估算的?我们还是以上面的投资决策问题来作为例子

一般我们基于以下几种情况来做评估:

  • 其他人的选择。比如有很多人投资股市失败,因此我们就会降低我们投资股票的价值。
  • 自己的反复试验。我们常常不是只做一次选择,而是做了很多次选择,从而收获了所谓的“经验”的东西。我们根据经验来评估选择的价值。比如我们做了好几次投资楼市的选择,结果大获成功,因此我们就会认为投资楼市是不错的选择。
  • 基于理性分析。我们根据我们已有的知识对当前的情况做分析,从而做出一定的判断。
  • 基于感性的逻辑。比如选择投资自己到人工智能领域。虽然我们大约觉得人工智能前景很好,但是我们真正要投资自己到这个领域有时候仅仅是出于一种热爱或者说一种理想主义。就是不管别人觉得好不好,反正我觉得好,我就这么选了。

计算机要如何才能评估价值呢?

  • 其他人的选择。不好意思,计算机只有自己,没有其他人。也许你会说多台计算机。如果是共用一个“大脑”做分布式计算,那还是只有自己。
  • 基于理性分析。不好意思,计算机在面对问题时往往什么都不知道,比如基于屏幕玩Atari游戏,计算机压根不知道看到的像素是个什么东西。它没有人类的先验知识,无法分析。(当然啦,先使用监督学习然后再增强学习的AlphaGo就是有先验知识的情况下做的增强学习)
  • 基于感性的逻辑。不好意思,计算机目前还产生不了感性。

那么,基于自己的反复试验呢?耶,这个可以啊。计算机这方面比人类强多了,可以24小时不分昼夜的反复试验,然后对价值做出正确的判断。

所以,Value Function从分析上是可以评估出来的,那具体该怎么评估呢?

我们下面将不得不引入点数学公式,虽然也会非常好理解。

还记得回报Result的基本定义吗?就是所有Reward的累加(带衰减系数discount factor):
G t = R t + 1 + λ R t + 2 + … = ∑ k = 0 ∞ λ k R t + k + 1 {G_t} = {R_{t + 1}} + \lambda {R_{t + 2}} + \ldots = \sum\limits_{k = 0}^\infty {{\lambda ^k}{R_{t + k + {\rm{1}}}}} Gt=Rt+1+λRt+2+=k=0λkRt+k+1
那么Value Function该如何定义?也很简单,就是回报的期望啊!回报的期望越高,价值显然也就越大,也就越值得去选择。用数学来定义就是如下:
v ( s ) = E [ G t ∣ S t = s ] v\left( s \right) = {\rm E}\left[ {{G_t}|{S_t} = s} \right] v(s)=E[GtSt=s]

接下来,我们把上式展开如下:
v ( s ) = E [ G t ∣ S t = s ] = E [ R t + 1 + λ ( R t + 2 + λ R t + 3 + … ) ∣ S t = s ] = E [ R t + 1 + λ G t + 1 ∣ S t = s ] = E [ R t + 1 + λ v ( S t + 1 ) ∣ S t = s ] \begin{array}{l} v\left( s \right) = {\rm E}\left[ {{G_t}|{S_t} = s} \right]\\ {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} = {\rm E}\left[ {{R_{t + 1}} + \lambda ({R_{t + 2}} + \lambda {R_{t + 3}} + \ldots )|{S_t} = s} \right]\\ {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} = {\rm E}\left[ {{R_{t + 1}} + \lambda {G_{t + 1}}|{S_t} = s} \right]\\ {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} = {\rm E}\left[ {{R_{t + 1}} + \lambda v\left( {{S_{t + 1}}} \right)|{S_t} = s} \right] \end{array} v(s)=E[GtSt=s]=E[Rt+1+λ(Rt+2+λRt+3+)St=s]=E[Rt+1+λGt+1St=s]=E[Rt+1+λv(St+1)St=s]

因此,
v ( s ) = E [ R t + 1 + λ v ( S t + 1 ) ∣ S t = s ] v\left( s \right) = {\rm E}\left[ {{R_{t + 1}} + \lambda v\left( {{S_{t + 1}}} \right)|{S_t} = s} \right] v(s)=E[Rt+1+λv(St+1)St=s]

上面这个公式就是Bellman方程的基本形态。从公式上看,当前状态的价值下一步的价值以及当前的反馈Reward有关。

它表明Value Function是可以通过迭代来进行计算的!!!

Bellman方程是这么简洁的一个等式,但却是增强学习算法的基础。

接下来,我们将探讨Dynamic Programming(动态规划):也就是基于Bellman方程而衍生得到的求解Value Function的方法。

4. 动态规划与Q-Learning

接下来将介绍 如何构建基于Bellman方程的 算法 及Q-Learning。首先介绍动作价值函数:

  1. Action-Value function 动作价值函数

前面我们引出了价值函数,考虑到每个状态之后都有多种动作可以选择,每个动作之下的状态又多不一样,我们更关心在某个状态下的不同动作的价值。显然。如果知道了每个动作的价值,那么就可以选择价值最大的一个动作去执行了。这就是Action-Value function: Q π ( s , a ) {Q^\pi }\left( {s,a} \right) Qπ(s,a) 。那么同样的道理,也是使用reward来表示,

只是这里的reward和之前的reward不一样,这里是执行完动作action之后得到的reward,之前state对应的reward则是 多种动作对应的reward的期望值。显然,动作之后的reward更容易理解。
那么,有了上面的定义,动作价值函数就为如下表示:


参考链接:

[1]. https://zhuanlan.zhihu.com/p/21262246?refer=intelligentunit
[2]. https://zhuanlan.zhihu.com/p/21340755
[3]. https://blog.csdn.net/itplus/article/details/9361915

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值