Vector, Matrix, and Tensor Derivatives by Erik Learned-Miller(译)

  本文档旨在帮助您了解和获取矢量、矩阵和高阶张量(具有三维或更多维的阵列)的导数。

1 简化,简化,简化

对数组进行求导的大部分困惑源于试图同时做太多事情。这些事情包括同时获取多个部分的导数、在存在求和符号的情况下获取导数、以及应用链式法则。至少在缺乏经验的情况下,试图同时完成所有这些事情将会使我们犯错的可能性大大增加。

1.1 将符号扩展为每个部分的显式和与方程式

为了简化给定的计算,为输出的单个标量元素(除了标量变量之外)写出显式公式通常很有用。一旦根据其他标量值能够得到输出的单个标量元素的一个显式公式,那么使用微积分就可以解决问题,这比尝试同时进行矩阵数学,求和以及导数计算更容易。

Example. 假设我们有一个长度为 C C C的列向量 y ⃗ \vec{y} y ,它通过形成 C × D C\times D C×D矩阵 W W W与长度为 D D D的列向量 x ⃗ \vec{x} x 的乘积来计算:
(1) y ⃗ = W x ⃗ 。 \vec{y}=W\vec{x} \tag{1}。 y =Wx (1)  假设我们需要研究 y ⃗ \vec{y} y 关于 x ⃗ \vec{x} x 的导数。该导数的完整表征需要 y ⃗ \vec{y} y 的每个分量相对于 x ⃗ \vec{x} x 的每个分量的(偏)导数,在这种情况下,其将包含 C × D C×D C×D个值,因为在 y ⃗ \vec{y} y 中有 C C C个分量,在 x ⃗ \vec{x} x 中有 D D D个分量。
  让我们从计算其中一个开始,比如 y ⃗ \vec{y} y 的第3个分量,相对于 x ⃗ \vec{x} x 的第7个分量。也就是说,我们想要计算
∂ y ⃗ 3 ∂ x ⃗ 7 , \frac{\partial \vec{y}_{3}}{\partial \vec{x}_{7}}, x 7y 3这只是一个标量关于另一个标量的导数。
  要做的第一件事就是写下计算 y ⃗ 3 \vec{y}_{3} y 3的公式,这样我们就可以得出它的导数。 根据矩阵向量乘法的定义,通过取 W W W的第3行和向量 x ⃗ \vec{x} x 之间的点积来计算值 y ⃗ 3 \vec{y}_{3} y 3
(2) y ⃗ 3 = ∑ j = 1 D W 3 , j x ⃗ j 。 \vec{y}_{3}=\sum_{j=1}^{D}{W_{3,j} \vec{x}_{j}} \tag{2}。 y 3=j=1DW3,jx j(2)此时,我们已经将原始矩阵方程 ( 1 ) (1) (1)简化为标量方程。这使得计算所需的导数变得更容易。

1.2 去掉求和符号

