【深度学习笔记】6 优化算法

参考

局部极小值和鞍点

函数 f ( x ) = x ⋅ c o s ( π x ) , − 1.0 ≤ x ≤ 2.0 f(x)=x⋅cos(πx),−1.0≤x≤2.0 f(x)=xcos(πx),1.0x2.0 中 存在局部极小值

在这里插入图片描述函数 f ( x ) = x 3 f(x)=x^3 f(x)=x3 中存在鞍点
在这里插入图片描述
二维空间函数 f ( x , y ) = x 2 − y 2 f(x,y)=x^2-y^2 f(x,y)=x2y2 的鞍点 ,在X轴上是局部最小值,在Y轴上是局部最大值
在这里插入图片描述
假设一个函数的输入为 k k k 维向量,输出为标量,那么它的海森矩阵(Hessian matrix)有 k 个特征值。该函数在梯度为0的位置上可能是局部最小值、局部最大值或者鞍点。

  • 当函数的海森矩阵在梯度为零的位置上的 特征值全为正 (正定矩阵)时,该函数得到局部最小值。
  • 当函数的海森矩阵在梯度为零的位置上的 特征值全为负 (负定矩阵)时,该函数得到局部最大值。
  • 当函数的海森矩阵在梯度为零的位置上的 特征值有正有负 时,该函数得到鞍点。

随机矩阵理论告诉我们,对于一个大的高斯随机矩阵来说,任一特征值是正或者是负的概率都是0.5。那么,以上第一种情况的概率为 0. 5 k 0.5^k 0.5k.由于深度学习模型参数通常都是高维的(k很大),目标函数的鞍点通常比局部最小值更常见。

梯度下降 gradient descent

根据泰勒公式 我们有以下近似 f ( x + ϵ ) ≈ f ( x ) + ϵ f ′ ( x ) f(x+\epsilon) \approx f(x) +\epsilon f'(x) f(x+ϵ)f(x)+ϵf(x)

找到一个 η > 0 \eta>0 η>0 使得 ∣ η f ′ ( x ) ∣ |\eta f'(x)| ηf(x)足够小,令 ϵ = − η f ′ ( x ) \epsilon = -\eta f'(x) ϵ=ηf(x)
f ( x − η f ′ ( x ) ) ≈ f ( x ) − η ( f ′ ( x ) ) 2 ≲ f ( x ) f(x-\eta f'(x)) \approx f(x)-\eta (f'(x))^2 ≲ f(x) f(xηf(x))f(x)η(f(x))2f(x)
所以我们有 η > 0 \eta>0 η>0 ,通过迭代 x x ← x − η f ′ ( x ) x \leftarrow x-\eta f'(x) xxηf(x)
这样函数 f ( x ) f(x) f(x)的值可能会降低。 η \eta η 称为学习率,太小 f ( x ) f(x) f(x)降低地缓慢,太大无法保证前面泰勒公式成立 ,无法保证 f ( x ) f(x) f(x) 值一定降低。

f ( x ) = x 2 , η = 0.05 f(x) = x^2,\eta=0.05 f(x)=x2,η=0.05 f ( x ) = x 2 , η = 1.1 f(x) = x^2,\eta = 1.1 f(x)=x2,η=1.1
在这里插入图片描述在这里插入图片描述

随机梯度下降

在深度学习里,目标函数通常是训练数据集中有关各个样本的损失函数的平均。设样本
x ( i ) = [ x 1 ( i ) , x 2 ( i ) , … , x m ( i ) ] , i = 1 , 2 … n x^ {(i)} = [x^{(i)}_1,x^{(i)}_2,\dots ,x^{(i)}_m],i=1,2 \dots n x(i)=[x1(i),x2(i),,xm(i)],i=1,2n
w w w 为模型的参数向量,目标函数定义为
f ( x , w ) = 1 n ∑ i = 1 n f ( x ( i ) , w ) f(x,w) = \dfrac{1}{n} \sum_{i=1}^n f (x^{(i)},w) f(x,w)=n1i=1nf(x(i),w)
目标函数在 w 处的梯度为
∇ f ( x , w ) = 1 n ∑ i = 1 n ∇ f ( x ( i ) , w ) \nabla f(x,w) = \dfrac{1}{n} \sum_{i=1}^n \nabla f(x^{(i)},w) f(x,w)=n1i=1nf(x(i),w)

