【论文翻译】Visualizing and Understanding Convolutional Networks ECCV 2014

Visualizing andUnderstanding Convolutional Networks

卷积神经网络的可视化理解

Matthew D. Zeiler zeiler@cs.nyu.edu 纽约大学计算机科学系Courant研究所

Rob Fergus fergus@cs.nyu.edu 纽约大学计算机科学系Courant研究所

 

摘要(Abstract)

近来,大型的卷积神经网络模型在Imagenet数据集上表现出了令人印象深刻的效果(如2012年的Krizhevsky),但是现如今大家并没有很清楚地理解为什么它们有如此好的效果,以及如何改善其效果。在这篇文章中,我们对这两个问题均进行了讨论。我们介绍了一种创新性的可视化技术可以深入观察中间的特征层函数的作用以及分类器的行为。作为一项类似诊断性的技术,可视化操作可以使我们找到比Krizhevsky (ALexNet模型)更好的模型架构。在Imagenet分类数据集上,我们还进行了一项抽丝剥茧的工作,以发现不同的层对结果的影响。我们看到,当softmax分类器重训练后,我们的模型在Imagenet数据集上的结果可以很好地泛化到其他数据集,瞬间就击败了现如今caltech-101以及caltech-256上的最好的方法。

 

1、介绍(Introduction)

自从1989年LeCun等人研究推广卷积神经网络(以下称为CNN)之后,在1990年代,CNN在一些图像应用领域展现出极好的效果,例如手写字体分类,人脸识别等等。在去年,许多论文都表示他们可以在一些更有难度的数据集上取得较好的分类效果,Ciresan 等人于2012在NORB和CIFAR-10数据集上取得了最好的效果。更具有代表性的是Krizhevsky等人2012的论文,在ImageNet 2012数据集分类挑战中取得了绝对的优势,他们的错误率仅有16.4%,与此相对的第二名则是 26.1%。造成这种有趣的现象的因素很多:(i)大量的训练数据和已标注数据; (ii) 强大的GPU训练 (iii) 更好的正则化方法如Dropout(Hinton et al., 2012)。

尽管如此,我们还是很少能够深入理解神经网络中的机理,以及为何它们能取得如此效果。从科学的角度讲,这是远远不够的。如果没有清楚地了解其中的本质,那么更好的模型的开发就只能变成整天像无头苍蝇一样乱试。在本文中,我们介绍一种可视化技术来揭示输入响是应如何在每一层得到独得的特征图谱的。这也能让我们观察到特征在训练过程中的进化过程,以便分析出模型的潜在问题。我们使用的可视化技术是一种多层的反卷积网络,由Zeiler在2011年提出,把特征激活映射回输入像素空间。我们还进行了一项很有意义的研究,那就是遮挡输入图像的一部分,来说明哪一部分是对分类最有影响的。

使用这些方法,我们从Krizhevsky模型的体系结构开始,逐步探索了其他不同模型的体系结构,发现他们的性能优于Imagenet上的结果。我们还探索了不同数据集上模型的泛化能力,仅依靠在上面重新训练softmax层。因此,我们这儿讨论的是一种有监督的预训练形式,与Hinton 和Bengio,Vincent等人推广的无监督的训练方法不同。另外convnet特征的泛化能力的讨论在Donahue的2013的论文中也有探讨到。

 

1.1. 相关工作(Related Work)

通过对神经网络可视化方式来获取一些科研灵感是很常有的做法,但大多都局限于第一层,因为第一层比较容易映射到像素空间。在较高的网络层就难以处理了,只有有限的解释节点活跃性的方法。Erhan等人2009的方法,通过在图像空间中执行梯度下降以最大化单元的激活来找到每个单元的最大响应刺激方式。这需要很细心的操作,而且也没有给出任何关于单位某种恒定属性的信息。受此启发有一种改良的方法,(Le et al, 2010)在(Berkes & Wiskott,2006)的基础上作一些延伸,通过计算一个节点的Hessian矩阵来观测节点的一些稳定的属性,问题在于对于更高层次而言,不变性非常复杂,因此通过简单的二次近似法(quadratic approximation)很难描述。相反,我们的方法提供了非参数化的不变性视图,显示了训练集中的哪些模式激活了特征映射。(Donahue等,2013)显示了可视化,看可视化结果能表明模型中高层的节点究竟是被哪一块区域给激活。我们的可视化效果不同,因为它们不仅仅是输入图像的作物,而是自上而下的投影,它揭示了每个补丁内的结构,这些结构会刺激特定的特征图谱。

 

