深度学习详细笔记 (通俗易懂,这一篇就够了 )--深度学习模型的结构与优化(5)

深度L层神经网络 (Deep L-layer neural network)

要理解深度神经网络,我们可以想象它就像是建筑的多层楼房。越多的层就意味着这座楼房越高,同样地,神经网络里有越多的隐藏层就意味着它越“深”。上面的图片很好地展示了不同“楼层”数量的神经网络模型,从简单的地面楼(逻辑回归)到拥有多层的大厦。

你可能会问,为什么我们不直接说有5层或者6层呢?这是因为在神经网络的命名规则中,我们通常不把输入层算作一层。所以,当我们说2层神经网络的时候,它实际上有一个输入层和一个隐藏层,然后是输出层。这个命名规则其实是为了方便,因为当我们谈论网络的“深度”时,我们真正关心的是隐藏层的数量。

现在,让我们深入研究一下一个4层神经网络的结构。想象一下,这个网络就像是一个4层的楼房。 L L L 代表楼的总层数,这里 L = 4 L=4 L=4。我们的输入层是底楼,记为第0层,而最顶层,也就是输出层,是第L层。每一层楼有不同数量的房间,这些“房间”在神经网络中就是神经元。第l层有 n [ l ] n[l] n[l] 个神经元,这里 l l l 的范围是从0到L。所以在这个模型中, n [ 0 ] = n x = 3 n[0] = nx = 3 n[0]=nx=3 意味着我们有三个输入特征,这三个特征就像是我们楼房的大门。而 n [ 1 ] = 5 n[1]=5 n[1]=5, n [ 2 ] = 5 n[2]=5 n[2]=5, n [ 3 ] = 3 n[3]=3 n[3]=3 n [ 4 ] = 1 n[4]=1 n[4]=1 则是随着楼层递增的房间数量。

每个房间都有灯光,这个“灯光”可以暗或亮,代表神经元的激活函数输出,我们用 a [ l ] a[l] a[l] 来表示它。权重 W [ l ] W[l] W[l] 就像是楼层之间的电梯,它决定了我们从一层到另一层时“灯光”的变化程度。

这样,不管你是神经网络的初学者,还是有经验的专家,都能很容易地理解这个复杂的结构了。

深度网络中的正向传播 (Forward Propagation in a Deep Network)

深层神经网络的正向传播可以被想象成一个复杂的信息高速公路,信息在各个层之间高速流动。为了更容易理解,我们还是用上面的4层神经网络作为例子来说明。

首先,对于单个样本:

  • 在第1层(也就是底楼):
    z [ 1 ] = W [ 1 ] x + b [ 1 ] = W [ 1 ] a [ 0 ] + b [ 1 ] z^{[1]} = W^{[1]}x + b^{[1]} = W^{[1]}a^{[0]} + b^{[1]} z[1]=W[1]x+b[1]=W[1]a[0]+b[1]
    这里, a [ 0 ] a^{[0]} a[0] 就是输入特征,而 g [ 1 ] ( z [ 1 ] ) g^{[1]}(z^{[1]}) g[1](z[1]) 则是激活函数输出的值,我们可以表示为 a [ 1 ] a^{[1]} a[1]

  • 在第2层(第一个隐藏层):
    z [ 2 ] = W [ 2 ] a [ 1 ] + b [ 2 ] z^{[2]} = W^{[2]}a^{[1]} + b^{[2]} z[2]=W[2]a[1]+b[2]
    同样地, a [ 2 ] = g [ 2 ] ( z [ 2 ] ) a^{[2]} = g^{[2]}(z^{[2]}) a[2]=g[2](z[2])

  • 在第3层(第二个隐藏层):
    z [ 3 ] = W [ 3 ] a [ 2 ] + b [ 3 ] z^{[3]} = W^{[3]}a^{[2]} + b^{[3]} z[3]=W[3]a[2]+b[3]
    并且, a [ 3 ] = g [ 3 ] ( z [ 3 ] ) a^{[3]} = g^{[3]}(z^{[3]}) a[3]=g[3](z[3])

  • 最后,在第4层(输出层):
    z [ 4 ] = W [ 4 ] a [ 3 ] + b [ 4 ] z^{[4]} = W^{[4]}a^{[3]} + b^{[4]} z[4]=W[4]a[3]+b[4]
    输出 a [ 4 ] = g [ 4 ] ( z [ 4 ] ) a^{[4]} = g^{[4]}(z^{[4]}) a[4]=g[4](z[4]) 就是神经网络预测的结果。