如果使用梯度下降,每次自变量迭代的计算开销为 O ( n ) O(n) O(n),它随着 n n n 线性增长。因此,当训练数据样本数很大时,梯度下降每次迭代的计算开销很高。

随机梯度下降(stochastic gradient descent,SGD)减少了每次迭代的计算开销。在随机梯度下降的每次迭代中,我们随机均匀采样的一个样本索引 i ∈ 1 , … , n i \in {1,…,n} i1,,n,并计算梯度 ∇ f ( x ( i ) , w ) \nabla f(x^{(i)},w) f(x(i),w) 来迭代 w
w ← w − η ∇ f ( x ( i ) , w ) w \leftarrow w-\eta \nabla f(x^{(i)},w) wwηf(x(i),w)
可以看到每次迭代的计算开销从梯度下降的 O(n) 降到了常数 O ( 1 ) O(1) O(1)。随机梯度 ∇ f ( x ( i ) , w ) \nabla f(x^{(i)},w) f(x(i),w) 是对梯度 ∇ f ( x , w ) \nabla f(x,w) f(x,w) 的无偏估计:
E ( ∇ f ( x ( i ) ) , w ) = ∑ i = 1 n ∇ f ( x ( i ) , w ) ∗ 1 n ( 均 与 分 布 概 率 1 / n ) = 1 n ∑ i = 1 n ∇ f ( x ( i ) , w ) = ∇ f ( x , w ) E(\nabla f(x^{(i)}),w)= \sum_{i=1}^n \nabla f(x^{(i)},w)*\dfrac{1}{n}(均与分布概率1/n) = \dfrac{1}{n} \sum_{i=1}^{n} \nabla f(x^{(i)},w)=\nabla f(x,w) E(f(x(i)),w)=i=1nf(x(i),w)n1(1/n)=n1i=1nf(x(i),w)=f(x,w)
这意味着,平均来说,随机梯度是对梯度的一个良好的估计。

小批量随机梯度下降

梯度下降是用全部的训练集(n个),随机梯度下降每次随机使用一个数据(1个)。我们可以折中一下每次随机抽取 ∣ B ∣ |\Beta| B 个, B \Beta B 为一个随机的 mini-batch序号
g t ( B t ) = ∇ f ( x B t , w t − 1 ) = 1 ∣ B t ∣ ∑ i ∈ B t ∇ f ( x ( i ) , w t − 1 ) g_t(\Beta_t)=\nabla f(x^{\Beta_t},w_{t-1})=\dfrac{1}{|\Beta_t|}\sum_{i \in \Beta_t} \nabla f(x^{(i)},w_{t-1}) gt(Bt)=f(xBt,wt1)=Bt1iBtf(x(i),wt1)
w t ← w t − 1 − η t g t = w t − 1 − η t ∣ B t ∣ ∑ i ∈ B t ∇ f ( x ( i ) , w t − 1 ) w_t \leftarrow w_{t-1}-\eta_t g_t=w_{t-1} - \dfrac{\eta_t}{|\Beta_t|}\sum_{i \in \Beta_t} \nabla f(x^{(i)},w_{t-1}) wtwt1ηtgt=wt1BtηtiBtf(x(i),wt1)

每次从 n 个重复采样 ∣ B ∣ 个 |\Beta|个 B g t g_t gt ∇ f ( x , w t − 1 ) \nabla f(x,w_{t-1}) f(x,wt1)的无偏估计(没看懂)

基于随机采样得到的梯度的方差在迭代过程中无法减小,因此在实际中,(小批量)随机梯度下降的学习率可以在迭代过程中自我衰减,例如 η t = η t α η_t=η_t^α ηt=ηtα通常 α = − 1 α=−1 α=1或者 − 0.5 −0.5 0.5 η t = η α t η_t=ηα^t ηt=ηαt
α = 0.95 α=0.95 α=0.95 ,或者每迭代若干次后将学习率衰减一次。如此一来,学习率和(小批量)随机梯度乘积的方差会减小。而梯度下降在迭代过程中一直使用目标函数的真实梯度,无须自我衰减学习率。