2. 我们的方法(Approach)

正如LeCun等人(1989)和(Krizhevsky等人,2012)所定义的那样,我们在整篇论文中使用标准的完全监督的convnet模型。这些模型将彩色2D输入图像通过一系列图层映射到个不同类别上的概率矢量。每一层由(i)前一层输出(或者在第一层的情况下,输入图像)与一组学习滤波器的卷积组成;(ii)通过整数线性函数()传递响应; (iii)[可选地]最大化汇集在当地邻域上,和(iv)[可选地]局部对比操作,其对特征映射上的响应进行归一化。有关这些操作的更多详细信息,请参阅(Krizhevsky等,2012)和(Jarrett等,2009)。神经网络的顶层是传统的全连接网络,最后一层是softmax分类器。图3显示了我们实验中使用最多的模型。

我们使用大量个标记图像来训练这些模型,其中标签是指示真实类别的离散变量。交叉熵损失函数适用于图像分类,用于比较和。网络参数(卷积层中的滤波器,完全连接层中的权重矩阵和偏差)通过反向传播相对于整个网络中的参数的损失的导数并通过随机梯度下降来更新参数来训练。第3节给出了详细的内容。

 

2.1. 反卷积可视化(Visualizationwith a Deconvnet)

了解一个卷积的操作需要解释中间层的特征激活。我们提出了一种将这些特征响应映射回输入像素空间的新方法,显示了最初在特征映射中引起给定激活的输入模式。我们用反卷积网络(deconvnet)执行这种映射(Zeiler et al。,2011)。一个deconvnet可以被认为是一个使用相同组件(过滤,池化)但相反的convnet模型,所以不是将像素映射到要素而是相反。在(Zeiler et al。,2011)中,提出了deconvnets作为执行无监督学习的一种方式。在这里,他们没有被用于任何学习能力,只是作为一个已经训练的卷积网络的转折点的探索。

为了检查一个卷积网络,将一个反卷积(deconvnet)附加到它的每个图层上,如图1(顶部)所示,为回到图像像素提供一条连续的路径。首先,将输入图像呈现给convnet,并在整个图层中计算特征。为了检查给定的卷积网络激活,我们将图层中的所有其他激活设置为零,并将该功能图作为输入传递给附加的反卷积层。然后我们通过(i)反池化,(ii)纠正和(iii)过滤以重新构建所选激活下的图层中的活动。然后重复此操作直至达到输入像素空间。

反池化:在最小化池中,最大池操作是不可逆的,但是我们可以通过在一组开关变量中记录每个池区中最大值的位置来获得近似反转。在deconvnet中,反池化操作使用这些开关将来自上一层的重建放置到合适的位置,从而保留刺激的结构。参见图1(下图)以了解该过程。

纠正:该convnet使用relu非线性函数,纠正特征映射,从而确保特征映射总是正的。 为了在每一层获得有效的特征重建(也应该是正的),我们通过非线性传递重建的信号。

过滤:小网络使用学习过的滤波器来卷积上一层的特征映射。为了反转这种情况,deconvnet使用相同过滤器的转置版本,但应用于纠正过的图,而不是下面图层的输出。在实践中,这意味着垂直和水平地翻转每个过滤器。

从较高层向下投影使用由convnet中的最大池所产生的交换设置。由于这些开关设置对于给定的输入图像是独特的,因此从单次激活获得的重建类似于原始输入图像的一小部分,并且结构根据它们对特征激活的贡献而加权。由于模型是有判别性地训练的,因此它们隐含地显示输入图像的哪些部分是有判别性的。请注意,这些预测不是来自模型的样本,因为没有涉及生成过程。

图1.顶部:连接到一个反卷积层(左侧)(右侧)。反卷积层将从下面的图层重建大致的版本。底部:在deconvnet中使用交换机进行反池化操作的示意图,该交换机记录了在convnet中进行池化期间每个池区中的本地max(彩色区域)的位置。

 

3.训练细节 (Training Details)