虽然直接从公式 ( 2 ) (2) (2)计算导数当然是可能的,但人们在区分包含求和符号( ∑ \sum )或乘积符号( ∏ \prod )的表达式时经常会出错。开始计算时,写出一个没有任何求和符号的计算有时候是有用的,这能确保你做的一切正确。使用“1”作为第一个下标,我们有:
y ⃗ 3 = W 3 , 1 x ⃗ 1 + W 3 , 2 x ⃗ 2 + . . . + W 3 , 7 x ⃗ 7 + . . . + W 3 , D x ⃗ D 。 \vec{y}_{3}=W_{3,1} \vec{x}_{1}+W_{3,2} \vec{x}_{2}+...+W_{3,7} \vec{x}_{7}+...+W_{3,D} \vec{x}_{D}。 y 3=W3,1x 1+W3,2x 2+...+W3,7x 7+...+W3,Dx D当然,我已经明确地包含了涉及 x ⃗ 7 \vec{x}_{7} x 7的术语,因为这就是我们在这方面的不同之处。 在这一点上,我们可以看到 y ⃗ 3 \vec{y}_{3} y 3的表达式仅依赖于 x ⃗ 7 \vec{x}_{7} x 7到单个项 W 3 , 7 x ⃗ 7 W_{3,7} \vec{x}_{7} W3,7x 7。 由于求和中的其他项都不包括 x ⃗ 7 \vec{x}_{7} x 7,因此它们相对于 x ⃗ 7 \vec{x}_{7} x 7的导数都是0.因此,我们有
(3) ∂ y ⃗ 3 ∂ x ⃗ 7 = ∂ ∂ x ⃗ 7 [ W 3 , 1 x ⃗ 1 + W 3 , 2 x ⃗ 2 + . . . + W 3 , 7 x ⃗ 7 + . . . + W 3 , D x ⃗ D ] = 0 + 0 + . . . + ∂ ∂ x ⃗ 7 [ W 3 , 7 x ⃗ 7 ] + . . . + 0 = ∂ ∂ x ⃗ 7 [ W 3 , 7 x ⃗ 7 ] = W 3 , 7 。 \begin{aligned} \frac{\partial \vec{y}_{3}}{\partial \vec{x}_{7}}&=\frac{\partial }{\partial \vec{x}_{7}}{[W_{3,1} \vec{x}_{1}+W_{3,2} \vec{x}_{2}+...+W_{3,7} \vec{x}_{7}+...+W_{3,D} \vec{x}_{D}]} \tag{3}\\ &=0+0+...+\frac{\partial }{\partial \vec{x}_{7}}{[W_{3,7} \vec{x}_{7}]}+...+0\\ &=\frac{\partial }{\partial \vec{x}_{7}}{[W_{3,7} \vec{x}_{7}]}\\ &=W_{3,7}。 \end{aligned} x 7y 3=x 7[W3,1x 1+W3,2x 2+...+W3,7x 7+...+W3,Dx D]=0+0+...+x 7[W3,7x 7]+...+0=x 7[W3,7x 7]=W3,7(3)  通过关注 y ⃗ \vec{y} y 的一个分量和 x ⃗ \vec{x} x 的一个分量,我们使计算变得尽可能简单。 在将来,当您感到困惑时,可以尝试将问题减少到这个最基本的设置,以查看您出错的地方。

1.2.1 完成导数:Jacobian矩阵

回想一下,我们的最初目标是计算 y ⃗ \vec{y} y 的每个分量相对于 x ⃗ \vec{x} x 的每个分量的导数,并且我们注意到其数量将是 C × D C\times D C×D。 它们可以以下列形式写成矩阵:
[ ∂ y ⃗ 1 ∂ x ⃗ 1 ∂ y ⃗ 1 ∂ x ⃗ 2 ∂ y ⃗ 1 ∂ x ⃗ 3 ⋯ ∂ y ⃗ 1 ∂ x ⃗ D ∂ y ⃗ 2 ∂ x ⃗ 1 ∂ y ⃗ 2 ∂ x ⃗ 2 ∂ y ⃗ 2 ∂ x ⃗ 3 ⋯ ∂ y ⃗ 2 ∂ x ⃗ D ⋮ ⋮ ⋮ ⋱ ⋮ ∂ y ⃗ C ∂ x ⃗ 1 ∂ y ⃗ C ∂ x ⃗ 2 ∂ y ⃗ C ∂ x ⃗ 3 ⋯ ∂ y ⃗ C ∂ x ⃗ D ] \begin{bmatrix} \frac{\partial \vec{y}_{1}}{\partial \vec{x}_{1}} &\frac{\partial \vec{y}_{1}}{\partial \vec{x}_{2}} &\frac{\partial \vec{y}_{1}}{\partial \vec{x}_{3}} &\cdots &\frac{\partial \vec{y}_{1}}{\partial \vec{x}_{D}} \\ \frac{\partial \vec{y}_{2}}{\partial \vec{x}_{1}} &\frac{\partial \vec{y}_{2}}{\partial \vec{x}_{2}} &\frac{\partial \vec{y}_{2}}{\partial \vec{x}_{3}} &\cdots &\frac{\partial \vec{y}_{2}}{\partial \vec{x}_{D}} \\ \vdots &\vdots &\vdots &\ddots &\vdots \\ \frac{\partial \vec{y}_{C}}{\partial \vec{x}_{1}} &\frac{\partial \vec{y}_{C}}{\partial \vec{x}_{2}} &\frac{\partial \vec{y}_{C}}{\partial \vec{x}_{3}} &\cdots &\frac{\partial \vec{y}_{C}}{\partial \vec{x}_{D}} \\ \end{bmatrix} x 1y 1x 1y 2x 1y Cx 2y 1x 2y 2x 2y Cx 3y 1x 3y 2x 3y Cx Dy 1x Dy 2x Dy C在这种特殊情况下,这称为雅可比矩阵,但这个术语对我们的目的来说并不太重要。
  请注意,对于等式