Pytorch

torch.optim.SGD(params, lr=<required parameter>, momentum=0, dampening=0, weight_decay=0, nesterov=False)

weight_dacay 权重衰减等价于L2范数正则化(L2 penalty),通常会使学到的权重参数的元素较接近0

动量法

动量法使得相邻时间步的自变量更新在方向上更加一致(不会出现太大的震荡)

指数加权平均

y t = ( 1 − γ ) x t + γ y t − 1 = ( 1 − γ ) x t ( 1 − γ ) γ x t − 1 + γ 2 y t − 2 ⏟ γ y t − 1 = γ ( 1 − γ ) x t − 1 + γ 2 y t − 2 = ( 1 − γ ) x t + ( 1 − γ ) γ x t − 1 + ( 1 − γ ) γ 2 x t − 2 + γ 3 y t − 3 ⇒ n = 1 1 − γ 1 n x t + 1 n ∗ ( 1 − 1 n ) x t − 1 + 1 n ∗ ( 1 − 1 n ) 2 x t − 2 + ( 1 − 1 n ) 3 y t − 3 = 1 n ∑ i = 0 k ( 1 − 1 n ) k x t − k + ( 1 − 1 n ) y t − ( k + 1 ) (1) \tag{1}{ \begin{aligned} y_t &=(1-\gamma)x_t + \gamma y_{t-1}\\ & =(1-\gamma)x_t \underbrace{(1-\gamma)\gamma x_{t-1}+\gamma^2y_{t-2}}_{\text{$\boxed {\gamma y_{t-1}=\gamma(1-\gamma)x_{t-1}+\gamma^2y_{t-2}}$}} \\ &=(1-\gamma)x_{t}+(1-\gamma)\gamma x_{t-1}+(1-\gamma)\gamma^2x_{t-2}+\gamma^3y_{t-3} \\ \xRightarrow{n=\frac{1}{1-\gamma}} & \dfrac{1}{n}x_{t}+\dfrac{1}{n}*(1-\dfrac{1}{n})x_{t-1}+ \dfrac{1}{n}*(1-\dfrac{1}{n})^2x_{t-2}+(1-\dfrac{1}{n})^3y_{t-3} \\ &=\dfrac{1}{n}\sum_{i=0}^{k}(1-\dfrac{1}{n})^{k}x_{t-k} +(1-\dfrac{1}{n})y_{t-(k+1)} \end{aligned} } ytn=1γ1 =(1γ)xt+γyt1=(1γ)xtγyt1=γ(1γ)xt1+γ2yt2 (1γ)γxt1+γ2yt2=(1γ)xt+(1γ)γxt1+(1γ)γ2xt2+γ3yt3n1xt+n1(1n1)xt1+n1(1n1)2xt2+(1n1)3yt3=n1i=0k(1n1)kxtk+(1n1)yt(k+1)(1)
忽略最后一个高阶项,我们可以将 y t y_t yt 看成当前时刻 t 及之前 k 次
{ x t , x t − 1 , … x t − k } \{x_t,x_{t-1},\dots x_{t-k}\} {xt,xt1,xtk}
的加权和,权重为 ( 1 − 1 n ) k (1-\dfrac{1}{n})^k (1n1)k ,k越大(离当前时刻t越远)权重越小
( 1 − 1 n ) n = ( 1 − 1 + γ ) n = γ n = γ ( 1 1 − γ ) = 1 γ ( 1 − γ ) (1-\dfrac{1}{n})^n=(1-1+\gamma)^n=\gamma^n=\gamma^{(\dfrac{1}{1-\gamma})}=\dfrac{1}{\gamma^{(1-\gamma)}} (1n1)n=(11+γ)n=γn=γ(1γ1)=γ(1γ)1

