【李飞飞】cs231n-1/3

0. 课程计划

课程地址
2017video地址
2021slide地址
课程推荐书籍
2019讲解
2020讲解(仅前三集)
CS231n全称:Convolutional Neural Networks for Visual Recognition

cs224 自然语言处理

没有找到2017以后的视频流出,现在根据2021的slides学习。

课程目标:

  • 理解应用
  • 开发模型
  • 洞悉前沿
    最近5年的新进展;
    仍未解决的挑战;
    伦理;

1. 课程导读

1.1 CV简史

神经科学激发了AI。

1959年,Hubel and Wiesel,bar状刺激,脉冲式响应;
1963年,Larry Roberts,第一篇CV论文;
1970年,David Marr,2D转3D模型构建;
1986年,Hinton等,BP算法;
1992年,感知机;
1997年,图像场景分割;
1999年,单目标识别;
2001年,人脸检测;
2005年,梯度直方图(HoG,Histogram of Gradients)
2006年,空间金字塔;

CV图像集圣杯:
Caltech101,李飞飞,2004
VOC (Visual Object Classes Challenge 2009)
PASCAL (Pattern Analysis Statistical Modelling and Computational Learning 2006)
ImageNet,李飞飞,2009,2015年起机器已经打败人类;

1.2 CS231n一览

图像识别(image classification)是CV领域的核心问题,据此衍生的应用包括:目标检测、图像注解(image captioning)、语义分割(semantic segmentation)、视频问答(VQA, visual question answering)、visual instruction navigation、场景图生成(scene graph generation)等。
在这里插入图片描述

2. Image Classification

课程目标:

  • 图像分类任务理解
  • 两个最基本的数据驱动方法:KNN + 线性分类器

2.1 任务理解

人类看到猫的图片,机器看到的是MN3的像素值,这是gap;
影响效果的挑战:

  • 视角变化、背景干扰、光线、遮挡
  • 姿势、类内变化、类间相似

图像分类任务与排序等传统问题有明显区别,也就是无法通过硬编码算法实现;

2.2 最近邻算法

2.2.1 基本思想

物以类聚,人以群分;
你是什么样的人,看跟你关系最近的K个朋友的为人;

应用:互联网推荐系统之协同过滤系统,缺点是冷启动问题;

训练过程:记住所有数据和标签; O ( 1 ) O(1) O(1)
推理过程:根据距离最近的已知图像-标签对的,预测你的标签; O ( N ) O(N) O(N)

这样的计算复杂度是不可接受的,推理太慢了。

常用的距离度量方式:
L1: d ( I 1 , I 2 ) = ∑ P ∣ I 1 P − I 2 P ∣ d(I_1, I_2) = \sum_{P}|I_1^P-I_2^P| d(I1,I2)=PI1PI2P,P表示像素点;
L2: d ( I 1 , I 2 ) = ∑ P ( I 1 P − I 2 P ) 2 d(I_1, I_2) = \sqrt{\sum_{P}(I_1^P-I_2^P)^2} d(I1,I2)=P(I1PI2P)2

1-NN:你离谁最近,你的标签就跟谁的一模一样;
K-NN:离你最近的K个样本,根据距离,加权投票,共同决定你的标签;

K-NN算法的距离度量不适用于原始像素,因为原始数据哪怕仅仅平移一个像素,求得的距离都可能非常大,这不合理,平移前后的图像理应距离非常小。

图像做为一个整体的距离,也有一些改进算法,例如余弦相似度,但是仍然不能解决本质问题,更核心的提取特征。

2.2.2 超参策略

K-NN算法中的超参:K值、距离度量

  • 方案一:选择训练集表现最优的K,不好,那样K一定等于1;
  • 方案二:选择测试集表现最优的K,不好,谁也不知道算法在新数据上的表现;
  • 方案三:切分为训练集、验证集、测试集,用验证集选择K,最终性能在测试集评估,好点,验证集选择随机性大;
  • 方案四:交叉验证,更合理;
    例如,将除测试集之外的数据分为5份,每次取一份做为验证集,重复5次,用这五次验证集上的平均值做为K,最终在测试集评估;
    交叉验证常用于小样本集,在DL中不常用了。为什么?因为DL中一般数据集都很大,验证集随机性不大,而交叉验证又非常耗时。
    在这里插入图片描述

