【使用 BERT 的问答系统】第 2 章 :用于自然语言处理的神经网络

     🔎大家好,我是Sonhhxg_柒,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎

📝个人主页-Sonhhxg_柒的博客_CSDN博客 📃

🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝​

📣系列专栏 - 机器学习【ML】 自然语言处理【NLP】  深度学习【DL】

 🖍foreword

✔说明⇢本人讲解主要包括Python、机器学习(ML)、深度学习(DL)、自然语言处理(NLP)等内容。

如果你对这个系列感兴趣的话,可以关注订阅哟👋

文章目录

什么是神经网络?

神经网络的构建模块

神经元

输入层

隐藏层

输出层

激活函数

神经网络训练

神经网络的类型

前馈神经网络

卷积神经网络

循环神经网络

长短期记忆

编码器和解码器

Transformer 型号

模型架构

注意力模型

结论


将人类认知智能(即思考、推理和行动)带入人工系统一直是研究人员的热门话题。在这个过程中,他们提出了神经网络的想法,试图模拟人脑神经元的工作方式。尽管它们离人类的认知能力还有很远的距离,但人工神经网络在 ML 领域占据着非常有前途的地位,并且已经改变了 NLP 应用程序的开发方式。

在本章中,我们将讨论神经网络及其类型,以及一些特殊类型的神经网络,例如长短期记忆 (LSTM)、卷积神经网络 (CNN)、编码器、解码器和转换器。这将为我们转向更高级的 NLP 主题奠定基础,并研究 NLP 的最新技术水平现在如何在 NLU 方面与人类能力相匹配。

什么是神经网络?

神经网络被定义为神经元网络,这些神经元连接以处理信息并执行特定于任务的动作。简单来说,人类神经元在其突触端点接收到电信号时,就具备了传递和处理信息的能力。人工神经网络 (ANN)在被激活函数触发后通过网络传输信息来复制这种信息流。人工神经网络分为三种类型的层:输入层、隐藏层和输出层。神经网络一般有一个输入层和一个输出层以及多个隐藏层,如图2-1所示。

                                                                图 2-1  神经网络

神经网络的构建模块

在本节中,我们将讨论神经网络的基本构建块以及如何将这些块组合起来形成神经网络。

神经元

模仿人类神经元行为的神经元是神经网络的最小单元。它接受输入,对其进行处理,并将输出发送到其他神经元,这些神经元充当其他神经元的激活。神经元只能根据从前一层接收到的观察结果来激活。

输入层

如图2-1所示,输入层将处理后的数据作为输入。在这里,在图像的情况下,输入可以是像素,或者文本数据或特征值的句子的矢量表示中的数字。该层负责将所有特征的值与一些权重值结合起来(权重值定义了每个特征的重要性)。处理后,输入层的输出被送入下一层,即隐藏层,最后送入输出层。

隐藏层

这些层负责生成特定于任务的特征。我们可以在输入层和输出层之间有任意数量的隐藏层。每层都由负责执行特定于任务的动作的神经元组成。该层可以实现激活函数(即 Sigmoid、tanh),或者可以对前一层的所有输入进行加权求和。因此,该层接收来自前一层的输入,然后将输入的乘积与其相应的权重值相加,并应用激活函数从该隐藏层获得输出。然后将此信息传递到下一个隐藏层或输出层。

输出层

输出层是神经网络的最后一层。它负责收集来自最后一个隐藏层的所有信息以输出最终的预期结果。如果您正在处理分类模型,那么在回归问题的情况下,最后一层的节点数应该等于类数或单个节点。

我们如何决定层中的节点数和每一层上的节点数一直是一个悬而未决的问题。没有严格的指导方针,但在设计神经网络架构时应考虑一些建议。
  • 输入层中的节点数必须等于输入数据点的大小。

  • 输出层中的节点数取决于神经网络正在执行的任务。例如,对于分类任务,节点数应该等于类数,而对于回归任务,它应该只有一个节点。

  • 每个隐藏层中的隐藏层和节点数完全取决于您的目标任务。一个神经网络很可能对任务 A 工作得很好,但对任务 B 却不行。

  • 列出您要在输入层和输出层之间执行的所有中间转换。

  • 隐藏层中的节点数应大于输入层和输出层中的节点数。

  • 隐藏层中的节点数应为 2 的幂(即 2、4、8、16、32 等)。