lim ⁡ x → ∞ ( 1 + 1 x ) x = e \lim_{x \rightarrow \infty }(1+\dfrac{1}{x})^x = e xlim(1+x1)x=e
lim ⁡ n → ∞ ( 1 − 1 n ) n = lim ⁡ − n → ∞ [ ( 1 + 1 − n ) ( − n ) ] − 1 = e − 1 = 1 e ≈ 0.3679 \lim_{n \rightarrow \infty} (1-\dfrac{1}{n})^n=\lim_{-n \rightarrow \infty} [(1+\dfrac{1}{-n})^{(-n)}]^{-1}=e^{-1}=\dfrac{1}{e}\approx0.3679 nlim(1n1)n=nlim[(1+n1)(n)]1=e1=e10.3679

γ → 1 , ( 1 − 1 n ) n → 1 e \gamma \rightarrow 1,(1-\dfrac{1}{n})^n \rightarrow \dfrac{1}{e} γ1,(1n1)ne1
举个例子说明,当 γ = 0.95 , ( 1 − γ ) = 0.05 , n = 1 0.05 = 20 \gamma =0.95, (1-\gamma)=0.05,n=\dfrac{1}{0.05}=20 γ=0.95,(1γ)=0.05,n=0.051=20
带入(1)式有
y t = 0.05 ∑ i = 0 20 0.9 5 i x t − i + 0.9 5 21 x t − ( i + 1 ) \boxed {y_t = 0.05 \sum_{i=0}^{20} 0.95^i x_{t-i}} + 0.95^{21} x_{t-(i+1)} yt=0.05i=0200.95ixti+0.9521xt(i+1)

动量法

v t = γ v t − 1 + η t g t w t = w t − 1 − v t \begin{aligned} v_t &= \gamma v_{t-1}+ \eta_t g_t \\ w_t &= w_{t-1}-v_t \end{aligned} vtwt=γvt1+ηtgt=wt1vt
其中
v t = γ v t − 1 + ( 1 − γ ) [ η t 1 − γ g t ] = 1 n ∑ i = 0 k ( 1 − 1 n ) k [ η t 1 − γ g t ] t − k + ( 1 − 1 n ) v t − ( k + 1 ) \begin{aligned} v_t &=\gamma v_{t-1} + (1-\gamma) [\dfrac{\eta_t}{1-\gamma} g_t] \\ &=\dfrac{1}{n}\sum_{i=0}^{k}(1-\dfrac{1}{n})^{k}[\dfrac{\eta_t}{1-\gamma} g_t]_{t-k} +(1-\dfrac{1}{n})v_{t-(k+1)} \end{aligned} vt=γvt1+(1γ)[1γηtgt]=n1i=0k(1n1)k[1γηtgt]tk+(1n1)vt(k+1)
可以看到动量法当前时刻的梯度 v t v_t vt 近似的看成
η t 1 − γ g t , η t 1 − γ g t − 1 , … , η t 1 − γ g t − k \dfrac{\eta_t}{1-\gamma} g_t,\dfrac{\eta_t}{1-\gamma} g_{t-1},\dots,\dfrac{\eta_t}{1-\gamma} g_{t-k} 1γηtgt,1γηtgt1,,1γηtgtk
即之前梯度的加权平均

f ( x ) = 0.1 x 1 2 + 2 x 2 2 f(x)=0.1x_1^2+2x_2^2 f(x)=0.1x12+2x22 图像

无动量有动量
η = 0.4 \eta =0.4 η=0.4 ( γ = 0.5 ) (\gamma = 0.5) (γ=0.5)在这里插入图片描述在这里插入图片描述
η = 0.6 \eta =0.6 η=0.6 ( γ = 0.5 ) (\gamma = 0.5) (γ=0.5)在这里插入图片描述在这里插入图片描述

动量通常设置 0.9

Nesterov加速梯度下降法(Nesterov accelerated gradient,NAG)

在这里插入图片描述
v t = γ v t − 1 + η ∇ w f ( w t − 1 − γ v t − 1 ) w t = w t − 1 − v t \begin{aligned} v_t &= \gamma v_{t-1} +\eta \nabla_w f(w_{t-1}- \gamma v_{t-1}) \\ w_t &= w_{t-1}-v_t \end{aligned} vtwt=γvt1+ηwf(wt1γvt1)=wt1vt

Adagrad 法

首先各个维度上单独计算
s t = s t − 1 + g t ⊙ g t s_t= s_{t-1} + g_t \odot g_t st=st1+gtgt
w t = w t − 1 + η s t + ϵ ⊙ g t w_t = w_{t-1}+\dfrac{\eta}{\sqrt{s_t + \epsilon }} \odot g_t wt=wt1+st+ϵ ηgt