我们现在描述将在第4节中可视化的大型convnet模型。图3所示的架构与(Krizhevsky等,2012)用于ImageNet分类的架构相似。一个不同之处在于Krizhevsky层3,4,5中使用的稀疏连接(由于模型被分割成2个GPU)在我们的模型中被密集连接所取代。其他重要的与层1和层2有关的差异是在检查如4.1节所述的图6中的可视化。

该模型在ImageNet 2012培训集上进行了培训(130万张图片,分布在1000多个不同的类中)。通过将最小尺寸调整为256,裁剪中心256x256区域,减去每像素平均值(横跨所有图像),然后使用10个不同尺寸为224x224的子作物(角落+中心与水平(外))预处理每个RGB图像FL IPS)。使用随机梯度下降,最小批量为128,用于更新参数,从学习率0.01开始,结合动量项0.9。当验证错误高原时,我们在整个培训中手动退化学习速率。在完全连接层(6和7)中使用辍学率(Hinton et al。,2012),比率为0.5。所有权重初始化为0.01,偏差设置为0。

如图6(a)所示,训练过程中第一层过滤器的可视化表明其中一些占主导地位。为了解决这个问题,我们将RMS值超过固定半径的卷积层中的每个滤波器重新归一化到这个固定的半径。这是至关重要的,特别是在模型的第一层,输入图像大致在范围内。 正如(Krizhevsky et al。,2012)那样,我们在每个训练样例中生成多个不同作物和flips来提高训练集大小。我们停止使用基于(Krizhevsky et al。,2012)的70个时期的训练,这个时代在单个GTX580 GPU上花费了大约12天的时间。

图3.我们的8层convnet模型的体系结构。输入是224×224的子图像(具有3个颜色维度)。第一层有96个不同的过滤器(红色),每个的大小为7*7,步长为2。然后得到的特征图如下:(i)通过一个纠正线性函数(未显示),(ii)池化(使用步幅2的3×3区域内的最大值)和(iii)在特征映射上归一化对比度,得到96个不同的55*55的要素特征映射。层2,3,4,5中重复以上操作。最后两层全连接,将顶部卷积层的特征作为向量形式的输入(6·6·256= 9216维)。最后一层是C类softmax函数,C是类的数量。所有过滤器和功能图均为正方形。

 

4.卷积网络可视化(ConvnetVisualization)

使用第3节中描述的模型,我们现在使用反卷积来可视化ImageNet验证集上的特征激活。

特征可视化:图2显示了训练完成后我们模型的特征可视化。然而,我们不是显示给定特征映射的单一最强激活,而是显示前9个激活。分别向下投影到像素空间显示激发给定特征映射的不同结构,因此显示其对输入变形的不变性。除了这些可视化之外,我们还会显示相应的图像补丁。这些比可视化具有更大的变化,因为后者仅关注每个补丁内的判别结构。例如,在第5层第1行第2列中,这些补丁似乎没有什么共同之处,但可视化显示此特定特征映射侧重于背景中的草地,而不是前景对象。

图2.完全培训模型中的特征可视化。对于第2-5层,我们使用我们的反卷积网络方法在验证数据中显示特征映射的随机子集中的前9个激活,并将其投影到像素空间。我们的重建不是来自模型的样本:它们是来自验证集的重构模式,可在给定的特征映射中导致高激活。对于每个特征映射,我们还显示相应的图像补丁。注意:(i)每个特征图内的强分组,(ii)越高层不变性更大和(iii)图像的判别区域的夸大,例如眼睛和狗的鼻子(第4层,第1行,第1列)。以电子形式最好看。

来自每个层的投影显示网络中的特征的分层性质。 第2层响应角落和其他边缘/颜色连词。第3层具有更复杂的不变性,捕获相似的纹理(例如网格图案(第1行,第1列);文本(R2,C4))。第4层显示了显著的变化,但更多的是类特定的:狗脸(R1,C1);鸟的腿(R4,C2)。层5显示具有显著姿势变化的整个对象,例如,键盘(R1,C11)和狗(R4)。

训练期间的特征演变:图4可视化了投影回像素空间的给定的特征映射内的最强激活(在所有训练示例中)的训练过程的进展。外观突然跳跃是由于最强激活源自的图像发生变化而引起的。可以看出模型的较低层在几个时期内汇合。然而,在相当数量的时期(40-50)之后,上层才开始发展,表明需要让模型训练直到完全收敛。

