AlexNet——深度学习框架(一)

基于深度卷积神经网络的ImageNet分类

摘要

我们训练了一个大型的深度卷积神经网络,将ImageNet LSVRC-2010大赛中的120万张高分辨率图像分类为1000个不同的类别。在测试数据上,我们获得了前1名和前5名的错误率,分别为37.5%和17.0%,这比之前的技术水平要好得多。该神经网络有6000万个参数和65万个神经元,由5个卷积层组成,其中一些随后是最大池化层,以及3个全连接层,最后是1000路softmax。为了使训练更快,我们使用了非饱和神经元和一个非常高效的GPU实现卷积运算。为了减少全连接层的过拟合,我们采用了一种最新开发的正则化方法,称为“dropout”,该方法被证明是非常有效的。我们还在ILSVRC-2012竞赛中引入了该模型的一个变体,获得了15.3%的前5名测试错误率,而第二名的测试错误率为26.2%

1 导论

目前的目标识别方法基本使用机器学习方法。为了提高它们的性能,我们可以收集更大的数据集,学习更强大的模型,并使用更好的技术来防止过拟合。直到最近,标记图像的数据集都相对较小——大约有数张图像(例如,NORB[16]、Caltech-101/256[8,9]和CIFAR-10/100[12])。使用这种规模的数据集,简单的识别任务可以很好地解决,特别是如果使用保存标签的转换来扩充它们。例如,当前MNIST数字识别任务的最佳错误率(<0.3%)接近人类性能[4]。但是现实环境中的物体表现出相当大的可变性,所以要学会识别它们,就必须使用更大的训练集。的确,小图像数据集的缺点已经被广泛承认(例如,Pinto等[21]),但直到最近才有可能收集有数百万张图像的标记数据集。新的更大的数据集包括LabelMe[23]和ImageNet[6],其中包含数十万张完全分割的图像,以及超过22000个类别的超过1500万张标记高分辨率图像。为了从数以百万计的图像中了解成千上万的对象,我们需要一个具有巨大学习能力的模型。然而,对象识别任务的巨大复杂性意味着这个问题甚至不能通过ImageNet这样大的数据集来指定,所以我们的模型也应该有大量的先验知识来弥补我们没有的所有数据。卷积神经网络(Convolutional neural networks, CNNs)就是其中一类模型[16,11,13,18,15,22,26]。它们的容量可以通过改变它们的深度和广度来控制,而且它们还对图像的本质(即统计的平稳性和像素相关性的局部性)做出了强有力且基本正确的假设。因此,与具有相似层数标准前馈神经网络相比,cnn连接和参数要少得多,因此更容易训练,而它们在理论上的最佳性能可能只略差一些。

尽管cnn具有吸引人的特性,尽管其本地架构具有相对的效率,但要在大规模应用于高分辨率图像,它们仍然代价高昂。幸运的是,目前的gpu,配合高度优化的2D卷积,足够强大,以促进训练有趣的大型cnn,和最近的数据集,如ImageNet包含足够的标记示例,用来训练这样的模型,而没有严重的过拟合。本文的具体贡献如下:我们在ILSVRC-2010和ILSVRC-2012比赛[2]中使用的ImageNet的子集上训练了迄今为止最大的卷积神经网络之一,并取得了迄今为止在这些数据集上报道的最好的结。我们编写了一个高度优化的2D卷积的GPU实现和所有其他在训练卷积神经网络中固有的操作,我们将其公开。我们的网络包含了一些新的和不寻常的功能,这些功能可以提高它的性能并减少它的训练时间,这将在第3节中详细介绍。我们的网络规模使得过拟合成为一个重大问题,即使有120万个标记训练示例,所以我们使用了几个有效的技术来防止过拟合,这在第4节中描述。我们最终的网络包含5个卷积层和3个全连接层,这个深度似乎很重要:我们发现移除任何一个卷积层(每个卷积层包含的参数不超过模型参数的1%)都会导致性能下降。最后,网络的大小主要受限于当前gpu上可用的内存数量和我们愿意容忍的训练时间。我们的网络需要两个GTX 580 3GB gpu训练5到6天。我们所有的实验都表明,只要等待更快的gp更大的数据集出现,我们的结果就可以得到改善

2 数据集