⊙ \odot 是按元素乘法,首先为什么采用这个形式
在这里插入图片描述
在这里插入图片描述
也就是说当采样足够多的时候,可以用一阶梯度的平方和再开根号估计。

需要强调的是,小批量随机梯度按元素平方的累加变量 s t s_t st出现在学习率的分母项中。因此,如果目标函数有关自变量中某个元素的偏导数一直都较大,那么该元素的学习率将下降较快;反之,如果目标函数有关自变量中某个元素的偏导数一直都较小,那么该元素的学习率将下降较慢。然而,由于 s t s_t st 一直在累加按元素平方的梯度,自变量中每个元素的学习率在迭代过程中一直在降低(或不变)。所以,当学习率在迭代早期降得较快且当前解依然不佳时,AdaGrad算法在迭代后期由于学习率过小,可能较难找到一个有用的解

Pytorch

torch.optim.Adagrad(params, lr=0.01, lr_decay=0, weight_decay=0, initial_accumulator_value=0, eps=1e-10)

RMSProp 法

RMSProp 法是针对Adagrad 法的缺点来设计的,Adagrad 的问题是分母是 之前所有的梯度平方和再开根号,这个值是不断增大的,现在 RMSProp 改为之最近 1 / ( 1 − γ ) 1/(1-\gamma) 1/(1γ)个时间步的梯度平方和而不是之前所有的,这样这个值不会一直增大,学习率不会一直减小。

s t = γ s t − 1 + ( 1 − γ ) g t ⊙ g t s_t = \gamma s_{t-1}+(1-\gamma) g_t \odot g_t st=γst1+(1γ)gtgt
w t = w t − 1 − η s t + ϵ ⊙ g t w_t =w_{t-1}-\dfrac{\eta}{\sqrt{s_t+\epsilon}} \odot g_t wt=wt1st+ϵ ηgt

Pytorch

torch.optim.RMSprop(params, lr=0.01, alpha=0.99, eps=1e-08, weight_decay=0, momentum=0, centered=False)

AdaDelta 法

与 RMSProp 相比 AdaDelta 使用 Δ w \Delta w Δw 来代替 η \eta η
s t = ρ s t − 1 + ( 1 − ρ ) g t ⊙ g t g t ′ = Δ x t − 1 + ϵ s t + ϵ w t = w t − 1 − g t ′ Δ w t = ρ Δ w t − 1 + ( 1 − ρ ) g t ′ ⊙ g t ′ \begin{aligned} s_t &= \rho s_{t-1}+(1-\rho) g_t \odot g_t \\ g_t' &=\sqrt{\dfrac{\Delta x_{t-1}+\epsilon}{s_t+\epsilon}} \\ w_t &= w_{t-1}-g_t' \\ \Delta w_t &= \rho \Delta w_{t-1}+(1-\rho)g_t' \odot g_t' \end{aligned} stgtwtΔwt=ρst1+(1ρ)gtgt=st+ϵΔxt1+ϵ =wt1gt=ρΔwt1+(1ρ)gtgt

Pytorch

torch.optim.Adadelta(params, lr=1.0, rho=0.9, eps=1e-06, weight_decay=0)

Adam 法

  • Adam算法在RMSProp算法基础上对小批量随机梯度也做了指数加权移动平均。
  • Adam算法使用了偏差修正
    v t = β 1 v t − 1 + ( 1 − β 1 ) g t s t = β 2 s t − 1 + ( 1 − β 2 ) g t ⊙ g t \begin{aligned} v_t &= \beta_1 v_{t-1}+(1-\beta_1)g_t \\ s_t &= \beta_2 s_{t-1}+(1-\beta_2) g_t \odot g_t \end{aligned} vtst=β1vt1+(1β1)gt=β2st1+(1β2)gtgt

其中 0 ≤ β 1 , β 2 ≤ 1 0 \le \beta_1,\beta_2 \le 1 0β1,β21 作者推荐 β 1 = 0.9 , β 2 = 0.999 \beta_1 = 0.9,\beta_2 = 0.999 β1=0.9,β2=0.999