2.3 线性分类器

f ( x , W ) = W x + b f(x,W)=Wx+b f(x,W)=Wx+b
在这里插入图片描述
线性分类器是NN(乐高积木)中的每层积木的基础,NN几乎就是线性分类+上下采样;

截距 b b b使得分类器不必恒过原点;

线性分类器的缺点:无法拟合非线性边界,例如异或、同心圆、散点
在这里插入图片描述

3. 损失函数与优化算法

3.1 Loss Func

3.1.1 Hinge Loss

SVM的铰链损失函数: L i = ∑ j ≠ y i m a x ( 0 , s j − s y i + 1 ) L_i=\sum_{j\not = y_i}max(0, s_j-s_{y_i}+1) Li=j=yimax(0,sjsyi+1), y i y_i yi是标签;
通俗来说就是:与标签得分相近的要惩罚,得分远低于标签的无视。

”1“其实就是冗余安全度,因为权重可以缩放,所以并不关心分数的绝对大小,所以1就够了。

使L=0的W唯一吗?不唯一,例如2W;

损失函数可以用平方值吗, L i = ∑ j ≠ y i m a x ( 0 , s j − s y i + 1 ) 2 L_i=\sum_{j\not = y_i}max(0, s_j-s_{y_i}+1)^2 Li=j=yimax(0,sjsyi+1)2 ?可以,这样惩罚力度不同,也可以。

那究竟如何设计损失函数呢?

3.1.2 正则化

在原有数据损失函数上加一个正则化的项,让模型更加简单,让参数更小。

正则化的目的:防止过拟合,防止死记硬背,防止模型过于复杂。其他相似约束:
Dropout (防止一家独大)
Batch Normalization
Stochastic depth,fractional pooling, etc

L ( W ) = 1 N ∑ i = 1 N L i ( f ( x i , W ) , y i ) + λ R ( W ) L(W)=\frac{1}{N}\sum_{i=1}^{N}L_i(f(x_i,W),y_i)+\lambda R(W) L(W)=N1i=1NLi(f(xi,W),yi)+λR(W)

L2正则: R ( W ) = ∑ k ∑ l W k , l 2 R(W)=\sum_k \sum_l W_{k,l}^2 R(W)=klWk,l2
L1正则: R ( W ) = ∑ k ∑ l ∣ W k , l ∣ R(W)=\sum_k \sum_l |W_{k,l}| R(W)=klWk,l
弹性网络Elastic net: R ( W ) = ∑ k ∑ l β W k , l 2 + ∣ W k , l ∣ R(W)=\sum_k \sum_l \beta W_{k,l}^2+|W_{k,l}| R(W)=klβWk,l2+Wk,l

3.2 Softmax分类器

Softmax就是多分类逻辑回归;
P ( Y = k ∣ X = x i ) = e s k ∑ j e s j P(Y=k|X=x_i)=\frac{e^{s_k}}{\sum_j e^{s_j}} P(Y=kX=xi)=jesjesk

优点:1. 得分可能是负数,exp之后都是正数;2. 所有概率加起来等于1;3. 升函数;

交叉熵损失函数=对数似然损失函数=负对数损失函数: L i = − l o g ( e s k ∑ j e s j ) L_i=-log(\frac{e^{s_k}}{\sum_j e^{s_j}}) Li=log(jesjesk),具体看cs229课程;

可见,这种损失函数不关心分类错误的类的得分情况。每个样本分类正确这一事件之间是不相关的,因此联合概率就是直接相乘,小数乘很多次就变成非常非常小的数字,容易消失,加log之后就是直接相加,将乘法就转化为加法了。

最大似然估计简介:使得所有图片都被正确分类的联合概率最大。log概率之和最大化,就是最大似然,就是-log概率之和最小化。得到交叉熵损失函数。

KL散度=交叉熵-信息熵,又叫相对熵;
D K L ( P ∣ ∣ Q ) = ∑ y P ( y ) l o g P ( y ) Q ( y ) D_{KL}(P||Q)=\sum_yP(y)log\frac{P(y)}{Q(y)} DKL(PQ)=yP(y)logQ(y)P(y)
交叉熵:
H ( P , Q ) = H ( p ) + D K L ( P ∣ ∣ Q ) H(P,Q) = H(p)+D_{KL}(P||Q) H(P,Q)=H(p)+DKL(PQ)