数据集ImageNet是一个包含超过1500万张高分辨率图像的数据集,属于大约22000个类别。这些图片是从网上收集的,并使用亚马逊的Mechanical Turk众包工具进行人工标记。从2010年开始,作为帕斯卡视觉对象挑战赛的一部分,每年举行一次名为ImageNet大规模视觉识别挑战赛(ILSVRC)。ILSVRC使用ImageNet的一个子集,在1000个类别每个类别大约有1000张图片。总共大约有120万张训练图像,5万张验证图像和15万张测试图像。ILSVRC-2010是ILSVRC中唯一可用测试集标签的版本,所以这是我们进行大部分实验的版本。由于我们的模型也参加了ILSVRC-2012竞赛,在第6节中,我们也报告了这个版本的数据集的结果,它的测试集标签是不可用的。在ImageNet上,错误率:top-1(效果最好)至top-5(效果最差),其中top-5错误率是正确标签不在模型认为最可能的五个标签中的测试图像的一部分。ImageNet由可变分辨率的图像组成,而我们的系统需要恒定的输入维度。因此,我们将图像降采样到固定的256 × 256分辨率。给定一个矩形图像,我们首先对图像进行重新缩放,使较短的边的长度为256,然后从生成的图像中裁剪出中心区域256×256大小的图像。我们没有以任何其他方式对图像进行预处理,除了从每个像素中减去训练集上的平均活动。因此,我们在像素的原始RGB值(中心)上训练我们的网络。

3 结构

图2总结了我们的网络结构。它包含8个已学习的层——5个卷积层和3个全连接层。下面,我们将描述我们的网络架构的一些新奇或不寻常的特征。第3.1-3.4节是根据我们对其重要性的估计进行排序的,最重要的排在前面。

3.1 ReLU非线性

将一个 神 经 元 的 输 出 f 神经元的输出f f 作为其 输 入 x 输入x x 的函数来建模的标准方法是 f ( x ) = t a n h ( x ) f(x) = tanh(x) f(x)=tanh(x) f ( x ) = ( 1 + e − x ) − 1 f(x) = (1 + e^{−x})^{−1} f(x)=(1+ex)1。在梯度下降训练时间方面,这些饱和非线性非饱和非线性 f ( x ) = m a x ( 0 , x ) f(x) = max(0, x) f(x)=max(0,x)慢得多。根据Nair和Hinton[20],我们将具有这种非线性的神经元称为整流线性单元(ReLUs)。使用ReLUs的深度卷积神经网络的训练速度比使用tanh单位的深度卷积神经网络快好几倍。这在图1中展示了,对于特定的四层卷积网络,在CIFAR-10数据集上达到25%的训练误差所需的迭代次数。这幅图表明,如果我们使用传统的饱和神经元模型,我们就无法用这么大的神经网络来完成这项工作。我们不是第一个在cnn中考虑替代传统神经元模型的人。例如,Jarrett etal.[11]声称thenonlinearityf(x) = |tanh(x)|在Caltech-101数据集上的对比归一化后的局部平均池中工作得特别好。然而,在这个数据集上主要关注的是防止过拟合,因此他们观察到的效果与我们在使用ReLUs时报告的加速拟合训练集的能力是不同的。快速学习对在大数据集上训练的大模型的性能有很大的影响。

在这里插入图片描述
图1:使用ReLUs(实线)的四层卷积神经网络在CIFAR-10上达到25%的训练错误率,比使用tanh神经元(虚线)的等效网络快6倍。每个网络的学习率都是独立选择的,以使训练尽可能快。没有采用任何形式的正则化。这里所展示的效应的大小随网络结构的不同而不同,但具有ReLUs的网络始终比具有饱和神经元的网络学习速度快几倍

3.2 使用多个GPU训练

单个GTX 580 GPU只有3GB的内存,这限制了可以在其上训练的最大网络大小。事实证明,120万个训练示例足以训练一个GPU无法容纳的网络。因此,我们将网络分散到两个gpu上。当前的gpu特别适合于跨gpu并行化,因为它们可以直接读写彼此的内存,而不需要经过主机内存。我们所采用的并行化方案本质上是将一半的内核(或神经元)放在每个GPU上,并带有一个额外的技巧:GPU只在特定的层中进行通信。这意味着,例如,从第2层的所有神经元映射输入到第3层的神经元。然而,从位于同一GPU上的第3层的神经元映射输入到第4层的神经元。选择连接模式是交叉验证的一个问题,但这允许我们精确地调整通信量,直到它是计算量的可接受的一部分。结果架构有点类似于Cire san et al.[5]使用的“columnar”CNN,除了我们的列不是独立的(见图2)。该方案降低了我们的前1名和前5名的错误率分别为1.7%和1.2%。相比之下,在一个GPU上训练的每个卷积层的神经元数只有一半。双gpu网络的训练时间比单gpu网络 2 ^2 2稍短