y ⃗ = W x ⃗ , \vec{y}=W\vec{x}, y =Wx 关于 x ⃗ 7 \vec{x}_{7} x 7 y ⃗ 3 \vec{y}_{3} y 3的部分简单地由 W 3 , 7 W_{3,7} W3,7给出。如果你对其他组件进行相同的处理,你会发现,对于所有 i i i j j j
∂ y ⃗ i ∂ x ⃗ j = W i , j 。 \frac{\partial \vec{y}_{i}}{\partial \vec{x}_{j}}=W_{i,j}。 x jy i=Wi,j这意味着偏导数矩阵是
[ ∂ y ⃗ 1 ∂ x ⃗ 1 ∂ y ⃗ 1 ∂ x ⃗ 2 ∂ y ⃗ 1 ∂ x ⃗ 3 ⋯ ∂ y ⃗ 1 ∂ x ⃗ D ∂ y ⃗ 2 ∂ x ⃗ 1 ∂ y ⃗ 2 ∂ x ⃗ 2 ∂ y ⃗ 2 ∂ x ⃗ 3 ⋯ ∂ y ⃗ 2 ∂ x ⃗ D ⋮ ⋮ ⋮ ⋱ ⋮ ∂ y ⃗ C ∂ x ⃗ 1 ∂ y ⃗ C ∂ x ⃗ 2 ∂ y ⃗ C ∂ x ⃗ 3 ⋯ ∂ y ⃗ C ∂ x ⃗ D ] = [ W 1 , 1 W 1 , 2 W 1 , 3 ⋯ W 1 , D W 2 , 1 W 2 , 2 W 2 , 3 ⋯ W 2 , D ⋮ ⋮ ⋮ ⋱ ⋮ W C , 1 W C , 2 W C , 3 ⋯ W C , D ] \begin{bmatrix} \frac{\partial \vec{y}_{1}}{\partial \vec{x}_{1}} &\frac{\partial \vec{y}_{1}}{\partial \vec{x}_{2}} &\frac{\partial \vec{y}_{1}}{\partial \vec{x}_{3}} &\cdots &\frac{\partial \vec{y}_{1}}{\partial \vec{x}_{D}} \\ \frac{\partial \vec{y}_{2}}{\partial \vec{x}_{1}} &\frac{\partial \vec{y}_{2}}{\partial \vec{x}_{2}} &\frac{\partial \vec{y}_{2}}{\partial \vec{x}_{3}} &\cdots &\frac{\partial \vec{y}_{2}}{\partial \vec{x}_{D}} \\ \vdots &\vdots &\vdots &\ddots &\vdots \\ \frac{\partial \vec{y}_{C}}{\partial \vec{x}_{1}} &\frac{\partial \vec{y}_{C}}{\partial \vec{x}_{2}} &\frac{\partial \vec{y}_{C}}{\partial \vec{x}_{3}} &\cdots &\frac{\partial \vec{y}_{C}}{\partial \vec{x}_{D}} \\ \end{bmatrix}= \begin{bmatrix} W_{1,1} & W_{1,2} & W_{1,3} &\cdots & W_{1,D} \\ W_{2,1} & W_{2,2} & W_{2,3} &\cdots & W_{2,D} \\ \vdots & \vdots & \vdots &\ddots &\vdots \\ W_{C,1} & W_{C,2} & W_{C,3} &\cdots & W_{C,D} \\ \end{bmatrix} x 1y 1x 1y 2x 1y Cx 2y 1x 2y 2x 2y Cx 3y 1x 3y 2x 3y Cx Dy 1x Dy 2x Dy C=W1,1W2,1WC,1W1,2W2,2WC,2W1,3W2,3WC,3W1,DW2,DWC,D这显然就是 W W W本身。
  因此,基于以上所做工作我们可以得出结论,对于