3.3 优化算法

3.3.1 梯度

梯度方向最抖,负梯度方向是下降最快的方向;
所谓“梯度下降法”,就是使得损失函数值沿着负梯度方向下降。

  • 数值解: d f ( x ) d x = l i m h → 0 f ( x + h ) − f ( x ) h \frac{df(x)}{dx}=lim_{h\rarr 0}\frac{f(x+h)-f(x)}{h} dxdf(x)=limh0hf(x+h)f(x)
    慢,估计值,易于计算
  • 解析解:求导公式,链式法则
    快,准确,容易崩溃

交互式Demo

3.3.2 SGD与minibatch

记训练集是N,minibatch一次喂一小口,就像醉汉一样,知道自己要下山,但是走起来摇摇晃晃,不过一直在走,最终也能到山脚。

一次喂全部N,内存消耗太大。

如何学习到最好的W?两方面:

  1. 利用NN将原始数据编码,提取特征(手动则为“特征工程”)
  2. 改进优化算法;

4. NN

BP在pytorch中的实现实际如下:
在这里插入图片描述
链式法则, ∂ f ∂ x = ∂ f ∂ q ∂ q ∂ x \frac{\partial f}{\partial x}=\frac{\partial f}{\partial q}\frac{\partial q}{\partial x} xf=qfxq,其中 ∂ f ∂ q \frac{\partial f}{\partial q} qf称为Upstream梯度, ∂ q ∂ x \frac{\partial q}{\partial x} xq称为local梯度

5. CNN

全连接处理图片问题的缺点:1. 计算量太大;2. 丢失空间信息;

各种卷积

池化层:增大平移不变性,减小参数量,防止过拟合;

6. DL软硬件

7. 训练NN-One time setup

7.1 激活函数

在这里插入图片描述
sigmoid

  • 优点:1. 压缩数据范围至[0,1];2. 与神经元的firing rate相似,仿生解释更容易理解;
  • 缺点:
  1. 饱和曲线导致梯度消失;
    梯度为0则权值无法更新: ∂ σ ( x ) ∂ x = σ ( x ) ( 1 − σ ( x ) ) \frac{\partial \sigma (x)}{\partial x}=\sigma(x)(1-\sigma(x)) xσ(x)=σ(x)(1σ(x))
  2. 输出值不是以0为中心(zero-centered)
    出现zig-zag现象,也就是上一层的输出全正,梯度的符号又完全相同,则只能在第一象限、第三象限前进,更加曲折、更慢;
  3. 指数计算相对耗时;
  • 应用:
  1. 一般不用;
  2. 网络的最后一层分类器,可以用sigmoid
  3. 循环神经网络LSTM的特定层,IFO用sigmoid,G用tanh,这是特殊场景;

tanh
仍然存在饱和曲线导致的梯度消失;

ReLU (Rectified Linear Unit)
优点:1. 不再饱和;2. 计算高效;3. 快速收敛;
缺点:不以0为中心
当x<0时,梯度为0,权值不再更新,这个结点成为“僵尸”;

Leaky ReLU: f ( x ) = m a x ( 0.01 x , x ) f(x)=max(0.01x, x) f(x)=max(0.01x,x)
PReLU: f ( x ) = m a x ( α x , x ) f(x)=max(\alpha x,x) f(x)=max(αx,x),其中P表示parametric,引入参数 α \alpha α
ELU, Exponential Linear Units: 需要计算指数
Swish: KaTeX parse error: Undefined control sequence: \belta at position 14: f(x)=x\sigma(\̲b̲e̲l̲t̲a̲ ̲x)
SELU, Scaled ELU:
在满足以下两个条件的情况下,经过该激活函数后使得样本分布自动归一化到0均值和单位方差:
1 按照给定的参数对权重初始化:对于正态分布的初始化,初始化参数为0均值,方差为 1 / n \sqrt{1/n} 1/n , n是输入的通道个数
2 按照给定的参数对样本计算激活函数: λ = 1.0507 , α = 1.6733 \lambda=1.0507,\alpha=1.6733 λ=1.0507,α=1.6733

Maxout: 每个神经元有两组(w,b)参数,参数量增加一倍;