2 ^2 2在最终的卷积层中,单gpu网络实际上与双gpu网络拥有相同数量的内核。这是因为网络的大部分参数都在第一个完全连接的层中,它将最后一个卷积层作为输入。因此,为了使两个网络具有大致相同的参数数,我们没有将最终的卷积层(也没有将随后的完全连接层)的大小减半。因此,这种比较偏向于支持单gpu网络,因为它比双gpu网络的“一半大”。

3.3 局部响应归一化

ReLUs有一个理想的特性,即它们不需要输入归一化防止过拟合。如果至少有一些训练例子产生一个正输入到一个ReLU,学习就会在那个核中发生。然而,我们仍然发现下面的局部归一化方案有助于推广。用 a x , y i a_{x, y}^i ax,yi表示在第 i i i 核的位置 ( x , y ) (x, y) (x,y),然后应用ReLU非线性计算神经元的活动,响应归一化激活函数 b x , y j b_{x,y}^j bx,yj的表达式
b x , y i = a x , y i / ( k + α ∑ j = m a x ( 0 , i − n / 2 ) m i n ( N − 1 , i + n / 2 ) ( a x , y j ) 2 ) β b_{x, y}^i =a_{x, y}^i / \left ( k +\alpha \sum_{j = max(0,i−n / 2)}^{min (N−1,i+ n / 2)} \left ( a_{x, y}^j \right ) ^2 \right )^\beta bx,yi=ax,yi/k+αj=max(0,in/2)min(N1,i+n/2)(ax,yj)2β,总和除以N“相邻”的内核运行在同一空间位置,地图和N层是内核的总数。内核映射的顺序当然是任意的,在训练开始之前就确定了。这种响应归一化实现了一种侧面抑制的形式,这种抑制受到了在真实神经元中发现的类型的启发,在使用不同核计算的神经元输出之间创造了对大活动的竞争。常数k、n、α和β是超参数,其值由验证集确定;我们用k = 2, n = 5, α = 10−4,β = 0.75。我们在某些层中应用ReLU非线性后应用了这种归一化(见第3.5节)。该方案与Jarrett等人[11]的局部对比度归一化方案有一些相似之处,但我们的方案更准确地称为“亮度归一化”,因为我们没有减去平均活动。响应归一化将我们的前1位和前5位错误率分别降低了1.4%和1.2%。我们还在CIFAR-10数据集上验证了该方案的有效性:四层CNN未经归一化的测试错误率为13%,经过归一化的测试错误率为11% 3 ^3 3

3.4 重叠的池

网络池化层对同一核图中相邻神经元组的输出进行了总结。传统上,由相邻的共用单元概括的邻里不重叠(例如,[17,11,4])。更准确地说,一个池化层可以被认为是由一个以s像素为间隔的池化单元构成的网格,每个单元概括了一个以池化单元位置为中心的大小为z × z的邻域。如果我们设置s = z,我们得到传统的本地池,通常使用在cnn。如果我们设置s < z,就得到了重叠池。这就是我们在整个网络中使用的,s = 2 ,z = 3。与非重叠方案s = 2, z = 2相比,该方案的top-1和top-5错误率分别降低了0.4%和0.3%,产生了等效维数的输出。我们通常在训练过程中观察到,具有重叠池的模型发现过拟合稍微困难一些。

3.5 总体架构

现在我们准备好描述CNN的整体架构了。如图2所示,网包含有权重的8层;前五个是卷积的,其余三个是全连接的。最后一个全连接层的输出被馈送到一个1000路softmax,该softmax产生超过1000个类标签的分布。我们的网络最大限度地实现了多项逻辑回归目标,即在预测分布下,最大限度地提高了正确标签的对数概率的平均训练案例。