例如,如果您正在构建一个情感模型(或分类模型),系统会将用户反馈的情感识别为正面、负面或中性,那么神经网络输出层的结果是概率分布所有类别(正、负和中性),如图2-2所示。

                                                                图 2-2  神经网络

激活函数

神经网络用于解决复杂的非线性问题,而这在传统的线性模型中是行不通的。神经网络中的激活函数是在系统中引入非线性的激活函数,如图2-3所示。

                                                                        图 2-3  激活函数

它计算输入乘积及其相应权重的总和,然后加上偏差。然后激活函数决定将哪个特征或输入值传递到下一层。例如,假设我们在隐藏层的所有节点使用Sigmoid 函数,其中 Sigmoid 可以取 0 到 1 之间的任何值(含 0 和 1)。在此基础上,激活函数决定将本层和上一层的信息传递给下一层的比例。Tanh 和 ReLU 是神经网络中激活函数的其他重要示例。

至此,我们已经讨论了神经网络的构建块。接下来,我们转向神经网络的训练。

神经网络训练

神经网络训练基于前向传播和反向传播的概念。在前向传播中,输入数据从输入层的神经元传播到隐藏层的神经元,然后使用激活函数应用相关变换,最后到输出层的神经元计算预测值。在反向传播中,损失是通过比较输入数据的实际值和预测值来计算的。这个错误从输出层的神经元传播到隐藏层的所有神经元。隐藏层中的神经元很可能只收到一小部分误差分量,这取决于它们对输出层中神经元的贡献。

当我们谈论信息向前或向后传播时,这意味着连接这些神经元的边的权重和这些神经元的偏差值将被调整。此外,权重和偏差的值是随机初始化的,学习过程相应地找到这些模型参数的最佳值。

神经网络的类型

现在我们了解了每个神经元、权重和激活函数如何一起构建神经网络,我们可以研究如何以不同的方式使用它们中的每一个来获得不同的结果。接下来我们讨论几种类型的神经网络。

前馈神经网络

前馈神经网络 ( FNN) 最好被描述为一种单向神经网络,其结构中没有任何反馈或环回。FNN 的体系结构包括多个隐藏层和每个层中的多个隐藏单元,如图2-4所示。

该神经网络被称为前馈网络的原因之一是,当 FNN 充当分类器时,在正常操作期间层与层之间没有反馈。

                                                        图 2-4  基本 FNN 感知器图

在 FNN 中,感知器分层排列。第一层负责接收输入,最后一层负责输出。因为中间层与外界没有任何联系 ,所以被称为隐藏层。当一层中的感知器连接到下一层中的每个感知器时,信息从一层前馈到下一层。另一方面,同一层中的感知器没有连接。

FNN 模型在训练期间使用成本函数。该成本函数作用于模型做出的近似值与实际目标值之间的差异。与 ML 算法类似,FNN 也使用基于梯度的学习来进行训练。成本函数的可能选择包括二次成本、交叉熵成本、指数成本等。

输出层包含输出单元,其任务是提供所需的输出或预测。成本函数的选择和输出单元都是紧密耦合在一起的。输出单元有多种选择,如线性单元、sigmoid 单元、softmax 单元等。

FNN 易受数据噪声的影响且易于维护,因此在计算机视觉等领域具有广泛的应用前景。FNN 可以帮助揭示输入和输出之间的非线性关系,因此在这些网络的帮助下可以轻松表示大多数多分类。

卷积神经网络

CNN是一种 深度学习算法。它接收输入图像并为图像的各个方面分配权重和偏差。与其他分类算法相比,CNN 中的预处理相对较少,因为它们具有学习过滤器和特征的能力。

与其他神经网络类似,CNN 也由神经元组成,具有可学习的权重和偏差。加权和接管接收到的几个输入,然后与输出一起通过激活函数。CNN 与其他网络的不同之处在于它对卷进行操作的方式。这里的输入不是向量;相反,输入是多通道图像。

CNN 用于图像处理,因为它通过应用相关过滤器成功地捕获了图像中的空间和时间依赖性。网络以更好的方式理解图像,因为它可以更好地拟合图像数据集,同时减少所涉及的参数数量。

