第六章 MobileNetv1网络详解

系列文章目录

第一章 AlexNet网络详解

第二章 VGG网络详解

第三章 GoogLeNet网络详解 

第四章 ResNet网络详解 

第五章 ResNeXt网络详解 

第六章 MobileNetv1网络详解 

第七章 MobileNetv2网络详解 

第八章 MobileNetv3网络详解 

第九章 ShuffleNetv1网络详解 

第十章 ShuffleNetv2网络详解 

第十一章 EfficientNetv1网络详解 

第十二章 EfficientNetv2网络详解 

第十三章 Transformer注意力机制

第十四章 Vision Transformer网络详解 

第十五章 Swin-Transformer网络详解 

第十六章 ConvNeXt网络详解 

第十七章 RepVGG网络详解 

第十八章 MobileViT网络详解 


文章目录

  •  MobileNetv1网络详解
  • 0. 前言
  • 1. 摘要
  • 2.   MobileNetv1网络详解网络架构
    • 1.  MobileNetv1_Model.py(pytorch实现)
    • 2.
  • 总结


0、前言


1、摘要

      我们提出了 MobileNets 这类高效模型,专门用于移动和嵌入式视觉应用。MobileNets 基于一种简化的架构,利用深度可分离卷积构建轻量级深度神经网络。我们引入了两种简单的全局超参数,可以高效地权衡延迟和准确性。这些超参数允许模型构建者根据问题的约束条件选择适合其应用的正确大小的模型。我们对资源和准确性进行了广泛的实验,并展现了在 ImageNet 分类方面与其他受欢迎的模型相比的强大性能。我们随后展示了 MobileNets 在广泛应用和用例中的有效性,包括对象检测、细粒度分类、面部属性和大规模地理定位。

2、MobileNetv1网络结构

1. 本文介绍了一种名为MobileNets的高效模型,可以用于移动和嵌入式视觉应用。

2. 本文的研究背景是为了提高移动和嵌入式设备上的视觉应用的运行效率和准确性。

3. 本文的主要论点是MobileNets模型使用深度可分离卷积构建轻型深度神经网络,并且引入了有效的全局超参数来平衡延迟和准确性之间的权衡。

4. 以往的研究方法包括基于卷积神经网络的模型,但其对移动和嵌入式设备的限制较大并且计算效率较低。方法存在的问题是难以在准确性和运行效率之间平衡。

5. 本文提出了一种基于深度可分离卷积的模型架构和有效的全局超参数来平衡延迟和准确性,用于构建轻量级深度神经网络。

6. 实验结果表明,MobileNets模型在资源和准确性之间具有较强的平衡性,并且在ImageNet分类等任务上取得了较好的表现。该模型也适用于多种应用场景,包括目标检测、细粒度分类、人脸属性和大规模地理定位。然而,本研究仍存在一些限制,例如在一些复杂应用场景下准确性仍有待提高。

3.论文亮点(MobileNets(v1) Lightspot:)


1. Depthwise Convolution(大大减少了运算量和参数数量)
2.Increment Hyperparameter(α(控制卷积层卷积核个数)、β(控制图像大小) )

 4.论文详解

Pointwise卷积是一种1×1卷积核,通常被用作深度可分离卷积中的第二个步骤。它被称为点卷积,因为它只在每个像素点上执行卷积操作。该卷积操作可以将深度可分离卷积中处理后得到的特征图降维或升维,以便进一步处理需要更多或更少的通道。

 

1 基于FaceNet模型的MobileNet

Table 1.MobileNet Body Architecture

类型/步长

卷积核形状

输入形状

Conv / s2

3 × 3 × 3 × 32

224 × 224 × 3

Conv dw / s1

3 × 3 × 32 dw

112 × 112 × 32

Conv / s1

1 × 1 × 32 × 64

112 × 112 × 32

Conv dw / s2

3 × 3 × 64

112 × 112 ×64

Conv / s1

1 × 1 × 64 × 128

56 × 56 × 64

Conv dw / s1

3 × 3 × 128 dw

56 × 56 × 128

Conv / s1

1 × 1 × 128 × 128

56 × 56 × 128

Conv dw / s2

3 × 3 × 128 dw

56 × 56 × 128

Conv / s1

1 × 1 × 128 × 256

28 × 28 × 128