第二层、第四层和第五层的内核只与位于同一GPU上的前一层的内核映射相连(见图2)。第三层的内核与第二层的所有内核映射相连。全连接层中的神经元与前一层中的所有神经元相连。响应归一化层位于第一和第二卷积层之后。第3.4节中描述的Max-poolinglayers遵循响应归一化层和第5个卷积层。ReLU非线性应用于每个卷积和全连接层的输出。

第一个卷积层过滤224×224×3输入图像,它有96个大小为11×11×3的核步长为4像素(这是相邻的感受域中心之间的距离内核图中的神经元)。第二个卷积层将第一个卷积层的输出(响应归一化和合流)作为输入,用256个大小为5 × 5 × 48的核进行过滤。第三、第四和第五层卷积层彼此连接,没有任何中间的池化层或标准化层。第三个卷积层有384个大小为3 × 3 × 256的核连接到第2个卷积层的输出(归一化,合用)。第四层卷积层有384个核,大小为3 × 3 × 192;第五层卷积层有256个核,大小为3 × 3 × 192。每个完全连接的层有4096个神经元。

在这里插入图片描述

图2:CNN的架构示意图,明确地显示了两个gpu之间的职责划分。一个GPU在图形的顶部运行层组件,而另一个在图形的底部运行层组件。gpu只在某些层进行通信。该网络的输入为150528维,网络剩余层的神经元数量为253,440-186,624-64,896-64,896-43,264 - 4096-4096-1000。

4 减轻过拟合

我们的神经网络结构有6000万个参数。尽管ILSVRC的1000个类使每个训练示例对从图像到标签的映射施加10位约束,但如果没有相当大的过拟合,这是不够的,要学习这么多参数。下面,我们将介绍两种主要的对抗过拟合的方法。

4.1 数据增强

减少图像数据过拟合的最简单和最常见的方法是使用保持标签的变换人为地扩大数据集(例如,[25,4,5])。我们采用了两种不同的数据增强方式,这两种方式都允许用很小的计算量从原始图像生成变换后的图像,因此变换后的图像不需要存储在磁盘上。在我们的实现中,当GPU对前一批图像进行训练时,转换后的图像是在CPU上用Python代码生成的。所以这些数据增强方案实际上是免费的。

数据增强的第一种形式包括生成图像平移和水平反射。我们通过从256×256图像中提取随机的224×224补丁(以及它们的水平反射)来实现这一点,并在这些提取的补丁上训练我们的网络4。这使得我们的训练集的大小增加了2048倍,尽管最终的训练示例是高度相互依赖的。如果没有这个方案,我们的网络会遭受严重的过拟合,这将迫使我们使用更小的网络。在测试时间,网络提取5个224 × 224的patches(四个角斑和中心斑)及其水平反射(共10个斑)进行预测,并将网络的softmax层对10个斑的预测取平均值。

第二种形式的数据增强包括改变训练图像中RGB通道的强度。具体来说,我们在整个ImageNet训练集的RGB像素值集合上执行PCA。对每一个训练图像,我们添加找到的主成分的倍数,大小正比于相应的特征值乘以一个随机变量从一个均值为零和标准偏差为0.1的高斯绘制。因此,对每个RGB图像像素 I x y = [ I x y R , I x y G , I x y B ] ⊤ I_{xy}= [I_{xy}^R, I_{xy}^G, I_{xy}^B]^{\top} Ixy=[IxyR,IxyG,IxyB]相加如下数量:
[ p 1 , p 2 , p 3 ] [ α 1 λ 1 , α 2 λ 2 , α 3 λ 3 ] ⊤ [p_1,p_2,p_3][α_1λ_1, α_2λ_2, α_3λ_3]^{\top} [p1,p2,p3][α1λ1,α2λ2,α3λ3]
其中 p i p_i pi λ i λ_i λi分别为RGB像素值的3 × 3协方差矩阵的特征向量和特征值 α α α为上述随机变量。每个 α i α_i αi 是只对一个特定训练图像的所有像素绘制一次,直到该图像被再次用于训练,此时它将被重新绘制。该方案近似地捕捉了自然图像的一个重要属性,即物体的特性对于光照强度和颜色的变化是不变的。该方案减少了超过1%的top-1错误率

4.2 Dropout