y ⃗ = W x ⃗ , \vec{y}=W\vec{x}, y =Wx 我们有
d y ⃗ d x ⃗ = W 。 \frac{\mathrm{d} \vec{y}}{\mathrm{d} \vec{x}}=W。 dx dy =W

2 行向量而不是列向量

在处理不同的神经网络包时,我们应当密切注意权重矩阵、数据矩阵等的排列。 例如,如果数据矩阵 X X X包含许多不同的矢量,每个矢量代表一个输入,则每个数据矢量是否构成数据矩阵 X X X的行或列?
  在第一部分的示例中,我们使用了矢量 x ⃗ \vec{x} x ,它是一个列向量。 但是,当 x ⃗ \vec{x} x 是行向量时,您还应该能够使用相同的基本思想。

2.1 Example 2

y ⃗ \vec{y} y 是长度为 C C C的行向量,其通过取另一长度为 D D D的行向量 x ⃗ \vec{x} x D D D C C C列的矩阵W的乘积来计算。
y ⃗ = x ⃗ W 。 \vec{y}=\vec{x}W。 y =x W重要的是,尽管 y ⃗ \vec{y} y x ⃗ \vec{x} x 分量数量并未改变,但 W W W的形状却变成 W W W之前形状的转置。特别是,因为我们现在左乘 x ⃗ \vec{x} x ,而之前 x ⃗ \vec{x} x 在右边,所以 W W W必须转换为矩阵代数才能使用。
  在这种情况下,由
y ⃗ 3 = ∑ j = 1 D x ⃗ j W j , 3 \vec{y}_{3}=\sum_{j=1}^{D}{ \vec{x}_{j} W_{j,3}} y 3=j=1Dx jWj,3可以得到
∂ y ⃗ 3 ∂ x ⃗ 7 = W 7 , 3 。 \frac{\partial \vec{y}_{3}}{\partial \vec{x}_{7}}=W_{7,3}。 x 7y 3=W7,3请注意,W的下标与第一个示例中的下标相反。 然而,当写出完整的雅可比矩阵时,我们仍然可以看到,
(4) d y ⃗ d x ⃗ = W 。 \frac{\mathrm{d} \vec{y}}{\mathrm{d} \vec{x}}=W \tag{4}。 dx dy =W(4)

3 处理更高的维度

让我们考虑另一个密切相关的问题,即计算
d y ⃗ d W 。 \frac{\mathrm{d} \vec{y}}{\mathrm{d} W}。 dWdy 在这种情况下, y ⃗ \vec{y} y 沿一个坐标变化,而 W W W沿两个坐标变化。 因此,所有的导数自然而然包含在三维阵列中。我们避免使用术语“三维矩阵”,因为不清楚矩阵乘法和其他矩阵运算是如何在三维阵列上定义的。
  处理三维数组时,尝试找到显示它们的方法可能会更麻烦。 相反,我们应该简单地将结果定义为可用于计算所需三维数组的任何元素的结果的公式。
  让我们再次计算 y ⃗ \vec{y} y 的一个分量之间的标量导数,比如 y ⃗ 3 \vec{y}_{3} y 3 W W W的一个分量,比如 W 7 , 8 W_{7,8} W7,8。 让我们从相同的基本设置开始,在这些设置中我们用其他标量分量来记录 y ⃗ 3 \vec{y}_{3} y 3的等式。 现在我们想要一个用标量值表示 y ⃗ 3 \vec{y}_{3} y 3的方程,并显示 W 7 , 8 W_{7,8} W7,8在其计算中的作用。
  然而,我们看到的是 W 7 , 8 W_{7,8} W7,8 y ⃗ 3 \vec{y}_{3} y 3的计算中没有任何作用,因为