Conv dw / s1

3 × 3 × 256 dw

28 × 28 × 256

Conv / s1

1 × 1 × 256 ×256

28 × 28 × 256

Conv dw / s2

3 × 3 × 256 dw

28 × 28 × 256

Conv / s1

1 × 1 × 256 ×512

14 × 14 × 256

5 × Conv dw / s1

      Conv / s1

3 × 3 × 512 dw

1 × 1 × 512 ×512

14 × 14 × 512

14 × 14 × 512

Conv dw / s2

3 × 3 × 512 dw

14 × 14 × 512

Conv / s1

1 × 1 × 512 ×1024

7 × 7 × 512

Conv dw / s1

3 × 3 × 1024 dw

7 × 7 × 1024

Conv / s1

1 × 1 × 1024 ×1024

7 × 7 × 1024

Avg Pool / s1

Pool 7 × 7

7 × 7 × 1024

FC / s1

1024 × 1000

1 × 1 × 1024

Softmax / s1

Classifier

1 × 1 × 1000

MobileNet结构是建立在深度可分离卷积的基础之上,除了第一层是全卷积层。通过这样简单的网络定义,我们能够轻松地探索网络拓扑,找到优秀的网络。MobileNet结构在表1中定义。所有层都跟随着一个batchnorm [13]和ReLU非线性,但最后一个全连接层没有非线性,而是进入一个softmax层进行分类。图3对比了使用常规卷积、batchnorm和ReLU非线性的层和使用深度卷积、1×1点卷积以及每个卷积层后都加上batchnorm和ReLU的分解层。使用深度可分离卷积和第一层的步长卷积来进行下采样。最后进行平均池化将空间分辨率降低至1,然后进入全连接层。MobileNet共有28层,包括深度和点卷积在内。

2不同类型所需资源

Table 2.Resource Per Layer Type

类型

乘法加法

参数数量

Conv 1 × 1

94.86%

74.59%

Conv DW 3 × 3

3.06%

1.06%

Conv 3 × 3

1.19%

0.02%

Fully Connected

0.18%

24.33%

仅仅用少数的Mult-Adds定义网络是不够的,还必须确保这些操作可以被高效地实现。例如,非结构化稀疏矩阵操作通常不比密集矩阵操作快,除非达到非常高的稀疏度。我们的模型结构将几乎所有计算都放入了密集的1×1卷积中。这可以使用高度优化的常规矩阵乘法(GEMM)函数来实现。通常,卷积是通过GEMM来实现的,但需要在内存中进行初始重新排列,称为im2col,以将其映射到GEMM。例如,这种方法在流行的Caffe软件包[15]中使用。1×1卷积不需要进行这种内存重新排列,并且可以直接使用GEMM实现,这是最优化数值线性代数算法之一。MobileNet的95%的计算时间都花在1×1卷积上,而参数的75%如表2所示。几乎所有的额外参数都在完全连接的层中。MobileNet模型是使用TensorFlow[1]和异步梯度下降的RMSprop[33]训练的,类似于Inception V3 [31]。然而,与训练大型模型相反,我们使用较少的正则化和数据增强技术,因为小型模型不易过拟合。在训练MobileNets时,我们不使用侧面头或标签平滑,并通过限制用于大型Inception训练的小剪辑的大小,进一步减少图像扭曲的数量。此外,我们发现对于深度滤波器很少的情况下,应该很少或不使用权重衰减(l2正则化)。在下一节的ImageNet基准测试中,所有模型都使用相同的训练参数进行训练,而不管模型的大小。

3标准卷积修改的资源使用情况,请注意每一行是在前一行的基础上叠加的累积效果。该示例是针对一个内部MobileNet(DK = 3M = 512N = 512DF = 14)

Table 3.Resource usage for modifications to standard convolution.Note that each row is a cumulative effect adding on top of the previous row.This example is for an internal MobileNet layer with DK =3,M =512,N =512,DF =14.

层/修改后

乘法加法计算量(百万)

参数数量(百万)

传统卷积

462

2.36

深度可分离卷积

52.3

0.27

α=0.75

29.6

0.15

β=0.714

15.1

0.15