卷积是两个输入的组合以生成输出。对于 CNN,通常此输入是用过滤器屏蔽以生成所需输出特征的图像。当我们谈论空间分布的数据或矩阵作为输入时,选择的过滤器通常是一组权重,用于调整输入以获得所需的变化以生成结果。如果引用一般意义,那么卷积就是两个值的点积生成第三个值。图2-52-6显示了卷积在 CNN 中的工作原理。

                                                                    图 2-5  卷积示例

                                                                                图 2-6卷积示例

在图2-5所示的示例中,输入采用 5 × 5 矩阵的形式,其中包含来自图像的信息。我们将应用一个过滤器来产生输出。输入用零填充以将其转换为以下矩阵。完成此填充以生成所需维度的输出的空间表示。

在给定的示例中,步幅或步长为 2,这意味着过滤器水平向右移动两步,垂直向下移动两步。过滤器第一次对左上角的蓝色子矩阵进行卷积:

(0x-1 + 0x0 + 0x-1 + 0x0 + 1x1 + 4x1 + 0x1 + 2x0 + 0x-1) = 5

以下步骤填充输出矩阵的其余部分。此处还值得注意的是,以蓝色、黑色和红色显示的子矩阵具有非常不同的值,但在从过滤器屏蔽后,蓝色和黑色子矩阵产生相等的输出,而红色子矩阵产生小得多的值。这表示适当的过滤器可以帮助改变输出特征矩阵的程度。例如,如果图像的像素值具有很大的对比度值,则适当的过滤器可以帮助降低图像对比度 。

CNN 发挥着至关重要的作用,它可以将图像缩小为更易于处理的形式,同时保留对获得良好预测很重要的特征。CNN 的这种能力使它们可扩展到大型数据集。

在 CNN 中,我们有一个卷积层,它从输入图像中提取高级特征,例如边缘。该层是 CNN 的构建块。它由一组与图像卷积的独立滤波器组成,为我们提供特征图。这些过滤器是随机初始化的,它们成为网络后续学习的参数。

每个神经元都连接到输入图像的特定特征图的小块。在特定的特征图中也有参数共享。在特定的特征图中,所有神经元都具有相同的连接权重。参数共享和本地连接有助于减少整个系统中的参数数量并确保更好的计算效率。

池化的概念使 CNN 不同于其他神经网络。池化功能逐渐减少表示的空间大小,以减少参数数量和计算量。池化层在每个特征图上独立运行。

在池化层之后,扁平化的输出被馈送到 FNN,然后反向传播应用于训练的每次迭代,如图2-7所示。经过一系列迭代,该模型能够使用 softmax 分类技术对图像进行分类。

                                                                图 2-7 CNN图表

循环神经网络

递归神经网络 (RNN) 是一种神经网络,旨在处理连续数据或以流形式呈现的数据,以从数据的连续性中受益。通常,每个隐藏层接收到的数据都有一个来自前一层输出的输入作为当前层的输入,以及一个隐藏输入。

在输入序列较长的情况下,RNN 可以证明是非常有利的,在这种情况下,要求围绕维护相同输入的上下文进行循环,而不影响所使用模型的大小。这使得 NLP 成为 RNN 的自然应用,尽管历史信息往往会在很长一段时间内消失,并且也会减慢该过程。

正如我们在图2-8中看到的,输入由 Xt 表示,它是网络在时间步长 t 的输入。例如,X 1可以是一个向量对应一个句子中的一个词。隐藏状态由时间 t 处的 H t表示。它充当网络的存储器。H t的值是根据当前输入和前一个时间步的隐藏状态计算的:

H t = f (UX t + WH t-1 )

函数 f 是一个非线性变换函数,如 tanh 或 ReLU。
                                                                图 2-8  循环神经网络图

与FNN 相比,RNN利用其内部状态或记忆来处理输入序列。与输入相互独立的其他网络不同,RNN 中的所有输入都相互关联。RNN 从输入序列中获取 X 0,然后输出 H 0。此输出与 X 1一起是下一步的输入。因此,H 0和X 1构成下一步的输入。类似地,H t-1和 X t构成时间 t 的输入。这样,RNN 在训练时会记住上下文。