结合许多不同模型的预测是减少测试误差的一种非常成功的方法[1,3],但对于已经需要几天时间来训练的大型神经网络来说,这似乎太昂贵了。然而,有一个非常有效的模型组合版本,在训练期间只花费大约两倍的成本。最近引入的技术称为“dropout”[10],它将每个隐藏神经元的输出设为零概率为0.5。以这种方式被“剔除”的神经元不参与正向传递,也不参与反向传播。因此,每当一个输入被提出时,神经网络就会对一个不同的体系结构进行采样,但所有这些体系结构都共享权值。这种技术减少了神经元的复杂的协同适应,因为一个神经元不能依赖于其他特定神经元的存在。因此,它被迫学习与其他神经元的许多不同随机子集相结合的更健壮的特征。在测试时,我们使用了所有的神经元,但将它们的输出乘以0.5,这是一个合理的近似值,相当于取指数多dropout网络产生的预测分布的几何平均值。我们在图2的前两个完全连接的层中使用dropout。没有dropout,我们的网络显示出大量的过拟合。Dropout能增加一倍收敛所需的迭代数

5 学习的细节

我们使用随机梯度下降法训练我们的模型,批次大小为128个例子,动量为0.9,权重衰减为0.0005。我们发现,这少量的重量衰减对模型的学习是重要的。换句话说,权值衰减在这里不仅仅是一个正则化器:它减少了模型的训练误差。权重w的更新规则为
v i + 1 : = 0.9 ⋅ v i − 0.0005 ⋅ ϵ ⋅ w i − ϵ ⋅ ⟨ ∂ L ∂ w ∣ w i ⟩ w i + 1 : = w i + v i + 1 \begin{aligned} v_{i+1} & := 0.9 · v_i− 0.0005 · \epsilon · w_i− \epsilon · \left \langle \left.\frac{\partial L}{\partial w} \right |_{w_i} \right \rangle \\ w_{i+1} & := w_i+ v_{i+1} \end{aligned} vi+1wi+1:=0.9vi0.0005ϵwiϵwLwi:=wi+vi+1
其中 i i i 是迭代指标, v v v 是动量变量, ϵ \epsilon ϵ 是学习率, ⟨ ∂ L ∂ w ∣ w i ⟩ D i \left \langle \left.\frac{\partial L}{\partial w} \right |_{w_i} \right \rangle _{D_i} wLwiDi是目标对 w w w 的导数的第 i i i d i d_i di 的平均值,在 w i w_i wi 处计算。

我们从标准差0.01的零均值高斯分布初始化每一层的权值。我们用常数1初始化第二层、第四层和第五层卷积层以及完全连接的隐藏层中的神经元偏差。通过为ReLUs提供积极的输入,这种初始化加速了学习的早期阶段。我们用常数0初始化其余层的神经元偏差。

我们对所有层都使用了相同的学习速率,并在整个训练过程中手动调整。我们遵循的启发式方法是,当验证错误率不再随着当前的学习率提高时,将学习率除以10初始学习率为0.01,终止前降低了3倍。我们用120万张图像的训练集对网络进行了大约90个周期的训练,在两个NVIDIA GTX 580 3GB gpu上,这需要5到6天的时间。

6 结果

我们对ILSVRC-2010的研究结果总结在表1中。我们的网络实现了前1名和前5名的测试集错误率37.5%和17.0% 5 ^5 5。在ILSVRC2010年竞赛中取得的最佳成绩是47.1%和28.2%,该方法将6个基于不同特征[2]训练的稀疏编码模型的预测进行了平均,从那时起,最好的公布结果是45.7%和25.7%,该方法是对Fisher向量(FVs)训练的两个分类器的预测进行平均,这两个分类器是从两种密集采样特征[24]计算出来的。
在这里插入图片描述
表1:ILSVRC2010测试集结果比较。斜体是其他人取得的最好结果。
在这里插入图片描述
表2:ILSVRC-2012验证和测试集错误率比较。斜体是其他人取得的最好结果。带有星号*的模型被“预先训练”来对整个ImageNet 2011秋季版本进行分类。详见第6节。