(5) y ⃗ 3 = x ⃗ 1 W 1 , 3 + x ⃗ 2 W 2 , 3 + . . . + x ⃗ D W D , 3 。 \vec{y}_{3}= \vec{x}_{1}W_{1,3}+\vec{x}_{2}W_{2,3} +...+\vec{x}_{D}W_{D,3} \tag{5} 。 y 3=x 1W1,3+x 2W2,3+...+x DWD,3(5)也就是说,
∂ y ⃗ 3 ∂ W 7 , 8 = 0 。 \frac{\partial \vec{y}_{3}}{\partial W_{7,8}}=0。 W7,8y 3=0然而, y ⃗ 3 \vec{y}_{3} y 3关于 W W W的第3列的元素的导数肯定是非零的。 例如, y ⃗ 3 \vec{y}_{3} y 3相对于W_{2,3}的导数由下式给出
(6) ∂ y ⃗ 3 ∂ W 2 , 3 = x ⃗ 2 , \frac{\partial \vec{y}_{3}}{\partial W_{2,3}}=\vec{x}_{2}\tag{6}, W2,3y 3=x 2(6)通过检查公式 ( 5 ) (5) (5)可以很容易地看出。
  通常,当 y ⃗ \vec{y} y 分量的下标等于 W W W的第二下标时,导数将为非零,否则将为零。 即:
∂ y ⃗ j ∂ W i , j = x ⃗ i , \frac{\partial \vec{y}_{j}}{\partial W_{i,j}}=\vec{x}_{i}, Wi,jy j=x i但是该三维数组的其他元素将为0.令 F F F表示代表 y ⃗ \vec{y} y 相对于 W W W的导数的三维数组,其中
F i , j , k = ∂ y ⃗ i ∂ W j , k , F_{i,j,k}=\frac{\partial \vec{y}_{i}}{\partial W_{j,k}}, Fi,j,k=Wj,ky i
F i , j , i = x ⃗ j , F_{i,j,i}=\vec{x}_{j}, Fi,j,i=x j但是 F F F的所有其他元素都是零。
  最后,如果我们将一个新的二维数组 G G G定义为
G i , j = F i , j , i , G_{i,j}=F_{i,j,i}, Gi,j=Fi,j,i我们可以看到,我们需要的关于 F F F的所有信息都可以存储在 G G G中,并且 F F F的非平凡部分实际上是二维的,而不是三维的。
  以紧凑的方式表示导数阵列的重要部分对于神经网络的有效实现是至关重要的。

4 多个数据点

重复一些前面的例子是一个很好的练习,但是我们可以使用 x ⃗ \vec{x} x 的多个例子,堆叠在一起形成矩阵 X X X.假设每个 x ⃗ \vec{x} x 都是长度为 D D D的行向量,而 X X X是二维的、具有 N N N D D D列的数组。 W W W,如在我们的上一个示例中,将是具有 D D D行和 C C C列的矩阵。 Y Y Y,由下式给出
Y = X W , Y=XW, Y=XW也将是一个矩阵,有 N N N行和 C C C列。 因此, Y Y Y的每一行将给出与输入 X X X的相应行相关联的行向量。
  坚持之前为输出的给定部分写下表达式的操作,我们有
Y i , j = ∑ k = 1 D X i , k W k , j 。 Y_{i,j}=\sum_{k=1}^{D}{X_{i,k}W_{k,j}}。 Yi,j=k=1DXi,kWk,j我们可以从这个等式中直接看出导数
∂ Y a , b ∂ X c , d , \frac{\partial Y_{a,b}}{\partial X_{c,d}}, Xc,dYa,b除非 a = c a = c a=c,否则它们都为零。 也就是说,由于 Y Y Y的每个分量仅使用相应的 X X X行来计算,因此 Y Y Y X X X的不同行之间的分量的导数都是零。
  此外,我们可以知道
(7) ∂ Y i , j ∂ X i , k = W k , j , \frac{\partial Y_{i,j}}{\partial X_{i,k}}=W_{k,j}\tag{7}, Xi,kYi,j=Wk,j(7)并不完全取决于我们正在比较的 Y Y Y X X X的行。
  事实上,矩阵 W W W保持所有这些部分——我们只需要根据等式 ( 7 ) (7) (7)索引,来获得我们想要的特定偏导数。
  如果我们让 Y i , : Y_{i,:} Yi,:成为 Y Y Y的第i行,让 X i , : X_{i,:} Xi,:成为 X X X的第i行,那么我们得到
∂ Y i , : ∂ X i , : = W , \frac{\partial Y_{i,:}}{\partial X_{i,:}}=W, Xi,:Yi,:=W这是我们先前从公式 ( 4 ) (4) (4)得到的结果的简单推广。

5 链式法则与向量和矩阵相结合