当前状态由

H t = f (H t-1 , X t )。

在应用激活函数时,

H (t) = tanh (WH (t-1) + UX (t) )。
  • H 是单个隐藏向量。

  • W 是先前状态的权重。

  • tanh 是激活函数。

  • U 是当前输入状态下的权重。

网络的输出由 Y t表示。有权重参数化从输入到隐藏层的连接。权重矩阵 U 将输入参数化为隐藏连接。隐藏层到隐藏层的连接由权重矩阵 W 参数化,隐藏层到输出层的连接由权重矩阵 V 参数化。所有这些权重 (U, V, W) 都是跨时间共享的。

因此,输出由下式给出

Y t = V H t。

RNN 模型可以对数据序列进行建模,因此可以假设样本的每个结果都依赖于之前的结果。RNN 还有另一个优势,因为它们甚至可以与卷积层一起使用以扩展有效像素邻域。

RNN 模型在使用 tanh 或 ReLU 作为激活函数时有一个缺点,因为它无法处理长序列。RNN 的训练也是一项艰巨的任务,存在梯度消失和爆炸的问题。

长短期记忆

LSTM 是使用最广泛的 RNN 形式之一。他们能够学习长期依赖性,以及他们的默认行为来长时间学习或记住信息。

所有 RNN 模型都具有链接的神经网络重复模块的形式。在标准 RNN 中,这个重复模块将具有非常简单的结构,例如单个 tanh 层。

另一方面,LSTM 也具有这种链状结构,但重复模块具有不同的结构。在这里,不是单个神经网络层,而是四个以非常特殊的方式交互的层。LSTM 的控制流程类似于 RNN,因为它处理数据并在数据向前传播时传递信息。LSTM 工作方式的不同之处在于单元允许 LSTM 保留或忘记信息。在 LSTM 中,重点是细胞状态和各种门。细胞状态充当传输高速公路,并通过序列链一路传递相关信息。随着细胞状态的进行,门会添加或删除信息。门是不同的神经网络,它们决定在细胞状态中允许哪些信息。

编码器和解码器

编码器-解码器是用于序列预测问题的 RNN 组织,通常具有可变数量的输入、输出或两者。encoder-decoder 最初的主要目的是机器翻译问题,但它已被证明在相关的序列到序列预测问题上是成功的,例如问答和文本摘要。

编码器-解码器方法涉及两个 RNN,一个用于对输入序列进行编码,另一个用于将编码的输入序列解码为目标序列。编码任务由编码器执行,解码任务由解码器执行。这种编码器-解码器架构对于序列到序列模型的各种应用非常有用,例如:
  • 聊天机器人

  • 机器翻译

  • 文字概要

  • 图片说明

编码器-解码器架构

编码器-解码器架构由两个主要组件组成,即编码器和解码器。这两个组件同时联合训练。编码器-解码器的架构如图2-9所示。

                                                 图 2-9 编码器-解码器的架构

编码器获取输入并读取整个输入序列,并将其编码为内部表示。编码器处理输入序列并从序列中收集信息,然后进一步传播。这个固定长度的内部表示向量被称为上下文向量。中间向量 ID 是模型的编码器部分产生的最终内部状态。这有助于解码器做出准确的预测。解码器负责从编码器读取编码序列,从而生成输出序列。

模型的编码器部分

负责转换输入序列并将信息封装为内部状态向量的编码器基本上是一个 LSTM 或 GRU(门控循环单元)单元。仅使用内部状态;编码器的输出被拒绝,如图2-10所示。

                                                图 2-10  用于编码器的 LSTM
为了理解模型编码器部分的工作原理,我们关注 LSTM。在 LSTM 中,一次仅将一个元素作为输入。这意味着如果我们有一个长度为 m 的序列,那么 LSTM 需要 m 个时间步来读取整个序列。
  • X t是时间步长 t 的输入。

  • h t和 c t是 LSTM 在时间步长 t 的内部状态;对于 GRU,只有一个内部状态 h t。

  • Y t是时间步 t 的输出。

让我们举一个将英语句子翻译成法语的例子。
  • English: It is a good day.

  • French: C’est une bonne journée.