现在,假设我们不仅有一个样本,而是有整整m个样本。这时候,我们可以使用矩阵来表示所有样本的正向传播:

  • 在第1层:
    Z [ 1 ] = W [ 1 ] X + b [ 1 ] = W [ 1 ] A [ 0 ] + b [ 1 ] Z^{[1]} = W^{[1]}X + b^{[1]} = W^{[1]}A^{[0]} + b^{[1]} Z[1]=W[1]X+b[1]=W[1]A[0]+b[1]
    这里, A [ 1 ] = g [ 1 ] ( Z [ 1 ] ) A^{[1]} = g^{[1]}(Z^{[1]}) A[1]=g[1](Z[1])

  • 在第2层:
    Z [ 2 ] = W [ 2 ] A [ 1 ] + b [ 2 ] Z^{[2]} = W^{[2]}A^{[1]} + b^{[2]} Z[2]=W[2]A[1]+b[2]
    并且, A [ 2 ] = g [ 2 ] ( Z [ 2 ] ) A^{[2]} = g^{[2]}(Z^{[2]}) A[2]=g[2](Z[2])

  • 在第3层:
    Z [ 3 ] = W [ 3 ] A [ 2 ] + b [ 3 ] Z^{[3]} = W^{[3]}A^{[2]} + b^{[3]} Z[3]=W[3]A[2]+b[3]
    然后, A [ 3 ] = g [ 3 ] ( Z [ 3 ] ) A^{[3]} = g^{[3]}(Z^{[3]}) A[3]=g[3](Z[3])

  • 最后,在第4层:
    Z [ 4 ] = W [ 4 ] A [ 3 ] + b [ 4 ] Z^{[4]} = W^{[4]}A^{[3]} + b^{[4]} Z[4]=W[4]A[3]+b[4]
    输出 A [ 4 ] = g [ 4 ] ( Z [ 4 ] ) A^{[4]} = g^{[4]}(Z^{[4]}) A[4]=g[4](Z[4]) 就是神经网络基于所有m个样本的预测结果。

简而言之,无论是单个样本还是多个样本,第l层的正向传播都可以概括为以下两个公式:
Z [ l ] = W [ l ] A [ l − 1 ] + b [ l ] Z^{[l]} = W^{[l]}A^{[l-1]} + b^{[l]} Z[l]=W[l]A[l1]+b[l]
A [ l ] = g [ l ] ( Z [ l ] ) A^{[l]} = g^{[l]}(Z^{[l]}) A[l]=g[l](Z[l])
其中, l l l 取值范围是1到L。

确保矩阵维度正确 (Getting your matrix dimensions right)

在设计神经网络时,确保各种参数和变量的维度正确是至关重要的。否则,你的代码可能会因为维度不匹配而出错。为了帮助大家更好地理解,我们将通过以下内容逐步解析维度的规律。

首先,考虑单个训练样本的情况:

  • 输入 x x x 的维度是 ( n [ 0 ] , 1 ) (n^{[0]}, 1) (n[0],1),其中 n [ 0 ] n^{[0]} n[0] 表示输入层的特征数目。

  • 对于每一层 l l l 的参数 W [ l ] W^{[l]} W[l] b [ l ] b^{[l]} b[l],它们的维度如下:
    W [ l ] : ( n [ l ] , n [ l − 1 ] ) W^{[l]}: (n^{[l]}, n^{[l-1]}) W[l]:(n[l],n[l1])
    b [ l ] : ( n [ l ] , 1 ) b^{[l]}: (n^{[l]}, 1) b[l]:(n[l],1)

其中, n [ l ] n^{[l]} n[l] n [ l − 1 ] n^{[l-1]} n[l1] 分别代表第 l l l 层和 l − 1 l-1 l1 层的神经元数目。