现在我们已经完成了几个基本的例子,让我们将这些想法与链式法则的例子结合起来。 同样,假设 y ⃗ \vec{y} y x ⃗ \vec{x} x 是列向量,让我们从这个等式开始
y ⃗ = V W x ⃗ , \vec{y}=VW\vec{x}, y =VWx 并尝试计算 y ⃗ \vec{y} y 相对于 x ⃗ \vec{x} x 的导数。 我们可以简单地观察到两个矩阵 V V V W W W的乘积是另一个矩阵,令之为 U U U,因此
d y ⃗ d x ⃗ = V W = U 。 \frac{\mathrm{d} \vec{y}}{\mathrm{d} \vec{x}}=VW=U。 dx dy =VW=U但是,我们想通过使用链式法则来定义中间结果,这样我们就可以看到链式法则如何应用于非标量导数的情况下的过程。
  定义中间结果为
m ⃗ = W x ⃗ 。 \vec{m}=W\vec{x}。 m =Wx 则我们有
y ⃗ = V m ⃗ 。 \vec{y}=V\vec{m}。 y =Vm 运用链式法则,可以进一步得到
d y ⃗ d x ⃗ = d y ⃗ d m ⃗ d m ⃗ d x ⃗ 。 \frac{\mathrm{d} \vec{y}}{\mathrm{d} \vec{x}}=\frac{\mathrm{d} \vec{y}}{\mathrm{d} \vec{m}}\frac{\mathrm{d} \vec{m}}{\mathrm{d} \vec{x}}。 dx dy =dm dy dx dm   为了确保我们确切地知道这能给我们带来什么,让我们采用分析单个元素的老方法,从 y ⃗ \vec{y} y 的单个元素和 x ⃗ \vec{x} x 的单个元素开始:
d y ⃗ i d x ⃗ j = d y ⃗ i d m ⃗ d m ⃗ d x ⃗ j 。 \frac{\mathrm{d} \vec{y}_{i}}{\mathrm{d} \vec{x}_{j}}=\frac{\mathrm{d} \vec{y}_{i}}{\mathrm{d} \vec{m}}\frac{\mathrm{d} \vec{m}}{\mathrm{d} \vec{x}_{j}}。 dx jdy i=dm dy idx jdm   但是我们究竟应该如何解释右边的乘积呢? 链式法则的含义是将 y ⃗ i \vec{y}_{i} y i相对于每个标量中间变量的变化乘以每个标量中间变量相对于 x ⃗ j \vec{x}_{j} x j的变化。 特别是,如果 m ⃗ \vec{m} m M M M个元素,那么我们可以改写
d y ⃗ i d x ⃗ j = ∑ k = 1 M d y ⃗ i d m ⃗ k d m ⃗ k d x ⃗ j 。 \frac{\mathrm{d} \vec{y}_{i}}{\mathrm{d} \vec{x}_{j}}=\sum_{k=1}^{M}{\frac{\mathrm{d} \vec{y}_{i}}{\mathrm{d} \vec{m}_{k}}\frac{\mathrm{d} \vec{m}_{k}}{\mathrm{d} \vec{x}_{j}}}。 dx jdy i=k=1Mdm kdy idx jdm k  回想一下我们之前关于矢量导数的结果:
d y ⃗ i d m ⃗ k \frac{\mathrm{d} \vec{y}_{i}}{\mathrm{d} \vec{m}_{k}} dm kdy i就是 V i , k V_{i,k} Vi,k,且
d m ⃗ k d x ⃗ j \frac{\mathrm{d} \vec{m}_{k}}{\mathrm{d} \vec{x}_{j}} dx jdm k就是 W k , j W_{k,j} Wk,j。所以我们可以得出
d y ⃗ i d x ⃗ j = ∑ k = 1 M V i , k W k , j , \frac{\mathrm{d} \vec{y}_{i}}{\mathrm{d} \vec{x}_{j}}=\sum_{k=1}^{M}{V_{i,k}W_{k,j}}, dx jdy i=k=1MVi,kWk,j也即是 V W VW VW的表达式,或者说是我们对问题的原始答案。
  总而言之,我们可以在矢量和矩阵的导数求解中按照以下步骤使用链式法则:

  •清楚地说明中间结果和用于表示它们的变量,

  •按照链式法则将最终所求导数写成各项乘积的表达式,

  •对链式法则表达式中的中间结果进行适当的运算。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值