显示的英语序列可以被认为是一个包含五个单词的句子。编码器 X t的输入如下。
  • X1 = It

  • X2 = is

  • X3 = a

  • X4 = good

  • X5 = day.

LSTM 将分五个时间步逐字读取序列。每个单词 X t使用单词嵌入表示为一个向量。词嵌入将每个词转换为固定长度的向量。内部状态 (h t , c t ) 了解 LSTM 在时间步 t 之前读取的内容。这里 LSTM 将在时间步 t = 5 中读取整个句子。最终状态 h 5 , c 5具有整个输入序列的信息,“It is a good day”。

编码器的输出是 Yt ,它在每个时间步都是 LSTM 的预测。因为在机器翻译问题中,我们采用整个输入序列的输出,所以每个时间步的Yt都被丢弃,因为它没有用。

模型的解码器部分

解码器的工作方式与编码器不同。它的训练阶段和测试阶段的工作方式不同,而编码器模型在训练和测试阶段的工作方式相同。

如果我们以前面介绍的句子语言翻译示例为例,就像编码器一样,解码器也逐字生成输出句子。要生成输出“C'est une bonne journée”,我们需要在开头添加START_并在结尾添加_END作为输出序列的分隔符,以便解码器识别序列的开始和结束。解码器基本上被训练为根据编码器收集的信息生成输出,因此解码器的初始状态 (h 0 , c 0 ) 被设置为编码器的最终状态。

输入START_以便解码器可以开始生成下一个单词。解码器使用_END学习法语句子的结尾。损失是根据每个时间步预测的输出计算的,误差会随着时间反向传播以更新模型的参数。在测试阶段,每个时间步产生的输出作为输入馈送到下一个时间步,序列的结尾使用_END标识。

双向编码器和解码器

在双向编码器-解码器架构中,编码器和解码器是双向 LSTM。后向编码器的最后一个隐藏状态初始化前向解码器,而后向解码器用前向编码器的最后一个隐藏状态初始化。

在考虑过去和未来的上下文信息时使用双向编码器。输入词向量序列从前向和后向输入到 LSTM。双向解码器也是一个双向 RNN,由两个独立的 LSTM 组成。其中一个 LSTM 从左到右解码信息,而另一个 LSTM 从右到左反向解码。RNN 中的这种双向性提供了更好的性能。

例如,我们必须预测句子“The weather is cloudy;”中“cloudy”之后的下一个词。可能会下雨。” 单向 LSTM 将看到“The weather is …”,并将尝试仅使用此上下文来预测下一个词。当使用双向 LSTM 时,我们将能够看到更多信息。
  • Forward LSTM: “The weather is …”

  • Backward LSTM: “… it might rain today.”

因此,使用过去和未来的信息可以更轻松地预测“多云”一词,因为网络将更好地理解下一个词。

Transformer 型号

Transformer是一种新颖的架构,旨在解决序列到序列的任务,同时处理远程依赖关系。就像 RNN 所做的那样,转换器在样本中维护顺序信息。如果我们从更高层次看一下 transformer 模型,它基本上就像机器翻译应用程序中的一个黑盒子,将一种语言的句子作为输入并输出句子的翻译,如图2-11所示.

                                                图 2-11  作为黑匣子的变压器

模型架构

Transformer具有编码器-解码器结构,对编码器和解码器使用堆叠式自注意力和全连接层。转换器由编码器、解码器、位置编码和注意力等组件组成。有一堆编码器和解码器。每个编码器都与其他编码器非常相似,因为它们具有相同的架构。解码器也共享此属性,并且在转换器中彼此相似,如图2-12所示。
                                        图 2-12  Transformer 中的编码器-解码器堆栈

 编码器包括一堆相同的层。每层进一步由两个子层组成。第一层用于多头自注意力机制。另一方面,第二层是一个简单的、完全连接的前馈网络。在每个子层之间,使用残差连接和层归一化。输入流经编码器中的自我注意层,帮助编码器在编码特定单词时查看输入序列中的其他单词。

解码器类似于编码器,包括一堆相同的层。它也有像编码器这样的子层,但多了一个子层。第三个子层负责对编码器堆栈的输出执行多头注意力。这些层帮助解码器只关注输入句子的相关部分。