再来看看正向传播中的 z [ l ] z^{[l]} z[l] a [ l ] a^{[l]} a[l],它们的维度如下:
z [ l ] : ( n [ l ] , 1 ) z^{[l]}: (n^{[l]}, 1) z[l]:(n[l],1)
a [ l ] : ( n [ l ] , 1 ) a^{[l]}: (n^{[l]}, 1) a[l]:(n[l],1)

它们的维度是一样的,这意味着 z [ l ] z^{[l]} z[l] a [ l ] a^{[l]} a[l] 可以直接进行计算。

好的,现在我们来看反向传播的部分。你会发现 d W [ l ] dW^{[l]} dW[l] d b [ l ] db^{[l]} db[l] 的维度与 W [ l ] W^{[l]} W[l] b [ l ] b^{[l]} b[l] 的维度完全相同:
d W [ l ] : ( n [ l ] , n [ l − 1 ] ) dW^{[l]}: (n^{[l]}, n^{[l-1]}) dW[l]:(n[l],n[l1])
d b [ l ] : ( n [ l ] , 1 ) db^{[l]}: (n^{[l]}, 1) db[l]:(n[l],1)

这其实很直观,因为我们在更新参数时需要确保 d W [ l ] dW^{[l]} dW[l] W [ l ] W^{[l]} W[l] 有相同的维度, d b [ l ] db^{[l]} db[l] b [ l ] b^{[l]} b[l] 也是如此。

现在,假设我们有 m m m 个训练样本。此时,输入矩阵 X X X 的维度就是 ( n [ 0 ] , m ) (n^{[0]}, m) (n[0],m)。但值得注意的是,不论样本数量是多少, W [ l ] W^{[l]} W[l] b [ l ] b^{[l]} b[l] 的维度都不会变。在计算 Z [ l ] = W [ l ] A [ l − 1 ] + b [ l ] Z^{[l]} = W^{[l]}A^{[l-1]} + b^{[l]} Z[l]=W[l]A[l1]+b[l] 时,因为 Python 的广播机制, b [ l ] b^{[l]} b[l] 会被看作 ( n [ l ] , m ) (n^{[l]}, m) (n[l],m) 维度的矩阵进行运算,且其每一列都相同。

最后,当我们有多个训练样本时, Z [ l ] Z^{[l]} Z[l] A [ l ] A^{[l]} A[l] 的维度都会变为:
Z [ l ] : ( n [ l ] , m ) Z^{[l]}: (n^{[l]}, m) Z[l]:(n[l],m)
A [ l ] : ( n [ l ] , m ) A^{[l]}: (n^{[l]}, m) A[l]:(n[l],m)

这些维度知识点非常重要,因为它们帮助我们在设计神经网络时确保所有的计算都能够正确进行。

4. 为什么选择深度表示? (Why deep representations?)

说到神经网络,我们经常听说它的强大功能,这其中很大一部分功劳归于它的"深度"结构。那么,为什么深层的神经网络会如此出色呢? 通过一些具体例子,我们来深入探讨一下。

想象一下,你正在看一张人脸图片。在第一层神经网络中,我们只是简单地识别出这张图片中的边缘和轮廓。往下一层看,神经网络开始识别出眼睛、鼻子和嘴巴等脸部的基本特征。再深入一些,我们可以看到神经网络已经能够识别出整张脸。也就是说,从简单的边缘,到局部特征,再到整体脸部,随着网络深度的增加,识别的特征越来越复杂。这正是深层网络的魔力所在:能够从简单特征构建出复杂特征。

类似地,在语音识别中,开始可能只是识别简单的音调,但随着网络深度的增加,我们可以识别到音素、单词,甚至整个短句。这个特点告诉我们,随着网络的加深,从简单到复杂的特征都可以被有效地学习和提取。