尽管基本的 MobileNet 架构已经足够小和低延迟,但有时特定用例或应用程序可能需要模型更小、更快。为了构建这些更小、更少计算开销的模型,我们介绍了一个非常简单的参数 α,称为宽度乘数。宽度乘数 α 的作用是在每个层上均匀地减少网络。对于给定的层,宽度乘数 α 和输入通道数 M 成为 αM 和输出通道数 N 成为 αN。具有宽度乘数 α 的深度可分离卷积的计算成本为:DK ·DK ·αM ·DF ·DF +αM ·αN ·DF ·DF (6)其中 α2 (0;1],具有典型设置 1、0.75、0.5 和 0.25。α=1 是基线 MobileNet,α<1 是降低的 MobileNets。宽度乘数的效果是将计算成本和参数数量平方减少约 α2。可以将宽度乘数应用于任何模型结构,以定义一个新的较小模型,具有合理的精度。

第二个超参数用于减少神经网络计算成本的是分辨率乘数ρ。我们将其应用于输入图像,并随后将每个层的内部表示也同样按照乘数进行缩减。实际上,我们通过设置输入分辨率来隐式地设置ρ。现在,我们可以将核心层的计算成本表达为具有宽度乘数α和分辨率乘数ρ的深度可分离卷积:DK·DK·αM·ρDF·ρDF+αM·αN·ρDF·ρDF(其中ρ2(0;1],通常被隐式地设置为网络的输入分辨率为224、192、160或128。ρ=1是基线MobileNet,ρ<1是减少计算MobileNets。分辨率乘数的作用是通过ρ2减少计算成本。例如,我们可以查看MobileNet中的一个典型层,然后看看深度可分离卷积、宽度乘数和分辨率乘数如何降低成本和参数。表3显示了在序列应用架构缩小方法到该层时的计算和参数数量。第一行显示具有输入特征映射大小为14×14×512和内核K大小为3×3×512×512的全卷积层的倍加和和参数。在下一节中,我们将详细讨论资源和准确性之间的权衡。

4 深度分离与全卷积MobileNet模型在ImageNet百万级图片上的准确率、乘法操作数和参数数量比较。

Table 4.Depthwise Separable vs Full Convolution MobileNet

模型

ImageNet数据集上的准确率

乘法加法计算量(百万)

参数数量(百万)

全卷积MobileNet

71.7%

4866

29.3

MobileNet

70.6%

569

4.2

5 狭窄与浅层MobileNet模型对比

Table 5.Narrow vs Shallow MobileNet

模型

ImageNet数据集上的准确率

乘法加法计算量(百万)

参数数量(百万)

0.75 MobileNet

68.4%

325

2.6

浅层MobileNet

65.3%

307

2.9

6 MobileNet的宽度乘数表

Table 6.MobileNet Width Multiplie

宽度乘数(α)

ImageNet数据集上的准确率

乘法加法计算量(百万)

参数数量(百万)

1.0 MobileNet-244

70.6%

569

4.2

0.75 MobileNet-244

68.4%

325

2.6

0.5 MobileNet-24

63.7%

149

1.3

0.25MobileNet-244

50.6%

41

0.5

7 MobileNet分辨率表

Table 7.MobileNet Resolution

图像分辨率(β)

ImageNet数据集上的准确率

乘法加法计算量(百万)

参数数量(百万)

1.0 MobileNet-244

70.6%

569

4.2

1.0 MobileNet-192

69.1%

418

4.2

1.0 MobileNet-160

67.2%

290

4.2

1.0 MobileNet-128

64.4%

186

4.2

8 MobileNet与流行模型的比较

Table 8.MobileNet Comparison to Popular Models

模型

ImageNet数据集上的准确率

乘法加法计算量(百万)

参数数量(百万)

1.0 MobileNet-244

70.6%

569

4.2

GoogleNet

69.8%

1550

6.8

VGG 16

71.5%

15300

138

9小型MobileNet与流行模型的比较

Table 9.Smaller MobileNet Comparison to Popular Models

模型

ImageNet数据集上的准确率

乘法加法计算量(百万)

参数数量(百万)

0.50 MobileNet-160

60.2%

76

1.32

Squeezenet

57.5%

1700

1.25

AlexNet

57.2%

720

60

在本节中,我们首先探究深度卷积的效果,以及通过减少网络宽度而不是层数来选择缩小的影响。然后,我们展示了通过两个超参数(宽度乘数和分辨率乘数)来减小网络的权衡,并将结果与多个流行模型进行比较。接着,我们研究了MobileNets在多个不同应用中的应用。

首先,我们展示了MobileNet使用深度可分离卷积与使用完整卷积构建的模型的结果。在表4中,我们可以看到,在ImageNet的深度准确率提高1%时,使用深度可分离卷积可以极大地节省多次加法和参数。接下来,我们展示了将更薄的模型与使用较少层数的浅模型进行比较的结果。为了使MobileNet变得更浅,我们删除了表1中具有14×14×512特征尺寸的可分离滤波器的5层。在表5中,我们可以看到,以类似的计算和参数数量,使MobileNets变薄比使它们变浅产生的效果更好,效果提高了3%。表6展示了通过减小MobileNet架构的宽度乘子α来进行精度、计算和大小权衡的结果。当α=0.25时,精度平稳下降,架构太小。表7展示了通过训练具有降低输入分辨率的MobileNets的不同分辨率乘子来进行精度、计算和大小权衡的结果。在不同分辨率下,精度平稳下降。图4展示了由宽度乘子α2 f1;0.75;0.5;0.25g和分辨率f224;192;160;128g组成的16个模型的ImageNet精度和计算权衡结果。在α=0.25时,模型变得非常小,结果呈现对数线性跳跃。

10 MobileNetStanford Dogs数据集上的表现

Table 10. MobileNet for Stanford Dogs

模型

Top-1准确率

乘法加法计算量(百万)

参数数量(百万)

Inception V3

84%

5000

23.2

1.0 MobileNet-224

83.3%

569

3.3

0.75 MobileNet-224

81.9%

325

1.9

1.0 MobileNet-192

81.9%

418

3.3

0.75 MobileNet-192

80.5%

239

1.9

(Top-1准确率通常是指在分类问题中的指标之一,它是指模型在预测一个样本的正确类别时的准确率。具体地说,它指的是,在所有样本中,模型预测的概率最大的类别与实际所属类别相同的样本数占总样本数的比例。 例如,对于一个分类问题,如果总共有100个样本,模型预测出了其中的80个样本的正确类别,则它的Top-1准确率为80%。 需要注意的是,Top-1准确率只比较模型预测的最有可能的类别是否正确,而不关心其他可能的类别是否正确。因此,它可能会忽略了一些预测并不完全正确的情况,因此在某些情况下并不是完全可靠的指标。)

我们在Stanford Dogs数据集上训练MobileNet进行细粒度识别。我们扩展了[18]的方法,并从互联网上收集了比[18]更大但嘈杂的训练集。我们使用这个嘈杂的网络数据来预训练一个细粒度狗识别模型,然后在Stanford Dogs训练集上微调模型。Stanford Dogs测试集的结果在表10中。MobileNet几乎可以在大大降低计算和尺寸的情况下实现[18]的最先进结果。

11 PlaNet使用MobileNet架构的性能。百分比是在一定距离内定位到Im2GPS测试数据集的部分。原始PlaNet模型的数字是基于一个改进的架构和训练数据集的更新版本。​​​​​​​

Table 11.Performance of PlaNet using the MobileNet architec ture.Percentages are the fraction of the Im2GPS test dataset that were localized within a certain distance from the ground truth.The numbers for the original PlaNet model are based on an updated version that has an improved architecture and training dataset.

尺寸

Im2GPS技术

PlaNet

PlaNet  MobileNet

大陆(2500km)

51.9%

77.6%

79.3%

国家(750km)

35.4%

64.0%

60.3%

区域(200km)

32.1%

51.1%

45.2%

城市(25km)

21.9%

31.7%

31.7%

街道(1km)

2.5%

80.5%

11.4%

PlaNet是将确定照片拍摄位置的任务视为分类问题。该方法将地球划分为一组地理单元格,作为目标类,并对数百万个地理标记的照片进行卷积神经网络训练。PlaNet已被证明可以成功地定位各种照片,并且优于处理相同任务的Im2GPS[6,7]。我们使用MobileNet架构在相同数据上重新训练PlaNet。虽然基于Inception V3架构[31]的完整PlaNet模型具有5200万个参数和57.4亿个乘加,但MobileNet模型仅有1300万个参数,通常为300万个主体和1000万个最终层以及580,000个乘加。如表11所示,MobileNet版本提供的性能只略有降低,尽管更紧凑,仍然比Im2GPS表现要好得多。

12使用MobileNet架构进行面部属性分类。每一行对应不同的超参数设置(宽度乘数α和图像分辨率)。

Table 12.Face attribute classification using the MobileNet archi tecture.Each row corresponds to a different hyper-parameter set ting (width multiplier αand image resolution).

宽度乘数α/

图像分辨率β

平均准确率

(Average Precision)

乘法加法计算量(百万)

参数数量(百万)

1.0 MobileNet-224

88.7%

568

3.2

0.5 MobileNet-224

88.1%

149

0.8

0.25 MobileNet-224

87.2%

45

0.2

1.0 MobileNet-128

88.1%

185

3.2

0.5 MobileNet-128

87.7%

48

0.8

0.25 MobileNet-128

86.4%

15

0.2

Baseline

86.9%

1600

7.5

MobileNet的另一个用途是压缩具有未知或不常见训练程序的大型系统。在面部属性分类任务中,我们展示了MobileNet和蒸馏(一种深度网络的知识转移技术)之间的协同关系。我们试图使用MobileNet架构来缩小一个具有7500万个参数和160亿个Mult-Adds的大型面部属性分类器。该分类器是在类似于YFCC100M的多属性数据集上训练的。我们使用蒸馏技术来训练分类器模拟较大模型的输出,而不是真实标签,从而使其能够从大型(可能无限的)未标记数据集中进行训练。将蒸馏训练的可伸缩性和MobileNet的简单参数化相结合,最终系统不仅不需要正则化(例如重量衰减和提前停止),而且还表现出更好的性能。从Tab.12可以看出,基于MobileNet的分类器对于激进的模型缩小是有弹性的:它在属性之间实现了类似的平均平均精度(mean AP),同时只消耗1%的Multi-Adds。

13 使用不同框架和网络架构进行的COCO目标检测结果比较。mAP的报告以COCO主要挑战度量为基准(IoU=0.50:0.05:0.95时的AP)

Table 13.COCO object detection results comparison using differ ent frameworks and network architectures.mAP is reported with COCO primary challenge metric (AP at IoU=0.50:0.05:0.95)

框架/分辨率

模型

平均准确率

乘法加法计算量(十亿)

参数数量(百万)

SSD

300

Deeplab-VGG

21.1%

34.9

33.1

Inception V2

22.0%

3.8

13.7

MobileNet

19.3%

1.2

6.8

Faster-RCNN

300

VGG

22.9%

64.3

138.5

Inception V2

15.4%

118.2

13.3

MobileNet

16.4%

25.2

6.1

Faster-RCNN

600

VGG

25.7%

149.6

138.5

Inception V2

21.9%

129.6

13.3

MobileNet

19.8%

30.5

6.1

MobileNet可以作为现代目标检测系统中有效的基础网络。我们基于最近赢得了2016 COCO挑战赛的工作,报告了在COCO数据集上对MobileNet进行目标检测训练的结果。在表13中,MobileNet与VGG和Inception V2 [13]在Faster-RCNN [23]和SSD [21]框架下进行了比较。在我们的实验中,SSD采用300个输入分辨率(SSD 300),Faster-RCNN与300和600个输入分辨率(Faster-RCNN 300,Faster-RCNN 600)进行了比较。Faster-RCNN模型每个图像评估300个RPN提议框。这些模型都是在COCO train+val上进行训练,不包括8k个minival图像,并在minival上进行评估。 对于两种框架,MobileNet的计算复杂度和模型大小只有其他网络的一小部分,但实现了可比较的结果。

14 基于FaceNet模型的MobileNet

Table 14.MobileNet Distilled from FaceNe

模型

1e-4

准确率

乘法加法计算量(百万)

参数数量(百万)

FaceNet

83%

1600

7.5

1.0 MobileNet-160

79.4%

286

4.9

1.0 MobileNet-128

78.3%

185

5.5

0.75 MobileNet-160

75.2%

166

3.4

0.75 MobileNet-128

72.5%

108

3.8

FaceNet模型是一种最先进的人脸识别模型[25],它基于三元组损失构建人脸嵌入。为了构建一个移动的FaceNet模型,我们使用蒸馏技术通过最小化在训练数据上FaceNet和MobileNet输出的平方差异来进行训练。非常小的MobileNet模型的结果可以在表14中找到。 

1.MobileNetv1.py(pytorch实现)

from torch import nn
import torch

def _make_divisible(ch, divisor=8, min_ch=None):
    if min_ch is None:
        min_ch = divisor
    new_ch = max(min_ch, int(ch + divisor / 2) // divisor * divisor)
    if new_ch < 0.9 * ch:
        new_ch += divisor
    return new_ch

class ConvBNReLU(nn.Sequential):
    def __init__(self, in_channel, out_channel, kernel_size=3, stride=1, groups=1):
        padding = (kernel_size - 1) // 2
        super(ConvBNReLU, self).__init__(
            nn.Conv2d(in_channel, out_channel, kernel_size, stride, padding, groups=groups, bias=False),
            nn.BatchNorm2d(out_channel),
            nn.ReLU6(inplace=True)
        )

class InvertedResidual(nn.Module):
    def __init__(self, in_channel, out_channel, stride, expand_ratio):
        super(InvertedResidual, self).__init__()
        hidden_channel = in_channel * expand_ratio
        self.use_shortcut = stride == 1 and in_channel == out_channel
        layers = []
        if expand_ratio != 1:
            layers.append(ConvBNReLU(in_channel, hidden_channel, kernel_size=1))
        layers.extend([
            ConvBNReLU(hidden_channel, hidden_channel, stride=stride, groups=hidden_channel),
            nn.Conv2d(hidden_channel, out_channel, kernel_size=1, bias=False),
            nn.BatchNorm2d(out_channel)
        ])
        self.conv = nn.Sequential(*layers)
    def forward(self, x):
        if self.use_shortcut:
            return x + self.conv(x)
        else:
            return self.conv(x)

class MobileNetV2(nn.Module):
    def __init__(self, num_classes=1000, alpha=1.0, round_nearest=8):
        super(MobileNetV2, self).__init__()
        block = InvertedResidual
        input_channel = _make_divisible(32*alpha, round_nearest)
        last_channel = _make_divisible(1280*alpha, round_nearest)

        Inverted_residul_setting = [
            [1, 16, 1, 1],
            [6, 24, 2, 2],
            [6, 32, 3, 2],
            [6, 64, 4, 2],
            [6, 96, 3, 1],
            [6, 160, 3, 2],
            [6, 320, 1, 1]
        ]
        features = []
        features.append(ConvBNReLU(3, input_channel, stride=2))
        for t, c, n, s in Inverted_residul_setting:
            output_channel = _make_divisible(c * alpha, round_nearest)
            for i in range(n):
                stride = s if i == 0 else 1
                features.append(block(input_channel, output_channel, stride, expand_ratio=t))
                input_channel = output_channel
        features.append(ConvBNReLU(input_channel, last_channel, 1))
        self.features = nn.Sequential(*features)
        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
        self.classifier = nn.Sequential(
            nn.Dropout(0.2),
            nn.Linear(last_channel, num_classes)
        )
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                nn.init.kaiming_normal_(m.weight, mode='fan_out')
                if m.bias is not None:
                    nn.init.zeros_(m.bias)
            elif isinstance(m, nn.BatchNorm2d):
                nn.init.ones_(m.weight)
                nn.init.zeros_(m.bias)
            elif isinstance(m, nn.Linear):
                nn.init.normal_(m.weight, 0.01)
                nn.init.zeros_(m.bias)
    def forward(self, x):
        x = self.features(x)
        x = self.avgpool(x)
        x = torch.flatten(x, 1)
        x = self.classifier(x)
        return x

总结

我们提出了一种新的模型结构,称为基于深度可分离卷积的MobileNets。我们研究了一些重要的设计决策,以实现高效模型。然后,我们展示了如何使用宽度乘数和分辨率乘数来构建更小、更快的MobileNets,通过平衡一定量的精度来减小尺寸和延迟。我们然后比较了不同的MobileNets与流行的模型,表现出更优秀的尺寸、速度和精度特性。我们最后展示了MobileNet在广泛的任务中的有效性。作为下一步帮助MobileNets的采用和探索,我们计划在Tensor Flow中发布模型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值