编码器块有一层 FNN 的多头层,另一方面,解码器有一个额外的屏蔽多头注意机制。编码器和解码器堆栈都具有相同数量的单元。编码器和解码器单元的数量基本上是一个可以变化的超参数。

为了防止对乱序位置的不必要注意,在编码器和解码器的自注意层中的 softmax 之前使用了掩码。为了防止位置关注后续位置,在解码器中使用附加掩码与通用掩码结合使用。解码器中的这两个掩码可以在按位与操作的帮助下混合。

注意力模型

注意是使用softmax 函数的密集层的输出向量。它通过将其插入合适的场景来增强结果。翻译机制用于依赖于阅读一个完整的句子并将所有信息压缩成一个固定长度的向量。在这种情况下,如果我们有一个包含数百个单词的句子,用几个单词来表示,肯定会丢失信息或翻译不充分。

注意力能够部分解决这个问题。它负责让机器翻译器查看句子包含的所有信息。从而根据当前词和上下文生成合适的词。注意力还通过允许翻译器放大或缩小来提供关注局部或全局特征的能力。

为什么需要注意?

由于句子由不同数量的单词组成,自然会引入 RNN 来模拟单词之间的条件概率。在概率语言模型中,重点是使用马尔可夫假设为句子分配概率。

P(w 1 w 2 … w n ) ≈ Π P(w i | w i-k … w i-1 )

使用这种编码器-解码器模型,翻译工作在可变长度的输入和输出上。这是在将基本 RNN 单元更改为 GRU 或 LSTM 单元并且 ReLU 替换双曲正切激活时采用的。

在嵌入层的帮助下,离散词被映射到密集向量以提高计算效率。然后将这些嵌入的单词按顺序馈送到编码器。随着信息从左向右流动,每个词向量都是根据所有先前的输入来学习的,而不仅仅是当前词。完整阅读句子后,编码器会生成输出。还有一个由编码器生成的隐藏状态以供进一步处理。解码器使用来自编码器的隐藏状态并按顺序生成翻译词。

注意力如何运作

注意机制基本上是一个上下文向量,它被插入到编码器和解码器之间的间隙内的编码器-解码器架构中。该上下文向量将所有编码器单元的输出作为输入,然后为解码器要生成的每个单词计算源语言单词的概率分布。解码器能够捕获全局信息,而不仅仅是基于一个隐藏状态进行推断。这种注意力机制有助于解码器捕捉更广阔的视角。

如果我们研究一下上下文向量是如何构建的,它基本上非常简单。对于每个固定的目标词,我们通过遍历编码器的所有状态并将目标与源状态进行比较来为每个编码器状态生成分数。然后使用softmax对所有分数进行归一化。我们现在获得以目标状态为条件的概率分布。最后,为了使上下文向量易于训练,引入了权重。一旦我们得到上下文向量,就可以使用上下文向量、注意力函数和目标词轻松计算注意力向量。

注意力模型的类型

注意力模型分为三种类型:全局和局部注意力、硬和软注意力以及自注意力。让我们依次检查每一个。

全局注意力模型

在全局注意力模型 中,在计算输出时考虑了当前状态之前的每个编码器状态和解码器状态的输入。这里的上下文向量是通过全局对齐权重和每个编码器步骤的乘积获得的。然后将其馈送到 RNN 单元以获得解码器输出。

局部注意力模型

局部注意力模型与全局注意力模型不同 ,因为编码器中很少有位置用于计算对齐的权重。局部注意力模型还有两种类型:单调对齐和预测对齐。

硬注意力和软注意力模型

软注意力模型类似于全局注意力模型。硬注意力模型与局部注意力模型的不同之处在于,局部模型几乎在每个点都是不同的,而硬注意力模型则不然。局部注意力模型可以被认为是硬注意力和软注意力的混合体。

自注意力模型

自注意力模型 关联相同输入序列的不同位置。Self-attention理论上可以采用任何得分函数,条件是目标序列要被替换为相同的输入序列。

结论

在本章中,我们讨论了 NLP 领域中的各种神经网络。现在我们已经介绍了不同类型的神经网络,我们将注意力转向如何使用 BERT。

  • 7
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Sonhhxg_柒

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

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

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

打赏作者

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

抵扣说明:

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

余额充值