除了从功能角度看深层网络的优势,深度神经网络还有另一个明显的优点:效率。想象一下,我们有一个任务,用电路计算逻辑输出:
y = x 1 ⊕ x 2 ⊕ x 3 ⊕ ⋯ ⊕ x n y = x_1 \oplus x_2 \oplus x_3 \oplus \cdots \oplus x_n y=x1x2x3xn
其中, ⊕ \oplus 是异或操作。如果我们使用深层网络,每一层只进行前一层的两个输入的异或运算,最终的结果会是:
1 + 2 + ⋯ + 2 log ⁡ 2 ( n ) − 1 = 2 log ⁡ 2 ( n ) − 1 = n − 1 1+2+\cdots+2^{\log_2(n)-1} = 2^{\log_2(n)}-1 = n-1 1+2++2log2(n)1=2log2(n)1=n1
这意味着,对于 n n n个输入,深层网络只需要 n − 1 n-1 n1个神经元。相比之下,浅层网络可能需要指数级的神经元数量来实现相同的功能。

不过,尽管深度学习非常有吸引力,还是建议在实际问题上,先尝试简单的模型。只有当简单模型不能满足需求时,再考虑使用更复杂、更深层的模型。

4. 为什么选择深度表示? (Why deep representations?)

说到神经网络,我们经常听说它的强大功能,这其中很大一部分功劳归于它的"深度"结构。那么,为什么深层的神经网络会如此出色呢? 通过一些具体例子,我们来深入探讨一下。

想象一下,你正在看一张人脸图片。在第一层神经网络中,我们只是简单地识别出这张图片中的边缘和轮廓。往下一层看,神经网络开始识别出眼睛、鼻子和嘴巴等脸部的基本特征。再深入一些,我们可以看到神经网络已经能够识别出整张脸。也就是说,从简单的边缘,到局部特征,再到整体脸部,随着网络深度的增加,识别的特征越来越复杂。这正是深层网络的魔力所在:能够从简单特征构建出复杂特征。

类似地,在语音识别中,开始可能只是识别简单的音调,但随着网络深度的增加,我们可以识别到音素、单词,甚至整个短句。这个特点告诉我们,随着网络的加深,从简单到复杂的特征都可以被有效地学习和提取。

除了从功能角度看深层网络的优势,深度神经网络还有另一个明显的优点:效率。想象一下,我们有一个任务,用电路计算逻辑输出:
y = x 1 ⊕ x 2 ⊕ x 3 ⊕ ⋯ ⊕ x n y = x_1 \oplus x_2 \oplus x_3 \oplus \cdots \oplus x_n y=x1x2x3xn
其中, ⊕ \oplus 是异或操作。如果我们使用深层网络,每一层只进行前一层的两个输入的异或运算,最终的结果会是:
1 + 2 + ⋯ + 2 log ⁡ 2 ( n ) − 1 = 2 log ⁡ 2 ( n ) − 1 = n − 1 1+2+\cdots+2^{\log_2(n)-1} = 2^{\log_2(n)}-1 = n-1 1+2++2log2(n)1=2log2(n)1=n1
这意味着,对于 n n n个输入,深层网络只需要 n − 1 n-1 n1个神经元。相比之下,浅层网络可能需要指数级的神经元数量来实现相同的功能。

不过,尽管深度学习非常有吸引力,还是建议在实际问题上,先尝试简单的模型。只有当简单模型不能满足需求时,再考虑使用更复杂、更深层的模型。

5. 深度神经网络的构建块 (Building Blocks of Deep Neural Networks)

为了更清晰地理解深度学习,我们使用流程块图来描述神经网络中的正向传播和反向传播。想象一下,你正在建一座大楼,每一层楼都依赖于下面的楼层。这些楼层类似于神经网络中的层。

对于第 l l l层,正向传播是这样的:

  • 输入 a [ l − 1 ] a^{[l-1]} a[l1]
  • 输出 a [ l ] a^{[l]} a[l]
  • 参数 W [ l ] , b [ l ] W^{[l]}, b^{[l]} W[l],b[l]
  • 缓存变量 z [ l ] z^{[l]} z[l]

反向传播则是:

  • 输入 d a [ l ] da^{[l]} da[l]
  • 输出 d a [ l − 1 ] , d W [ l ] , d b [ l ] da^{[l-1]}, dW^{[l]}, db^{[l]} da[l1],dW[l],db[l]
  • 参数 W [ l ] , b [ l ] W^{[l]}, b^{[l]} W[l],b[l]

这就像是一座大楼的蓝图。不同的层有不同的输入和输出,它们都彼此连接。

6. 正向和反向传播 (Forward and Backward Propagation)