图4.随机选择的模型特征子集通过训练的演变。每个图层的特征都显示在不同的块中。在每个块中,我们在时期[1,2,5,10,20,30,40,64]显示随机选择的特征子集。可视化显示了给定特征映射的最强激活(在所有训练示例中),使用我们的反卷积方法投影到像素空间。色彩对比度是人为增强的,图形最好以电子形式查看。

特征不变性:图5示出了5个样本图像在查看相对于未改变的特征,来自模型的顶层和底层的特征矢量变化的同时被不同程度地平移,旋转和缩放。小的变换对模型的第一层有着显著的效果,但是对上面特征层的影响较小,平移和缩放是拟线性的。网络的输出在平移和缩放时是稳定的。一般来说,除了旋转对称的物体(例如娱乐中心)外,输出不是旋转不变的。

图5.分析模型内的垂直平移,缩放和旋转不变性(分别为a-c行)。第1列:5个样本图像正在进行转换。第2和3列:分别来自第1层和第7层的原始和变换图像的特征向量之间的欧几里德距离。第4列:图像被转换时,每个图像的真实标签的概率。

 

4.1结构选择(ArchitectureSelection)

虽然可视化训练过的模型可以深入了解其操作,也可以帮助选择好的体系结构。但是通过观察AlexNet网络的第一层和第二层,(图6(b)和(d)),各种问题都很明显。第一层滤波器有特别高频和低频的信息,却几乎没有中频信息。另外,第二层可视化显示了第一层卷积中使用步长为4的过滤器引起的频谱混叠。为了解决这些问题,我们(i)将第一层过滤器的尺寸从11x11减小到7x7,并且(ii)使卷积的步长变为2,而不是4。这种新的结构在第一和第二层特征中保留了更多的信息,如图6(c)和(e)所示。更重要的是,它也提高了分类性能,如5.1节所示。

图6.(a):没有缩放裁剪特征的第一层特征。注意到一个特征占主导地位。(b):(Krizhevsky等,2012)的第一层特征。(c):我们的第一层特征。较小的步幅(2 vs 4)和过滤器尺寸(7x7 vs 11x11)会导致更多鲜明的特征和更少的“死亡”特征。(d):(Krizhevsky等人2012)的第二层特征的可视化。(e):我们的第二层特征的可视化。(d)中可以看到这些更清晰,没有频谱混叠。

 

4.2.遮挡灵敏度(OcclusionSensitivity)

对于图像分类方法,存在这样的问题:模型是正确的识别出了图像中对象的位置,还是只是通过周围环境进行识别。图7试图通过系统地用灰色正方形遮挡输入图像的不同部分来回答这个问题,并检测分类器的输出。这些例子清楚地表明该模型将场景中的对象本地化,因为当对象被遮挡时正确的类的概率显著下降。图7还显示了来自顶部卷积层的最强特征映射的可视化,此外,将该映射中的激活(在空间位置上求和)作为遮挡器位置的函数。当遮挡器覆盖可视化中出现的图像区域时,我们看到特征映射激活的强度下降。这表明可视化真正对应于刺激该特征映射的图像结构,因此验证了图4和图2所示的其他可视化。

图7.三个测试示例,我们用灰色正方形(第1列)系统地遮盖场景的不同部分,并查看顶部(第5层)特征映射((b)和(c))和分类器输出((d )&(e))的变化。(b):对于灰度的每个位置,我们记录第5层的一个特征映射(在未被遮挡的图像中具有最强响应的一个)中的总激活。(c):将此特征映射投影到输入图像(黑色正方形)的可视化图,以及其他图像的可视化图。第一行显示最强的特征是狗的脸。当这被遮盖时,特征映射中的激活减少((b)中的蓝色区域)。(d):作为灰色方块位置的函数的正确类概率图。例如。当狗的脸变得模糊时,“博美犬”的概率显著下降。(e):最可能的标签作为遮挡器位置的函数。例如。在第一行,最多的位置是“博美犬”,但如果狗的脸部被遮挡而不是球,那么它会预测“网球”。在第二个例子中,汽车上的文本是第5层中最强的特征,但分类器对车轮最为敏感。第三个示例包含多个对象。第5层中最强的特征挑选出了人脸,但分类器对狗((d)的蓝色区域)敏感,因为它使用了多个特征映射。

 