按前面指数加权平均的方法展开
v t = β 1 v t − 1 + ( 1 − β 1 ) g t = ( 1 − β 1 ) g t + ( 1 − β 1 ) β 1 g t − 1 + β 1 2 v t − 2 = ( 1 − β 1 ) g t + ( 1 − β 1 ) β 1 g t − 1 + ( 1 − β 1 ) β 1 2 g t − 2 + β 1 3 g t − 3 = ( 1 − β 1 ) ∑ i = 0 k β 1 k g t − k + β 1 k + 1 g t − ( k + 1 ) \begin{aligned} v_t &= \beta_1 v_{t-1}+(1-\beta_1)g_t \\ & = (1-\beta_1)g_t +(1-\beta_1)\beta_1 g_{t-1}+\beta_1^2 v_{t-2} \\ & = (1-\beta_1)g_t +(1-\beta_1)\beta_1 g_{t-1} +(1-\beta_1)\beta_1^2 g_{t-2} +\beta_1^3 g_{t-3} \\ & = (1-\beta_1) \sum_{i=0}^k \beta_1^k g_{t-k} +\beta_1^{k+1} g_{t-(k+1)} \end{aligned} vt=β1vt1+(1β1)gt=(1β1)gt+(1β1)β1gt1+β12vt2=(1β1)gt+(1β1)β1gt1+(1β1)β12gt2+β13gt3=(1β1)i=0kβ1kgtk+β1k+1gt(k+1)

省略最后一项
v t = ( 1 − β 1 ) ∑ i = 0 k β 1 k g t − k v_t = (1-\beta_1) \sum_{i=0}^k \beta_1^k g_{t-k} vt=(1β1)i=0kβ1kgtk

是一个加权和,权重求和
( 1 − β 1 ) ∑ i = 0 t β 1 t = ( 1 − β 1 ) β 1 t − 1 β 1 − 1 = 1 − β 1 t (1-\beta_1)\sum_{i=0}^t \beta_1^t=(1-\beta_1) \dfrac{\beta_1^{t}-1}{\beta_1-1}=1-\beta_1^t (1β1)i=0tβ1t=(1β1)β11β1t1=1β1t

偏差修正就是让权重和为1,即乘以 1 1 − β 1 t \dfrac{1}{1-\beta_1^t} 1β1t1
所以 v t = β 1 v t − 1 + ( 1 − β 1 ) g t 1 − β 1 t \boxed {v_t = \dfrac{ \beta_1 v_{t-1}+(1-\beta_1)g_t}{1-\beta_1^t}} vt=1β1tβ1vt1+(1β1)gt
同理 s t = β 2 s t − 1 + ( 1 − β 2 ) g t ⊙ g t 1 − β 2 t \boxed {s_t =\dfrac{ \beta_2 s_{t-1}+(1-\beta_2) g_t \odot g_t}{1-\beta_2^t}} st=1β2tβ2st1+(1β2)gtgt

然后 g t ′ = η v t s t + ϵ g_t' = \dfrac{\eta v_t}{\sqrt{s_t+\epsilon}} gt=st+ϵ ηvt
w t = w t − 1 − g t ′ w_t = w_{t-1}-g_t' wt=wt1gt

Pytorch

torch.optim.Adam(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0, amsgrad=False)

amsgrad On the Convergence of Adam and Beyond

算法可视化

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

右图我们看到不同算法在损失曲面的等高线上走的不同路线。所有的算法都是从同一个点出发并选择不同路径到达最优点。注意:Adagrad,Adadelta和RMSprop能够立即转移到正确的移动方向上并以类似的速度收敛,而动量法和NAG会导致偏离。然而,NAG能够在偏离之后快速修正其路线,因为NAG通过对最优点的预见增强其响应能力。

左图不同算法在鞍点出的行为,鞍点即为一个点在一个维度上的斜率为正,而在其他维度上的斜率为负,SGD,动量法和NAG在鞍点处很难打破对称性,尽管后面两个算法最终设法逃离了鞍点。而Adagrad,RMSprop和Adadelta能够快速想着梯度为负的方向移动,其中Adadelta走在最前面。|

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值