让我们深入研究每层如何工作。正向传播就像是将石头从山顶滚下来,每一层都会给石头增加一些速度和方向。

正向传播的表达式为:
z [ l ] = W [ l ] a [ l − 1 ] + b [ l ] z^{[l]} = W^{[l]} a^{[l-1]} + b^{[l]} z[l]=W[l]a[l1]+b[l]
a [ l ] = g [ l ] ( z [ l ] ) a^{[l]} = g^{[l]}(z^{[l]}) a[l]=g[l](z[l])
对于 m m m个训练样本,我们可以将其向量化:
Z [ l ] = W [ l ] A [ l − 1 ] + b [ l ] Z^{[l]} = W^{[l]} A^{[l-1]} + b^{[l]} Z[l]=W[l]A[l1]+b[l]
A [ l ] = g [ l ] ( Z [ l ] ) A^{[l]} = g^{[l]}(Z^{[l]}) A[l]=g[l](Z[l])

接下来是反向传播,这就像是石头滚回山顶。每一层都会影响其速度和方向。

反向传播的表达式为:
d z [ l ] = d a [ l ] ∗ g [ l ] ′ ( z [ l ] ) dz^{[l]} = da^{[l]} * g^{[l]\prime}(z^{[l]}) dz[l]=da[l]g[l](z[l])
d W [ l ] = d z [ l ] ⋅ a [ l − 1 ] dW^{[l]} = dz^{[l]} \cdot a^{[l-1]} dW[l]=dz[l]a[l1]
d b [ l ] = d z [ l ] db^{[l]} = dz^{[l]} db[l]=dz[l]
d a [ l − 1 ] = W [ l ] T ⋅ d z [ l ] da^{[l-1]} = W^{[l]T} \cdot dz^{[l]} da[l1]=W[l]Tdz[l]

其中最后一个关系表示了不同层之间的连接。

对于 m m m个训练样本,我们也可以将其向量化:
d Z [ l ] = d A [ l ] ∗ g [ l ] ′ ( Z [ l ] ) dZ^{[l]} = dA^{[l]} * g^{[l]\prime}(Z^{[l]}) dZ[l]=dA[l]g[l](Z[l])
d W [ l ] = 1 m d Z [ l ] ⋅ A [ l − 1 ] T dW^{[l]} = \frac{1}{m} dZ^{[l]} \cdot A^{[l-1]T} dW[l]=m1dZ[l]A[l1]T
d b [ l ] = 1 m n p . s u m ( d Z [ l ] , a x i s = 1 , k e e p d i m s = T r u e ) db^{[l]} = \frac{1}{m} np.sum(dZ^{[l]}, axis=1, keepdims=True) db[l]=m1np.sum(dZ[l],axis=1,keepdims=True)
d A [ l − 1 ] = W [ l ] T ⋅ d Z [ l ] dA^{[l-1]} = W^{[l]T} \cdot dZ^{[l]} dA[l1]=W[l]TdZ[l]

7. 参数与超参数 (Parameters vs Hyperparameters)

在这部分,我们将探讨神经网络的两个关键组件:参数和超参数。想象一下,你正在建造一个房子。参数就像是你的砖块和木头,而超参数就像是你的蓝图。

神经网络中的参数是: W [ l ] W^{[l]} W[l] b [ l ] b^{[l]} b[l],它们是神经网络学习的结果。而超参数包括:学习速率 α \alpha α、训练迭代次数 N N N、神经网络层数 L L L、每层的神经元数 n [ l ] n^{[l]} n[l] 和激活函数 g ( z ) g(z) g(z)。超参数决定了参数的形态和值。

选择最佳的超参数往往需要经验和实验。这个过程类似于建房子时选择最佳的蓝图。通常的方法是尝试不同的超参数组合,看看哪个效果最好。

8. 神经网络与大脑有什么关系? (What does this have to do with the brain?)