7.2 数据预处理

标准化处理:
减均值将原始数据各个维度移动到原点为中心;
除标准差将各个维度的范围限制在单位1以内;
在这里插入图片描述
PCA:主成分分析
第一主成分是协方差矩阵的主特征向量方向;
沿主成分方向做数据投影、降维;降维后协方差矩阵是对角矩阵;

白化:
PCA投影后再对每一维度缩放,方差为1,则称为白化;
PCA白化的基础上,再映射回原数据坐标系,称为ZCA白化;

PCA和白化计算复杂,不再常用;
归一化后,对W的敏感程度更小,能用更大的学习率;

应用:
AlexNet减一张平均图;
VGGNet减每个通道的均值;
ResNet每个通道减均值除标准差;

7.3 权重初始化

方案一:所有权重全初始化为同一个常数
则所有神经元前向、反向都相同,永远行为已知,等于只有一个神经元;

方案二:随机初始化,幅度怎么选
f ( ∑ i w i x i + b , ∂ f ∂ w i = f ′ ∗ x i f(\sum_iw_ix_i+b,\frac{\partial f}{\partial w_i}=f'*x_i f(iwixi+b,wif=fxi
以tanh为例,幅度小, x i x_i xi趋向于0,梯度消失;幅度大, f ′ f' f趋向于0,输出趋近于饱和区,仍然梯度消失;

方案三:Xavier初始化,幅度 1 D i n \frac{1}{\sqrt{D_{in}}} Din 1
其中 D i n = D_{in}= Din=kernel_sizekernel_sizeinput_channel;
假设输入X和权值W是均值为0且独立同分布,则输出的方差=输入的方差;

可见,ReLU不是均值为0,因此Xavier初始化仍然不能解决问题;

方案四:MSRA初始化,幅度 2 D i n \sqrt{\frac{2}{D_{in}}} Din2 ,何凯明首次用于ResNet
假设 W ∼ N o r m a l ( 0 , 2 / d ) W\sim Normal(0,2/d) WNormal(0,2/d),或者 W ∼ U n i f o r m ( − 6 / d , 6 / d ) W\sim Uniform(-\sqrt{6/d},\sqrt{6/d}) WUniform(6/d ,6/d ),则输出的方差=输入的方差;

7.4 BN

Batch Normalization,强行将中间的特征图转成标准分布;
假设输入x是NxD维:
求batch中每个特征维度的均值,得到D个均值;
求batch中每个特征维度的方差,得到D个方差;
广播计算,减均值除标准差,得到NxD的输出;

标准分布的约束过强,因此再加学习参数:
y i , j = γ j x i , j ~ + β j y_{i,j}=\gamma_j \tilde{x_{i,j}}+\beta_j yi,j=γjxi,j~+βj
如果 γ = σ , β = μ \gamma=\sigma,\beta=\mu γ=σ,β=μ,则等效于Identity;

应用:常用于FC、Conv后,激活函数之前;

在这里插入图片描述

BN优点:

  • 加快收敛
  • 改善梯度,远离饱和区
  • 支持大学习率
  • 对初始化不敏感
  • 起正则化作用

7.5 迁移学习

8. 训练NN–Traning dynamics

8.1 优化器

SGD缺点:
x t + 1 = x t − α ∇ f ( x t ) x_{t+1}=x_t-\alpha\nabla f(x_t) xt+1=xtαf(xt)

  1. 在陡峭方向抖动;2. 陷于局部最优点或鞍点;3. 每个minibatch决定自己的,噪声大;

Momentum: 动量与历史相关,大胖子下山,冲出局部,更平滑
v t + 1 = ρ v t + ∇ f ( x t ) v_{t+1}=\rho v_t+\nabla f(x_t) vt+1=ρvt+f(xt)
x t + 1 = x t − α v t + 1 x_{t+1}=x_t-\alpha v_{t+1} xt+1=xtαvt+1

Nesterov Momentum:往前多看一步,更快收敛
v t + 1 = ρ v t − α ∇ f ( x t + ρ v t ) v_{t+1}=\rho v_t-\alpha\nabla f(x_t+\rho v_t) vt+1=ρvtαf(xt+ρvt)
x t + 1 = x t + v t + 1 x_{t+1}=x_t+v_{t+1} xt+1=xt+vt+1

AdaGrad:SGD的学习率用二次项自适应,系数累加,缺点是累加后系数太大,逐渐不更新了,卡住了;
s t + 1 = s t + ∇ f ( x t ) ∗ ∇ f ( x t ) s_{t+1} = s_t + \nabla f(x_t)*\nabla f(x_t) st+1=st+f(xt)f(xt)
x t + 1 = x t − α ∇ f ( x t ) / ( s t + 1 + 1 e − 7 ) x_{t+1}=x_t-\alpha\nabla f(x_t)/(\sqrt{s_{t+1}+1e^{-7}}) xt+1=xtαf(xt)/(st+1+1e7 )

RMSProp:“Leaky AdaGrad”,在AdaGrad基础上惩罚系数
s t + 1 = γ s t + ( 1 − γ ) ∇ f ( x t ) ∗ ∇ f ( x t ) s_{t+1} = \gamma s_t + (1-\gamma)\nabla f(x_t)*\nabla f(x_t) st+1=γst+(1γ)f(xt)f(xt)
x t + 1 = x t − α ∇ f ( x t ) / ( s t + 1 + 1 e − 7 ) x_{t+1}=x_t-\alpha\nabla f(x_t)/(\sqrt{s_{t+1}+1e^{-7}}) xt+1=xtαf(xt)/(st+1+1e7 )

Adam:学习率用一次项和二次项自适应
q t + 1 = γ 1 q t + ( 1 − γ 1 ) ∇ f ( x t ) q_{t+1} = \gamma_1 q_t + (1-\gamma_1)\nabla f(x_t) qt+1=γ1qt+(1γ1)f(xt)
s t + 1 = γ 2 s t + ( 1 − γ 2 ) ∇ f ( x t ) ∗ ∇ f ( x t ) s_{t+1} = \gamma_2 s_t + (1-\gamma_2)\nabla f(x_t)*\nabla f(x_t) st+1=γ2st+(1γ2)f(xt)f(xt)
x t + 1 = x t − α q t + 1 / ( s t + 1 + 1 e − 7 ) x_{t+1}=x_t-\alpha q_{t+1}/(\sqrt{s_{t+1}+1e^{-7}}) xt+1=xtαqt+1/(st+1+1e7 )
初始情况下启动较慢,上述公式还需要做一点点修正;

8.2 学习率

台阶式:ResNet中,每30epoch,将学习率乘0.1;
余弦式: α t = 1 2 α 0 ( 1 + c o s ( t π / T ) \alpha_t=\frac{1}{2}\alpha_0(1+cos(t\pi/T) αt=21α0(1+cos(tπ/T)
线性式: α t = α 0 ( 1 − t / T ) \alpha_t=\alpha_0(1-t/T) αt=α0(1t/T)
幂函数: α t = α 0 / t \alpha_t=\alpha_0/\sqrt{t} αt=α0/t

以上所有优化器都使用的一阶导数,而使用二阶导数不需要学习率;
之所以不使用,是海森矩阵的逆矩阵难以计算,虽然也有一些近似方法如BGFS、L-BGFS,但是仍然不常用;

早停:训练集准确率提高,验证集反而降低,则过拟合

模型集成:兼听则明,例如随机森林、2016年imagenet竞赛冠军,提升2%

checkpoint集成,好而相同;

周期性增大学习率,好而不同;

8.3 正则化

修改损失函数:KaTeX parse error: Undefined control sequence: \lambaR at position 12: L=L_{data}+\̲l̲a̲m̲b̲a̲R̲(W)
L2正则: R ( W ) = ∑ k ∑ l W k , l 2 R(W)=\sum_k \sum_l W_{k,l}^2 R(W)=klWk,l2
L1正则: R ( W ) = ∑ k ∑ l ∣ W k , l ∣ R(W)=\sum_k \sum_l |W_{k,l}| R(W)=klWk,l
弹性网络Elastic net: R ( W ) = ∑ k ∑ l β W k , l 2 + ∣ W k , l ∣ R(W)=\sum_k \sum_l \beta W_{k,l}^2+|W_{k,l}| R(W)=klβWk,l2+Wk,l

另一种正则化方法:DropOut,有效防止过拟合

  1. 打破特征之间的联合适应性,每个特征都能独当一面
  2. 模型集成的效果
  3. 随机抹去一些记忆,有效防止过拟合
  4. 训练阶段用p的概率做DropOut,测试阶段要乘p把幅度补回来,或者在训练阶段原地补偿Inverted dropout

数据增强:拔一根毫毛,吹出猴万个

正则化方法:Dropout、BN、数据增强、DropConnet、Fractional Pooling、Cutout…

8.4 超参

  1. 检查初始loss,看代码有没有bug
  2. Overfit a small sample
  3. 选一个能使loss下降够快的LR
  4. 逐渐降低LR
  5. 看loss曲线,判断过拟合、欠拟合、早停

8.5 Evaluation

超参:网络结构、学习率、正则化 --> AutoML

9. 典型CNN结构

目标:培养算法直觉,迁移学习,学习技巧
在这里插入图片描述
1998年LeNet5: 6w参数
conv-pool-conv-pool-fc-fc
卷积算子的优点:局部感受野;权值共享;下采样池化可以减少参数、防止过拟合;

2012年AlexNet:6000w参数
conv-pool-LSN–conv-pool-LSN–conv-conv-conv-pool-fc-fc-fc
贡献:

  1. 使用大量数据增强
  2. 首次使用ReLU
  3. 使用MaxPooling
  4. 使用DropOut
  5. 损失函数加L2正则化
  6. SGD+Momentum
  7. LR阶梯下降
  8. 正则化用LSN,Local Response Normalization,认为同一位置不需要太多的高激活神经元;–>现在基本弃用

2013年ZFNet:
结构同ResNet,做了更好的超参调整;
贡献:
用反卷积可视化(pool的反向需要记录switch);

2014年VGGNet:1.38亿个参数
贡献:
same_conv,
2层33conv的感受野与1层55conv的感受野相同
3层33conv的感受野与1层77conv的感受野相同
而计算量下降。

缺点:
前两个conv占据大量内存,第一个FC占据1亿个参数;

2014年GoogLeNet:500w个参数
贡献:

  1. 提出高效的“Inception"模块
    Inception模块使用不同尺度conv核+max pool,然后把结果摞起来;
    原始Inception缺点:
    计算量大,摞起来通道越来越大
    1x1卷积:Network In Network, NiN
    -降维、升维
    -跨通道信息交融
    -减少参数量
    -增加模型深度
    为了能堆起来,参数注意步长和padding, o = ⌊ ( x − f + 2 p ) / s ⌋ + 1 o=\lfloor(x-f+2p)/s\rfloor+1 o=xf+2p)/s+1
  2. 辅助分类层,模型集成,也相当于正则化
  3. Global Ave Pooling层,替代FC,更省参数
    class activation map,可视化激活图
    甚至可以做语义分割!
    在这里插入图片描述

Inceptionv2:
-用2层conv33代替1层conv55 (类似VGG)
-用conv13和conv31代替conv3*3

Inceptionv4:结合ResNet

2015年ResNet
更深的NN效果反而不好,原因不是过拟合,而是梯度消失

  1. 残差模块:
    浅层网络得到的结果加在深层网络的结果上;
    H ( x ) = F ( x ) + x H(x)=F(x)+x H(x)=F(x)+x,x是浅层结果,F(x)是中间新学习到的残差,H(x)是深层结果;
  2. 不再使用池化层,而使用stride=2
  3. bottleneck
    conv11–conv33–conv1*1
  4. MSRA初始化

变体:
2016年,Stochastic Depth,随机让部分残差块失活;
2017年,DenseNet,DenseBlock内密集跳接;

2017年SENet:
Squeeze-and-Excitation Netwoks,思路就是在feature map后面加一个global avg pooling得到C个值,再加两个FC层,进行重新校准,然后乘回原来的feature map.

2017年后,主办方觉得没必要再比了,比赛被迁移到kaggle上;

2017年SqueezeNet:

  • 组合conv,减少参数量
  • 权重合并、量化、霍夫曼编码、模型裁剪,做模型极限压缩

在这里插入图片描述
2017 MobileNet: DepthwiseConv
2018 ShuffleNet: GroupConv+channel shuffle
2016 NAS: Neural Architecture Search,meta learning,元学习, Learning to learn,用RNN生成模型参数,用强化学习获得环境奖励;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值