4.3.相关性分析(CorrespondenceAnalysis)

图8.用于对应实验的图像。列1:原始图像。第2,3,4列:分别遮挡右眼,左眼和鼻子。其他列显示随机遮挡的例子。

表1.在5种不同狗图像中测量不同物体部分的对应关系。(与随机对象部分相比)眼睛和鼻子的得分较低表明模型隐含地建立了模型中第5层的部分对应关系。在第7层,评分更相似,可能是由于上层试图区分不同品种的狗。

 

5. 实验(Experiments)

5.1. ImageNet 2012

该数据集包含1.3M / 50k /100k个培训/验证/测试样本,分布在1000多个类别中。表2显示了我们上这个数据集上的结果。

使用(Krizhevsky et al。,2012)中指定的确切的体系结构,我们试图在验证集上复制它们的结果。我们达到的误差率和他们在ImageNet 2012验证集中报告的值的误差不到0.1%。

接下来我们分析在4.1节中概述的改变架构(第1层中使用7×7滤波器,1、2层中卷积步长为2)的模型性能。图3所示模型,显著优于(Krizhevsky等人,2012)的体系结构,将其单一模型结果击败了1.7%(测试前五名)。当我们组合多个模型时,我们获得14.8%的测试误差,这是该数据集上发布的最佳性能(尽管只使用了2012年的训练集)。我们注意到,这个错误率几乎是ImageNet 2012分类挑战中最重要的non-convnet条目26.2%的错误率(Gunji et al。,2012)的一半。

表2.ImageNet 2012分类错误率。 *表示在ImageNet 2011和2012训练集上都进行了训练。

改变ImageNet模型的大小:在表3中,我们首先通过调整层的大小或完全去除它们来探索(Krizhevsky et al。,2012)的体系结构。在每一种情况下,模型都是从头开始用修改后的架构进行培训的。去除全连接层(6,7)只增加了轻微的误差。这是令人惊讶的,因为它们包含大部分模型参数。移除中间的两个卷积层队差错率影响也相对较小。但是,除去全部的中间卷积层和全连接层产生的只有4层的模型的性能显著变差。这表明模型的整体深度对于获得良好性能很重要。在表3中,我们修改了我们如图3的模型。改变全连接层的大小对性能几乎没有影响(对于(Krizhevsky et al。,2012)模型也是如此)。但是,增加中间卷积层的大小可以提高性能。但增加这些的同时,也增大了全连接层过度拟合。

表3.ImageNet 2012分类错误率(Krizhevskyet al。,2012)和我们的模型(见图3)的各种体系结构变化。

 

5.2.特征泛化(FeatureGeneralization)

上面的实验显示了我们的ImageNet模型的卷积部分在获得最新性能方面的重要性。这由图2的可视化支持,它显示了卷积层中的复杂不变性。我们现在探索这些特征提取层的能力,以推广到其他数据集,即Caltech-101(Feifei等人,2006),Caltech-256(Grifffi等人,2006)和PASCAL VOC 2012。为此,我们将我们的ImageNet训练的模型的第1-7层固定并使用新数据集的训练图像在最上面训练一个新的softmax分类器(使用适当的类别数)。由于softmax包含的参数相对较少,因此可以从相对较少的示例中快速训练,如某些数据集的情况。

我们的模型(softmax)和其他方法(通常是线性SVM)使用的分类器具有相似的复杂性,因此实验将我们从ImageNet学习到的特征表示与其他方法使用的手工标注的特征进行比较。需要注意的是,我们的特征表示和手工标注的特征都是使用Caltech和PASCAL训练集的图像设计的。例如,HOG描述中的超参数是通过对行人数据集进行系统实验确定的(Dalal&Triggs,2005)。我们还尝试了第二种从头开始训练模型的策略,即将层1-7重新设置为随机值,并在数据集的训练图像上训练它们以及softmax。

其中一个复杂因素是Caltech数据集中有一些图像也在ImageNet训练数据中。使用归一化相关性,我们确定了这些“重叠”图像,并将其从我们的Imagenet训练集中移除,然后重新训练我们的Imagenet模型,从而避免训练/测试污染的可能性。

 