我们常常听说神经网络是受大脑启发的,但它们之间真的有多相似呢?神经网络,特别是深度神经网络,主要分为两个过程:正向传播和反向传播。每个神经元在神经网络中都通过一个激活函数来工作,这与感知机模型非常相似。这样的模型与我们大脑中的神经元有许多相似之处。它可以看作是对大脑神经元的简化表示。例如,大脑神经元由树突、细胞体和轴突组成。其中,树突接收信号(这与神经网络中的输入类似),细胞体处理这些信号(类似于神经网络中的激活函数),然后轴突将处理后的信号传递给下一个神经元(类似于神经网络中的输出)。

但是,我们必须记住,真实的大脑神经元比这种简化模型要复杂得多。而且,我们现在还不完全明白大脑是如何学习的。它是否也使用了类似于反向传播和梯度下降的机制?可能会更复杂。不过,这提供了一个有趣的方向,生物学家和神经科学家可以进一步研究。而我们作为人工智能研究者,也许可以从中找到新的灵感,为神经网络模型提供更强大的学习策略!

这里写图片描述

9. 总结 (Summary)

这一课我们详细探讨了深度神经网络,它基于我们在之前学习的浅层神经网络。首先,我们明确了构建神经网络时常用的标准符号。然后,通过流程图,我们详细推导了正向和反向传播的具体步骤。为什么深度神经网络比浅层神经网络更有优势?我们从特征提取的复杂性和计算效率的角度进行了探讨。此外,我们还讨论了超参数的重要性,并解释了它与常规参数之间的区别。最后,我们简要探讨了神经网络与人类大脑的相似之处,指出虽然它们之间有一些相似性,但神经网络只是一个简化版本。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 非常感谢您的建议,我们会尽快为大家准备一篇关于C语言入门的学习笔记,帮助大家更好地掌握这门编程语言。我们会尽可能详细地介绍C语言的基本语法、数据类型、运算符、流程控制语句等内容,同时也会提供一些实例代码和练习题,帮助大家更好地理解和掌握C语言编程。希望我们的学习笔记能够对大家有所帮助,让大家更快地入门C语言编程。 ### 回答2: C语言是一门广泛应用于系统编程、嵌入式系统、游戏开发等领域的高级程序设计语言。入门C语言对于软件开发工程师和计算机科学爱好者来说非常重要。 在C语言学习笔记中,我们首先需要熟悉C语言的基础知识,如数据类型、变量、运算符、流程控制语句和函数等。了解基础知识将会帮助我们更好地理解后续学习内容。 其次,学习C语言需要掌握一些编程基本技巧,如程序的模块化设计、调试和测试、程序的优化等。这些技巧可以帮助我们提高代码质量和效率。 同时,我们还需要了解C语言的高级编程特性,如指针、动态内存分配、结构体、文件操作等。掌握这些编程特性可以让我们更加灵活地进行编程。 最后,想要成为一名优秀的C语言程序员,我们需要不断实践和探索,不断完善自己的编程技能、提高编程水平。需要经常练习编写代码,加入开源社区进行开源项目的贡献和参与,与其他程序员交流经验,扩展自己的技术视野。 总之,学习C语言需要投入大量的时间和精力,需要不断地学习、实践和交流。但是,在通过不断地学习和实践后,C语言将成为你的强大工具,可以开发出各种高效、可靠的应用程序,实现自己的编程理想和目标。 ### 回答3: C语言是一门非常基础但又非常重要的编程语言,这门语言被广泛应用于各个领域,如嵌入式系统,操作系统开发等。C语言入门,是每个程序员必经的过程,通过学习C语言,我们掌握了基本的编程思想和方法,同时也为我们日后学习其他高级语言奠定了扎实的基础。 在这篇学习笔记中,我们可以学到C语言的各种基础知识点,例如数据类型、运算符、控制语句、函数等。这些知识点是C语言编程的基础,掌握它们非常重要。在学习的过程中,需要认真阅读教材,并且要动手实践,自己编写一些小程序,才能真正理解和掌握知识点。 除此之外,我们还可以通过学习C语言的标准库函数来扩展语言的使用范围,这些标准库函数非常常用,不仅可以方便快捷地实现某些功能,而且也是日后学习其他语言时会用到的知识点。 在学习C语言过程中,需要有一个良好的学习态度,要不断地做笔记、做练习,不断地复习、总结,才能够真正掌握这门语言,更好的为日后的编程生涯打好基础。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

快撑死的鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值