我们还将我们的模型加入了ILSVRC-2012竞赛,并将结果报告在表2中。由于ILSVRC-2012测试集标签不是公开可用的,所以我们无法报告我们所尝试的所有模型的测试错误率。在这段剩下的部分,我们交替使用验证和测试错误率,因为在我们的经验中,它们的差异不超过0.1%(见表2)。本文中描述的CNN达到了18.2%的前5名错误率。对5个相似cnn的预测进行平均,错误率为16.4%。训练一个CNN,在最后一个池化层上再加一个第六层卷积,对整个ImageNet Fall 2011发布(15M张图片,22K个类别)进行分类,然后在ILSVRC-2012上进行“微调”,错误率为16.6%。将2011年秋季发布的两个预先训练过的cnn的预测与上述五个cnn的预测平均起来,错误率为15.3%。第二好的参赛作品获得了26.2%的错误率,该方法对从不同类型的密集采样特征[7]计算的fv上训练的几个分类器的预测进行了平均。

最后,我们还报告了2009年秋季版ImageNet的10184个类别和890万张图片的错误率。在这个数据集上,我们遵循文献中使用一半图像用于训练,一半图像用于测试的惯例。由于没有建立的测试集,我们的分割必然不同于以前作者使用的分割,但这不会明显影响结果。我们在这个数据集上的前1和前5的错误率分别是67.4%和40.9%,这是通过上面描述的网络实现的,但在最后一个池化层上增加了一个额外的第六卷积层。在这个数据集上发表的最佳结果分别是78.1%和60.9%[19]。
在这里插入图片描述
图3:第一个卷积层在224×224×3输入图像上学习到大小为11×11×3的96个卷积核。前48个内核在GPU 1上学习,后48个内核在GPU 2上学习。详见6.1节。

6.1 定性评估

图3显示了网络的两个数据连接层学习到的卷积核。该网络已经学习了各种频率和方向选择内核,以及各种彩色斑点。请注意两个gpu表现出的专门化,这是第3.5节中描述的受限连接的结果。GPU 1上的内核基本上是颜色无关的,而GPU 2上的内核基本上是颜色特定的。这种专门化发生在每次运行期间,并且独立于任何特定的随机权重初始化(对gpu的重编号取模)。

在图4的左面板中,我们通过计算8张测试图像的前5个预测,定性地评估了网络已经学习到什么。注意,即使是偏离中心的物体,如左上角的螨,也能被网识别出来。前5个标签中的大多数看起来都是合理的。例如,只有其他类型的猫被认为是豹的合理标签。在某些情况下(格栅,樱桃)对于照片的预期焦点确实是模棱两可的。

另一种探测网络视觉知识的方法是考虑最后一个4096维的隐藏层的图像所引起的特征激活。如果两幅图像通过小的欧氏分离产生特征激活向量,我们可以说,神经网络的高层认为它们是相似的。图4显示了来自测试集的五幅图像,以及根据这个度量,来自训练集的六幅与它们最相似的图像。注意,在像素级,L2中检索到的训练图像通常不接近第一列中的查询图像。例如,检索到的狗和大象以各种姿势出现。我们在补充材料中给出了更多测试图像的结果。

通过使用两个4096维实值向量之间的欧氏距离来计算相似度是低效的,但可以通过训练一个自动编码将这些向量压缩成短二进制码来提高效率。这将产生一个比对原始像素[14]应用自动编码器更好的图像检索方法,该方法不使用图像标签,因此有检索具有相似边缘模式的图像的倾向,无论它们是否语义相似。

7 讨论

我们的结果表明,使用纯监督学习,一个大型的深度卷积神经网络能够在一个极具挑战性的数据集上获得破纪录的结果。值得注意的是,如果去掉一个卷积层,我们的网络性能就会下降。例如,删除任何中间层将导致网络前1位性能损失约2%。所以深度对于我们的成果非常重要。

为了简化我们的实验,我们没有使用任何无监督的预训练,尽管我们希望它会有帮助,特别是当我们获得足够的计算能力来显著增加网络的规模,而没有获得相应的标记数据量时。到目前为止,随着我们的网络变得更大,训练时间更长,我们的结果已经有所改善,但为了匹配人类视觉系统的颞下路径,我们仍有许多数量级的工作要做。最终,我们希望在视频序列上使用非常大和深度的卷积网络,其中时间结构提供了非常有用的信息,这些信息在静态图像中缺失或不那么明显。

原论文

ImageNet Classification with Deep Convolutional Neural Networks

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值