Caltech-101:我们遵循(Fei-fei等,2006)的程序,每类随机选择15或30幅图像进行训练,每类测试50幅图像,表4中报告了每类准确度的平均值,使用5次训练/测试折叠。训练30张图像/类的数据用时17分钟。预先训练的模型在30幅图像/类上的结果比(Bo et al。,2013)的成绩提高2.2%。然而,从零开始训练的convnet模型非常糟糕,只能达到46.5%。

表4.针对我们的convnet模型的Caltech-101分类精度,与两种领先的替代方法对比。

Caltech-256:我们按照(Gri ffi等,2006)的程序,为每个类选择15,30,45或60个训练图像,表5中报告了每类精度的平均值。我们的ImageNet预训练模型在每类60训练图像上以74.2%比55.2%的显著差别击败了Bo等人获得的当前最先进的结果。(Bo et al。,2013)。但是,与Caltech-101一样,从零开始训练的模型效果并不理想。在图9中,我们探讨了“一次性学习”(Fei-fei et al。,2006)制度。使用我们的预训练模型,只需要6张Caltech-256训练图像即可击败使用10倍图像训练的先进的方法。这显示了ImageNet特征提取器的强大功能。

图9. Caltech-256分类性能,每个类的训练图像的数量是多变的。我们的预训练特征提取器仅使用6个训练样例,我们超过了(Bo et al。,2013)达到的最佳结果。

表5.Catech 256分类精度。

PASCAL 2012:我们使用标准的训练和验证图像在ImageNet预训练的网络顶部训练20类softmax。这并不理想,因为PASCAL图像可以包含多个对象,而我们的模型仅为每个图像提供一个单独的预测。表6显示了测试集的结果。PASCAL和ImageNet的图像本质上是完全不同的,前者是完整的场景而后者不是。这可能解释我们的平均表现比领先(严等人,2012)的结果低3.2%,但是我们确实在5类的结果上击败了他们,有时甚至大幅度上涨。

表6.PASCAL 2012分类结果,比较了我们Imagenet预训练的方法与两种领先的方法([A] =(Sande et al。,2012)和[B] =(Yan et al。,2012))。

 

5.3.特征分析(Feature Analysis)

我们研究了Imagenet预训练模型在每一层是如何区分特征的。我们通过改变ImageNet模型中的层数来完成这一工作,并将线性SVM或softmax分类器置于顶层。表7显示了Caltech101和Caltech-256的结果。对于这两个数据集,随着我们提升模型,可以看到一个稳定的改进,使用所有层可以获得最佳结果。这支持这样一个前提,即随着特征层次越来越深,他们将学习越来越强大的特征。

表7.我们的ImageNet预训练网络内每层特征映射中包含的区分信息分析。我们对来自卷积网络的不同层(如括号中所示)的特征进行线性SVM或softmax训练。较高层通常会产生更多区分性特征。

 

6.讨论(Discussion)

我们以多种方式探索了大型卷积神经网络模型,并对图像分类进行了训练。首先,我们提出了一种新颖的方式来可视化模型中的活动。这揭示了这些特征远不是随机的,不可解释的模式。相反,提升模型时,它们显示出许多直观上令人满意的属性,例如组合性,增加不变性和类别区别等。我们还展示了如何使用这些可视化来调试模型的问题以获得更好的结果,例如改进(Krizhevsky et al。,2012)令人印象深刻的ImageNet 2012结果。然后,我们通过一系列遮挡实验证明,该模型虽然训练了分类,但对图像局部结构高度敏感,并不仅仅使用广阔的场景环境。对该模型的进一步研究表明,对网络而言,具有最小的深度而不是任何单独的部分对模型的性能至关重要。

最后,我们展示了ImageNet训练模型如何很好地推广到其他数据集。对于Caltech-101和Caltech-256,数据集足够相似,以至于我们可以击败最好的结果,在后一种情况下,结果有一个显著的提高。这个结果带来了对具有小(数量级1000)训练集的基准效用的问题。我们的convnet模型对PASCAL数据的推广程度较差,这可能源于数据集偏差(Torralba&Efros,2011),虽然它仍处于报告的最佳结果的3.2%之内,尽管没有调整任务。例如,如果允许对每个图像的多个对象的使用不同的损失函数,我们的性能可能会提高。这自然也能使网络能够很好的处理对象检测。

 

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值