动手学深度学习笔记(一)

矩阵计算


1. 标量导数

一般的标量导数表示切线的斜率

2. 亚导数

将导数拓展到不可微的函数。在函数的不可导点,将导数(斜率)取为一个范围内的任意值。

如,对于函数:
y = ∣ x ∣ y=|x| y=x

其导数可以记为:
∂ ∣ x ∣ ∂ x = { 1 i f   x > 0 − 1 i f   x < 0 a i f   x = 0 , a ∈ [ − 1 , 1 ] \frac{\partial |x|}{\partial x}= \begin{cases} 1 & if\ x>0 \\ -1 & if\ x<0 \\ a & if\ x=0,a\in [-1,1] \end{cases} xx=11aif x>0if x<0if x=0,a[1,1]

函数 max ⁡ ( x , 0 ) \max{(x,0)} max(x,0) 的导数可以记为:
∂ max ⁡ ( x , 0 ) ∂ x = { 1 i f   x > 0 0 i f   x < 0 a i f   x = 0 , a ∈ [ − 1 , 1 ] \frac{\partial \max{(x,0)}}{\partial x}= \begin{cases} 1 & if\ x>0 \\ 0 & if\ x<0 \\ a & if\ x=0,a\in [-1,1] \end{cases} xmax(x,0)=10aif x>0if x<0if x=0,a[1,1]

3. 梯度

导数在向量的拓展。

\quad 标量 x x x向量 x \boldsymbol{x} x
标量 y y y ∂ y ∂ x ( 标 量 ) \frac{\partial y}{\partial x}(标量) xy ∂ y ∂ x ( 行 向 量 ) \frac{\partial y}{\partial \boldsymbol{x}}(行向量) xy
向量 y \boldsymbol{y} y ∂ y ∂ x ( 列 向 量 ) \frac{\partial \boldsymbol{y}}{\partial x}(列向量) xy ∂ y ∂ x ( 矩 阵 ) \frac{\partial \boldsymbol{y}}{\partial \boldsymbol{x}}(矩阵) xy
  1. y y y 是标量, x = [ x 1 x 2 ⋮ x n ] \boldsymbol{x}=\left[\begin{matrix} x_1 \\ x_2 \\\vdots \\x_n \end{matrix}\right] x=x1x2xn 是向量,梯度按照如下方法计算,标量相对于一个列向量的导数是一个行向量(分子布局法),所以下面的计算都要转置。
    ∂ y ∂ x = [ ∂ y ∂ x 1 , ∂ y ∂ x 2 , ⋯   , ∂ y ∂ x n ] \frac{\partial y}{\partial \boldsymbol{x}} = \left[\begin{matrix} \dfrac{\partial y}{\partial x_1}, & \dfrac{\partial y}{\partial x_2}, & \cdots, & \dfrac{\partial y}{\partial x_n} \end{matrix}\right] xy=[x1y,x2y,,xny]

    如,对于 y = x 1 2 + 2 x 2 2 y=x_1^2 + 2x_2^2 y=x12+2x22,梯度 ∂ y ∂ x = [ 2 x 1 , 4 x 2 ] \frac{\partial y}{\partial{\boldsymbol{x}}}=\left[\begin{matrix}2x_1,4x_2\end{matrix}\right] xy=[2x1,4x2]

    一些梯度的计算:

    y s u m ( x ) sum(\boldsymbol{x}) sum(x) ∥ x ∥ 2 \|x\|^2 x2 ⟨ u , v ⟩ \langle \boldsymbol{u},\boldsymbol{v}\rangle u,v
    ∂ y ∂ x \dfrac{\partial y}{\partial{\boldsymbol{x}}} xy 1 T \boldsymbol{1}^T 1T 2 x T 2\boldsymbol{x}^T 2xT u T ∂ v ∂ x + v T ∂ u ∂ x \boldsymbol{u}^T\frac{\partial \boldsymbol{v}}{\partial \boldsymbol{x}}+\boldsymbol{v}^T\frac{\partial \boldsymbol{u}}{\partial \boldsymbol{x}} uTxv+vTxu
  2. y = [ y 1 y 2 ⋮ y m ] \boldsymbol{y}=\left[\begin{matrix} y_1 \\ y_2 \\\vdots \\y_m \end{matrix}\right] y=y1y2ym 是矩阵, x x x 是一个标量,计算梯度的方式如下,得到的是一个列向量(分子布局法)。
    ∂ y ∂ x = [ ∂ y 1 ∂ x ∂ y 2 ∂ x ⋮ ∂ y m ∂ x ] \frac{\partial \boldsymbol{y}}{\partial x}= \left[\begin{matrix} \dfrac{\partial y_1}{\partial x} \\ \dfrac{\partial y_2}{\partial x} \\ \vdots \\ \dfrac{\partial y_m}{\partial x} \end{matrix}\right] xy=xy1xy2xym

  3. 对于向量 x = [ x 1 x 2 ⋮ x n ] \boldsymbol{x}=\left[\begin{matrix} x_1 \\ x_2 \\\vdots \\x_n \end{matrix}\right] x=x1x2xn 与向量 y = [ y 1 y 2 ⋮ y m ] \boldsymbol{y}=\left[\begin{matrix} y_1 \\ y_2 \\\vdots \\y_m \end{matrix}\right] y=y1y2ym,其求梯度的方式如下,最终得到一个矩阵。
    ∂ y ∂ x = [ ∂ y 1 ∂ x ∂ y 2 ∂ x ⋮ ∂ y m ∂ x ] = [ ∂ y 1 ∂ x 1 , ∂ y 1 ∂ x 2 , ⋯   , ∂ y 1 ∂ x n ∂ y 2 ∂ x 1 , ∂ y 2 ∂ x 2 , ⋯   , ∂ y 2 ∂ x n ⋮ ∂ y m ∂ x 1 , ∂ y m ∂ x 2 , ⋯   , ∂ y m ∂ x n ] \frac{\partial \boldsymbol{y}}{\partial \boldsymbol{x}}= \left[\begin{matrix} \dfrac{\partial y_1}{\partial \boldsymbol{x}} \\ \dfrac{\partial y_2}{\partial \boldsymbol{x}} \\ \vdots \\ \dfrac{\partial y_m}{\partial \boldsymbol{x}} \end{matrix}\right]= \left[\begin{matrix} \dfrac{\partial y_1}{\partial x_1}, & \dfrac{\partial y_1}{\partial x_2}, & \cdots, & \dfrac{\partial y_1}{\partial x_n} \\ \dfrac{\partial y_2}{\partial x_1}, & \dfrac{\partial y_2}{\partial x_2}, & \cdots, & \dfrac{\partial y_2}{\partial x_n} \\ &\vdots && \\ \dfrac{\partial y_m}{\partial x_1}, & \dfrac{\partial y_m}{\partial x_2}, & \cdots, & \dfrac{\partial y_m}{\partial x_n} \end{matrix}\right] xy=xy1xy2xym=x1y1,x1y2,x1ym,x2y1,x2y2,x2ym,,,,xny1xny2xnym

y \boldsymbol{y} y x \boldsymbol{x} x A x \boldsymbol{Ax} Ax x T A \boldsymbol{x}^T\boldsymbol{A} xTA a u a\boldsymbol{u} au A u \boldsymbol{Au} Au
∂ y ∂ x \dfrac{\partial \boldsymbol{y}}{\partial{\boldsymbol{x}}} xy I \boldsymbol{I} I A \boldsymbol{A} A A T \boldsymbol{A}^T AT a ∂ u ∂ x a\dfrac{\partial \boldsymbol{u}}{\partial \boldsymbol{x}} axu A ∂ u ∂ x \boldsymbol{A}\dfrac{\partial \boldsymbol{u}}{\partial \boldsymbol{x}} Axu
  • a a a a \boldsymbol{a} a A \boldsymbol{A} A 中都不包含 x \boldsymbol{x} x

相关链接:

  1. 矩阵求导的本质与分子布局、分母布局的本质(矩阵求导——本质篇)
  2. 矩阵求导公式的数学推导(矩阵求导——基础篇)
  3. 矩阵求导公式的数学推导(矩阵求导——进阶篇)

4. 向量链式法则

  • 标量的链式法则:

    y = f ( u ) , u = g ( x ) y=f(u),u=g(x) y=f(u),u=g(x),则 y y y 相对于 x x x 的导数可以表示为:
    ∂ y ∂ x = ∂ y ∂ u ∂ u ∂ x \frac{\partial y}{\partial x}=\frac{\partial y}{\partial u}\frac{\partial u}{\partial x} xy=uyxu

  • 向量的链式求导法则:

    类型求导
    y y y 是标量, u u u 是标量, x \boldsymbol{x} x 是向量 ∂ y ∂ x ( 1 , n ) = ∂ y ∂ u ( 1 , ) ∂ u ∂ x ( 1 , n ) \underset{(1,n)}{\dfrac{\partial y}{\partial \boldsymbol{x}}}= \underset{(1,)}{\dfrac{\partial y}{\partial u}} \underset{(1,n)}{\dfrac{\partial u}{\partial \boldsymbol{x}}} (1,n)xy=(1,)uy(1,n)xu
    y y y 是标量, u \boldsymbol{u} u 是向量, x \boldsymbol{x} x 是向量 ∂ y ∂ x ( 1 , n ) = ∂ y ∂ u ( 1 , k ) ∂ u ∂ x ( k , n ) \underset{(1,n)}{\dfrac{\partial y}{\partial \boldsymbol{x}}}= \underset{(1,k)}{\dfrac{\partial y}{\partial \boldsymbol{u}}} \underset{(k,n)}{\dfrac{\partial \boldsymbol{u}}{\partial \boldsymbol{x}}} (1,n)xy=(1,k)uy(k,n)xu
    y \boldsymbol{y} y 是向量, u \boldsymbol{u} u 是向量, x \boldsymbol{x} x 是向量 ∂ y ∂ x ( m , n ) = ∂ y ∂ u ( 1 , k ) ∂ u ∂ x ( k , n ) \underset{(m,n)}{\dfrac{\partial \boldsymbol{y}}{\partial \boldsymbol{x}}}= \underset{(1,k)}{\dfrac{\partial \boldsymbol{y}}{\partial \boldsymbol{u}}} \underset{(k,n)}{\dfrac{\partial \boldsymbol{u}}{\partial \boldsymbol{x}}} (m,n)xy=(1,k)uy(k,n)xu

例子:

  • 对于一个表达式 z = ( ⟨ x , w ⟩ − y ) 2 z=(\langle \boldsymbol{x},\boldsymbol{w}\rangle - y)^2 z=(x,wy)2,其中 x , w ∈ R n , y ∈ R \boldsymbol{x},\boldsymbol{w}\in \mathbb{R}^n,y\in\mathbb{R} x,wRn,yR,计算 ∂ z ∂ w \dfrac{\partial z}{\partial \boldsymbol{w}} wz 的过程如下:

    1. 首先将其中的变量求导,记 a = ⟨ x , w ⟩ , b = a − y , z = b 2 a=\langle \boldsymbol{x},\boldsymbol{w}\rangle,\quad b=a-y,\quad z=b^2 a=x,w,b=ay,z=b2

    2. 使用链式求导对每个中间变量求导
      ∂ z ∂ w = ∂ z ∂ b ∂ b ∂ a ∂ a ∂ w = ∂ b 2 ∂ b ∂ ( a − y ) ∂ a ∂ ⟨ x , w ⟩ ∂ w = 2 b ⋅ 1 ⋅ x T = 2 ( ⟨ x , w ⟩ − y ) x T \begin{aligned} \dfrac{\partial z}{\partial \boldsymbol{w}} & = \dfrac{\partial z}{\partial b}\dfrac{\partial b}{\partial a}\dfrac{\partial a}{\partial \boldsymbol{w}} \\ & = \dfrac{\partial b^2}{\partial b}\dfrac{\partial (a-y)}{\partial a}\dfrac{\partial \langle \boldsymbol{x},\boldsymbol{w}\rangle}{\partial \boldsymbol{w}} \\ & = 2b \cdot 1 \cdot \boldsymbol{x}^T \\ & = 2(\langle \boldsymbol{x},\boldsymbol{w}\rangle -y)\boldsymbol{x}^T \end{aligned} wz=bzabwa=bb2a(ay)wx,w=2b1xT=2(x,wy)xT

5. 自动求导

自动求导是计算一个函数在指定值上的导数,即对于一个 y = f ( x ) y=f(x) y=f(x) 的表达式,对于某一个 x = c x=c x=c f ′ ( c ) f'(c) f(c) 的值是什么。

自动求导是根据计算图进行详细计算的,也就是给定一个表达式:

  1. 首先将该表达式分解成一个一个的操作子
  2. 使用操作子就可以将整个表达式表示为一个无环图

如,对于上面例子的表达式, z = ( ⟨ x , w ⟩ − y ) 2 z=(\langle \boldsymbol{x},\boldsymbol{w}\rangle - y)^2 z=(x,wy)2 a , b , z a,b,z a,b,z 就算单个的计算子,它们可以构成如下的计算图,其中每个圈表示一个表达式或输入。
在这里插入图片描述

构造出计算图后,根据链式求导法则:
∂ y ∂ x = ∂ y ∂ u n ∂ u n ∂ u n − 1 ⋯ ∂ u 2 ∂ u 1 ∂ u 1 ∂ x \dfrac{\partial y}{\partial x}=\dfrac{\partial y}{\partial u_n}\dfrac{\partial u_n}{\partial u_{n-1}}\cdots\dfrac{\partial u_2}{\partial u_{1}}\dfrac{\partial u_1}{\partial x} xy=unyun1unu1u2xu1

可以通过如下两种方式实现自动求导:

  1. 正向累积。先计算 ∂ u 1 ∂ x \dfrac{\partial u_1}{\partial x} xu1 ,再计算 ∂ u 2 ∂ u 1 \dfrac{\partial u_2}{\partial u_1} u1u2,之后依次向前计算
    ∂ y ∂ x = ∂ y ∂ u n ( ∂ u n ∂ u n − 1 ( ⋯ ( ∂ u 2 ∂ u 1 ∂ u 1 ∂ x ) ) ) \dfrac{\partial y}{\partial x}= \dfrac{\partial y}{\partial u_n} \left(\dfrac{\partial u_n}{\partial u_{n-1}} \left(\cdots \left(\dfrac{\partial u_2}{\partial u_{1}} \dfrac{\partial u_1}{\partial x} \right)\right)\right) xy=uny(un1un((u1u2xu1)))

    正向累计可以根据计算图,从下向上依次计算每个结点相对于下一个参数的导数。

  2. 反向累积(反向传播)。先计算 ∂ y ∂ u n \dfrac{\partial y}{\partial u_n} uny ,再计算 ∂ u n ∂ u n − 1 \dfrac{\partial u_n}{\partial u_{n-1}} un1un,之后依次向后计算。
    ∂ y ∂ x = ( ( ( ∂ y ∂ u n ∂ u n ∂ u n − 1 ) ⋯   ) ∂ u 2 ∂ u 1 ) ∂ u 1 ∂ x \dfrac{\partial y}{\partial x}=\left(\left( \left(\dfrac{\partial y}{\partial u_n} \dfrac{\partial u_n}{\partial u_{n-1}}\right) \cdots\right) \dfrac{\partial u_2}{\partial u_{1}}\right) \dfrac{\partial u_1}{\partial x} xy=(((unyun1un))u1u2)xu1

    反向累积需要根据计算图从上向下依次求导,求导过程中需要将正向计算中的结果拿来构成每个结点的求导结果并保存为中间结果。如下所示:
    在这里插入图片描述

  • 反向累积中,计算复杂度为 O ( n ) O(n) O(n),内存复杂度为 O ( n ) O(n) O(n),因为要存储正向的所有中间结果,所以更加耗费资源。
  • 正向累积中,计算一个变量的时间复杂度为 O ( n ) O(n) O(n)(即从下向上扫一遍),对于多个变量的计算会使计算复杂度非常大。内存复杂度为 O ( 1 ) O(1) O(1),不需要保存中间的结果。

6. PyTorch 自动求导

  • 若要计算 y = 2 x T x y=2\mathbf{x}^T\mathbf{x} y=2xTx 关于行向量 x \mathbf{x} x 的导数,可以通过如下步骤。

    1. 构造 x \mathbf{x} x 向量,并指定在 x.grad 中保存计算出来的梯度

      # 1. 先创建 x ,再指定 x 可以求导
      >>> x = torch.arange(4.0)
      >>> x
      tensor([0., 1., 2., 3.])
      >>> x.requires_grad_(True)
      tensor([0., 1., 2., 3.], requires_grad=True)
      >>> x.grad     #默认为 None
      
      # 2. 在创建 x 同时指定 x 可以求导
      >>> x = torch.arange(4.0, requires_grad=True)
      >>> x
      tensor([0., 1., 2., 3.], requires_grad=True)
      >>> x.grad     #默认为 None
      
    2. 利用 x \mathbf{x} x 计算 y y y

      >>> y = 2 * torch.dot(x,x)           #计算内积
      >>> y
      tensor(28., grad_fn=<MulBackward0>)  #grad_fn 保存 y 的运算信息,表明 y 是由 x 构建的
      >>> y.grad_fn
      <MulBackward0 object at 0x00000211287EEFD0>
      
    3. 调用反向传播函数 y.backward() 自动计算 y y y 关于 x \mathbf{x} x 每个分量的梯度

      >>> y.backward()
      >>> x.grad
      tensor([ 0.,  4.,  8., 12.])
      
      >>> x.grad == 4 * x
      tensor([True, True, True, True])
      

    其计算的本质就是构造出 y = f ( x ) y=f(x) y=f(x) 的表达式,上式为 y = 2 ( x 1 2 + x 2 2 + x 3 2 + x 4 2 ) y=2(x_1^2 + x_2^2 + x_3^2 + x_4^2) y=2(x12+x22+x32+x42) ,之后将向量 x \boldsymbol{x} x 中的每个值都带入计算,得到 x = [ x 1 , x 2 , ⋯   , x n ] \boldsymbol{x}=\left[\begin{matrix}x_1,x_2,\cdots,x_n\end{matrix}\right] x=[x1,x2,,xn] 中每个位置的变量对应的求导公式 y ′ = f ′ ( x ) = [ f ′ ( x 1 ) , f ′ ( x 2 ) , ⋯   , f ′ ( x n ) ] = [ 4 x 1 2 , 4 x 2 2 , 4 x 3 2 , 4 x 4 2 ] y'=f'(\boldsymbol{x})=\left[\begin{matrix}f'(x_1),f'(x_2),\cdots,f'(x_n)\end{matrix}\right]=\left[\begin{matrix} 4x_1^2,4x_2^2,4x_3^2,4x_4^2\end{matrix}\right] y=f(x)=[f(x1),f(x2),,f(xn)]=[4x12,4x22,4x32,4x42],再将值带入对应位置。

  • 下面展示了计算 x x x 的累加和的梯度

    在默认情况下,PyTorch 会 累加梯度,使用 x.grad.zero_() 可以清除之前的值

    >>> x.grad.zero_()
    tensor([0., 0., 0., 0.])
    >>> x.grad
    tensor([0., 0., 0., 0.])
    
    >>> y = x.sum()
    >>> y.backward()
    >>> x.grad
    tensor([1., 1., 1., 1.])
    
  • 使用 y.backward() 计算梯度时必须保证 y 是一个标量,在数学上是不允许对非标量求导的,如下所示,一般情况下我们首先对 y 求和,求和之后是一个标量,再进行求导。

    >>> x.grad.zero_()
    >>> y = x *x
    >>> y.backward()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "D:\Applications\Anaconda\lib\site-packages\torch\tensor.py", line 221, in backward
        torch.autograd.backward(self, gradient, retain_graph, create_graph)
      File "D:\Applications\Anaconda\lib\site-packages\torch\autograd\__init__.py", line 126, in backward
        grad_tensors_ = _make_grads(tensors, grad_tensors_)
      File "D:\Applications\Anaconda\lib\site-packages\torch\autograd\__init__.py", line 50, in _make_grads
        raise RuntimeError("grad can be implicitly created only for scalar outputs")
    RuntimeError: grad can be implicitly created only for scalar outputs
    
    >>> y.sum().backward()
    >>> x.grad
    tensor([0., 2., 4., 6.])
    
  • 将某些计算移动到记录的计算图之外,即通过 y.detach() 命令使得中间变量 y y y 成为一个常数,对于包含 y y y 的表达式,当计算梯度时候会将 y y y 视为常数

    #1. 对 y 执行 detach()
    >>> x.grad.zero_()
    tensor([0., 0., 0., 0.])
    >>> y = x * x
    >>> u = y.detach()
    >>> z = u * x
    >>> z.sum().backward()
    
    >>> x.grad == u
    tensor([True, True, True, True])
    >>> x.grad
    tensor([0., 1., 4., 9.])
    
    #2. 不对 y 执行 detach()
    >>> x.grad.zero_()
    tensor([0., 0., 0., 0.])
    >>> y = x * x
    >>> z = y * x
    >>> z.sum().backward()
    >>> x.grad
    tensor([ 0.,  3., 12., 27.])
    
    #3. 因为 y 是 x 的函数,所以直接对 y 进行梯度求解没有影响,但是不能对 u 求导
    >>> x.grad.zero_()
    tensor([0., 0., 0., 0.])
    >>> y.sum().backward()
    >>> x.grad
    tensor([0., 2., 4., 6.])
    
    >>> u.sum().backward()
    RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn
    
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 动手深度学习v2是一本非常好的深度学习教材,是从谷歌机器习研究员李沐所主持的Gluon团队创作的。它提供了丰富的案例和实际应用,深入浅出地介绍了深度学习的基础理论和实践技能。 下载动手深度学习v2非常简单,可以通过访问官方网站来获取。首先,打开谷歌或百度搜索引擎,搜索"动手深度学习v2下载",就可以找到相关的下载链接。建议选择官网下载,因为官网下载最为安全可靠。 进入官网后,点击首页上的"下载"按钮,然后在目录下找到本书的下载链接,下载适合你的版本即可。此外,动手深度学习v2还有在线阅读的版本,方便习者随时随地习。 总的来说,动手深度学习v2是一本非常优秀的深度学习教材,相关下载链接也十分便捷,能够帮助广大习者更好地掌握深度学习相关的知识和技能。 ### 回答2: 动手深度学习v2是一本非常优秀的深度学习入门书籍,笔者十分推荐。如果您想要下载该书籍,可以使用以下方法: 1.进入动手深度学习v2的官网(https://zh.d2l.ai/),点击右上角的“Github”按钮,进入书籍的Github仓库。 2.在仓库中找到“releases”目录,选择最新的版本号,点击进入。 3.在该版本的页面中,找到“Source code (zip)”或“Source code (tar.gz)”选项,点击下载压缩包。 4.下载完成后,解压缩文件即可得到电子书的文件夹,其中包括PDF和HTML格式的书籍。 除此之外,您也可以在该官网中找到由中文社区翻译的在线电子书版本。在该电子书中,您可以直接在线阅读和习。值得注意的是,该书籍的在线翻译版本可能会比英文原版稍有滞后。如果您想要阅读最新的内容,请下载英文原版或者在该官网上查看最新的更新。 ### 回答3: 深度学习是现在的热门话题之一。而动手深度学习v2是一本非常好的深度学习教材,旨在为做实际项目的习者提供知识技能和实战经验。为了下载此书,您需要按照以下步骤进行。 首先,您需要访问动手深度学习官方网站,网址为d2l.ai。然后,您需要找到下载页面,这个页面可以通过页面上的“全书下载”按钮或主页面上的一个标签来访问。 在下载页面,您需要选择您所需要的版本,v2版本是最新版本。接着,您需要选择您所需的格式。您可以选择PDF格式或HTML格式,下方还提供了在线阅读链接。 若您选择了PDF格式,则需要点击下载链接,页面会跳到GitHub仓库中。在GitHub页面,您需要选择ZIP文件并下载。下载完成后,您就可以在本地解压并阅读这本书了。 若您选择了HTML格式,则不需下载,只需点击在线阅读链接即可。页面会跳转到包含书籍所有章节、实例代码、作者笔记等信息的HTML页面,您可以任意阅读或者下载章节(在左侧点击对应章节)。 总之,动手深度学习v2是一本亲身实践的深度学习教材,其深入浅出的讲解以及丰富的实战案例,能够帮助初者快速掌握深度学习这一技术,同时也是深度学习领域专业人士的必备读物。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值