pull/2698/merge
oozhuzaioo 2025-03-06 13:34:49 +08:00 committed by GitHub
commit 9a5106d6a3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 308 additions and 0 deletions

View File

@ -0,0 +1,135 @@
# rfc_task-137_model_BEiT-v2模型PaddleClas实现设计文档
|模型名称 | BEiTv2 |
|---|---|
|相关paper| https://arxiv.org/pdf/2208.06366.pdf |
|参考项目|PaddleClas比赛导师提供|
|提交作者 | 刘学文 |
|提交时间 | 2022-03-11 |
|依赖飞桨版本 | PaddlePaddle2.4.1 |
|文件名 | rfc_task_137_model_BEiT-v2.md |
----------------------------------------------------------------
# BEiTv2模型PaddleClas实现设计文档
## 一、概述
BEiT-v2[<sup>1</sup>](#BEiT-v2)模型是BEiT[<sup>2</sup>](#BEiT-v1)模型的V2版本。BEiT是一个两阶段的算法首先通过一个dVAE将图像映射成离散的视觉标志Visual Token然后再通过视觉Transformer学习带掩码的图像Patch到视觉标志的映射。
BEiT-v2的提出是为了解决BEiT未对第一阶段中dVAE学习到的语义空间进行深入的探讨和优化的问题。它的核心是通过训练好的模型作为Teacher来指导视觉标志的学习同时引入了标志符来学习整个图像的特征以提高准确率。
**算法详解**
BEiT-v2是一个两阶段的模型
**第一阶段**
第一阶段是VQ-KD的训练VQ-KD由两部分组成分别是*Tokenizer*以及*Decoder*
VQ-KD的作用是将输入图像转化为视觉标志即将输入图像 $x$ 转化未视觉标志 $\boldsymbol{z}=\left[z_{1}, \cdots, z_{N}\right] \in \mathcal{V}^{(H / P) \times(W / P)}$ , 其中 $\mathcal{V}$ 指的是视觉字典。
**Tokenizer**
Tokenizer的计算分成两步它首先使用ViT将输入图像编码成特征向量然后使用从码本中找最近邻。
假设图像序列 $\left\{\boldsymbol{x}_{i}^{p}\right\}_{i=1}^{N}$ 编码成的序列表示为 $\left\{h_{i}^{p}\right\}_{i=1}^{N}$,码本的嵌入表示为 $\left\{\boldsymbol{v}_1, \boldsymbol{v}_2, \cdots, \boldsymbol{v}_K\right\}$ ,那么对于第 $i$ 个图像的patch对应的视觉标志可以通过下面的式子确定
$$z_i=\arg \min _j\left\|\ell_2\left(\boldsymbol{h}_i\right)-\ell_2\left(\boldsymbol{e}_j\right)\right\|_2$$
其中 $\ell_2$ 是特征的L2正则化
**Decoder**
Decoder也是一个多层的Transformer当Tokenizer将图像表示到视觉标志后通过将这些视觉标志正则化可以将它输入到解码器中得到最终的输出 $\left\{\boldsymbol{o}_i\right\}_{i=1}^N$ 。输出向量的目的是重建训练好的模型作为Teacher指导的特征。
**损失函数**
VQ-KD的损失函数可以表示最大化模型输出以及Teacher生成的特征相似度并最小化生成特征和视觉单词的距离。因为存在不可导操作所以损失函数的内容如下式
$$\max \sum_{x \in \mathcal{D}} \sum_{i=1}^N \cos \left(\boldsymbol{o}_i, \boldsymbol{t}_i\right)-\left\|\operatorname{sg}\left[\ell_2\left(\boldsymbol{h}_i\right)\right]-\ell_2\left(\boldsymbol{v}_{z_i}\right)\right\|_2^2-\left\|\ell_2\left(\boldsymbol{h}_i\right)-\operatorname{sg}\left[\ell_2\left(\boldsymbol{v}_{z_i}\right)\right]\right\|_2^2$$
其中 $\operatorname{sg}[.]$ 表示停止梯度计算操作, $\mathcal{D}$ 表示用来Tokenizer的训练数据集。
**第二阶段**
第二阶段是预训练。预训练分为两个部分:掩码图像模型的训练和标志的训练。
**掩码图像模型**
BEiT-v2的预训练遵循了和BEiTv1类似的方式MIM不同的是它在输入数据中拼接了[CLS]标志。[CLS]标志与BEiTv1中得到的 $\boldsymbol{x}_i^{\mathcal{M}}$ 共同输入到视觉Transformer中通过视觉Transformer的计算可以得到模型的输出 $\left\{\boldsymbol{h}_i\right\}_{i=0}^N$ 。
在视觉Transformer之后添加一个MIM的输出头用于预测图像patch对应的视觉标志对于每个输出使用softmax损失函数预测每个patch的输出概率表示为下式
$$p\left(\boldsymbol{z}_i \mid \boldsymbol{h}_i\right)=\operatorname{softmax}_{\boldsymbol{z}_i}\left(\boldsymbol{W}_c \boldsymbol{h}_i+\boldsymbol{b}_c\right)$$
其中 $\boldsymbol{W}$ 和 $\boldsymbol{b}$ 分别是权值矩阵和偏置向量。最终MIM的损失函数表示为
$$\mathcal{L}_{\mathrm{MIM}}=-\sum_{x \in \mathcal{D}} \sum_{i \in \mathcal{M}} \log p\left(z_i \mid x^{\mathcal{M}}\right)$$
其中 $\boldsymbol{z}_i$ 是原始图像的视觉标志, $\mathcal{D}$ 表示与训练图像。
**预训练全局表示**
对[CLS]标志进行训练来捕获图像的全局信息,[CLS]的预训练的输入是由第 $l$ 层视觉Transformer的特征向量和第 $L$ 层[CLS]的特征向量拼接而成(具体可以见论文[<sup>1</sup>](#BEiT-v2)图三虚线框内),接下来将特征 $S$ 输入到一个两层的Transformer中来预测掩码图像的视觉标志.
## 二、设计思路与实现方案
### backbone
- Transformer
### optimizer(PaddleClas已有实现)
- adamw
- adam
- 初始学习率: $5e-4$
- 权重衰减:$0.05$
- momentum $0.9$
### loss
- 见算法详解
### dataset
- ImageNet-1K
- ADE20K
### metric
#### image classification
- top-1 accuracy
#### semantic segmentation
- mIoU
### 训练策略
- 16块V100 32GB英伟达显卡
#### image classification
- 训练和评估都是在ImageNet-1K上
##### Fine-tuning setup
- 遵循BEiT中提出的方法微调BEiT-v2模型
##### Linear probing
- 将表征层的特征固定,只通过监督数据去训练分类器
#### Semantic Segmentation
- 实验在ADE20K上进行
- 使用UperNet[<sup>3</sup>](#UperNet)任务层在输入分辨率为512×512的情况下对模型进行16万次迭代微调。
## 三、功能模块测试方法
|功能模块|测试方法|
|---|---|
|前向完全对齐|给定相同的输入分别对比PaddleClas实现的模型输出是否和官方的Pytorch版本相同|
|反向完全对齐|给定相同的输入检查反向参数更新分别对比PaddleClas实现和官方的Pytorch版本参数更新是否一致|
|图像预处理|对照官方实现编写paddle版本|
|超参数配置|保持和官方实现一致|
|训练环境|最好也是16块V100显卡环境采用单机多卡分布式训练方式和官方保持一致|
|精度对齐|在提供的小数据集上预训练并finetune后实现精度和论文对齐|
## 四、可行性分析和排期规划
|时间|开发排期规划|时长|
|---|---|---|
|03.11-03.19|熟悉相关工具、前向对齐|9days|
|03.20-03.26|反向对齐|7days|
|03.27-04.09|训练对齐|14days|
|04.10-04.16|代码合入|7days|
## 五、风险点与影响面
风险点:
- BEiT-v2模型分成多个预训练模型合入PaddleClas代码量较多
# 名词解释
MIM(Masked Image Model)
# 附件及参考资料
<div id="BEiT-v2"></div>
[1] Peng Z, Dong L, Bao H, et al. Beit v2: Masked image modeling with vector-quantized visual tokenizers[J]. arXiv preprint arXiv:2208.06366, 2022.
<div id="BEiT-v1"></div>
[2] Bao H, Dong L, Piao S, et al. Beit: Bert pre-training of image transformers[J]. arXiv preprint arXiv:2106.08254, 2021.
<div id="UperNet"></div>
[3] Xiao T, Liu Y, Zhou B, et al. Unified perceptual parsing for scene understanding[C]//Proceedings of the European conference on computer vision (ECCV). 2018: 418-434.

View File

@ -0,0 +1,173 @@
# rfc_task-137_MoCo-v2模型PaddleClas实现设计文档
|模型名称 | MoCov2模型 |
|---|---|
|相关paper| https://arxiv.org/pdf/2003.04297.pdf |
|参考项目| https://github.com/PaddlePaddle/PASSL https://github.com/facebookresearch/MoCo|
|提交作者 | 张乐 |
|提交时间 | 2022-03-11 |
|依赖飞桨版本 | PaddlePaddle2.4.1 |
|文件名 | rfc_task_137_model_MoCo-v2.md |
# MoCo-v2 模型PaddleClas实现设计文档
## 一、概述
MoCo-v2[<sup>2</sup>](#moco-v2)模型是在MoCo模型的基础上增加了数据增强、将单层fc替换为多层mlp、学习率衰减策略修改为consine衰减。因此我们在此重点介绍MoCo模型。
MoCo[<sup>1</sup>](#moco-v1)模型本身是一个自监督对比学习框架,可以从大规模图像数据集中学习到良好的图像表示特征,其预训练模型可以无缝地嵌入许多视觉任务中,比如:图像分类、目标检测、分割等。
**MoCo框架简述**
**前向传播**
下面我们从输入$minibatchImgs=\{I_1,I_2,..I_N\}$ 数据的前向传播过程来简单讲解MoCo框架首先对$I_n$分别进行变换$view_1$和$view_2$
$$I^{view1}_n=view_1(I_n)$$
$$I^{view2}_n=view_2(I_n)$$
其中,$view_1$和$view_2$表示一系列图像预处理变换随机裁切、灰度化、均值化等具体详见paper Source Codeminibatch大小为$N$。这样每幅输入图像$I_n$就会得到两个变换图像$I^{view1}_n$和$I^{view2}_n$。
接着将$I^{view1}_n$和$I^{view2}_n$分别送入两个编码器,则:
$$q_n=L2_{normalization}(Encoder_1(I^{view1}_n))$$
$$k_n=L2_{normalization}(Encoder_2(I^{view2}_n))$$
其中$q_n$和$k_n$的特征维度均为k, $Encoder_1$和$Encoder_2$分别是ResNet50的backbone网络串联一个MLP网络组成。
为了满足对比学习任务的条件,需要正负样本来进行学习。作者自然而然将输入的样本都看作正样本,至于负样本,则通过构建一个**动态**$Dict_{K\times C}$维度的超大字典,通过将正样本集合$q_+=\{q_1,q_2...q_N\}$和$k_+=\{k_1,k_2...k_N\}$一一做向量点乘求和相加来计算$Loss_+$
$$Loss_+=\{l^{1}_+;l^{2}_+; ...;l^{N}_+\}=\{ q_1\cdot k_1; q_2\cdot k_2;...; q_n\cdot k_n \}; Loss_+\in N \times 1$$
$Loss_-$的计算过程为:
$$l^{n,k}_-=q_n \cdot Dict_{:,n};Loss_-\in N \times C$$
最后的loss为
$$Loss=concat(Loss_+, Loss_-)\in N \times (1+C)$$
可以看到字典$Dict$在整个图像表示的学习过程中可以看作一个隐特征空间作者发现该字典设置的越大视觉表示学习的效果就越好。其中每次在做完前向传播后需要将当前的minibatch以**队列入队**的形式将$k_n$加入到字典$Dict$中,并同时将最旧时刻的minibatch**出队**。
学习的目标函数采用交叉熵损失函数如下所示:
$$Loss_{crossentropy}=-log \cdot \frac{exp(l_+/ \tau)}{ \sum exp(l_n / \tau)}$$
其中超参数$\tau$取0.07
**反向梯度传播**
在梯度反向传播过程中,梯度传播只用来更新$Encoder_1$的参数$Param_{Encoder_1}$,为了不影响动态词典$Dict$的视觉表示特征一致性,$Encoder_2$的参数$Param_{Encoder_1}$更新过程为:
$$Param_{Encoder_2}=m \cdot Param_{Encoder_2} + ( 1- m ) \cdot Param_{Encoder_1} $$
其中,超参数$m$取0.999
## 二、设计思路与实现方案
### 模型backbonePaddleClas已有实现
- ResNet50的backbone(去除最后的全连接层)
- MLP由 两个全连接层FC1 $ 2048 \times 2048 $ 和FC2 $ 2048 \times 128 $ 构成
- 动态字典大小为$65536$
### optimizer
- SGD:随机梯度下降优化器
- 初始学习率 $0.03$
- 权重衰减:$1e-4$
- momentum of SGD $0.9$
### 训练策略PaddleClas已有实现
- batch-size256
- 单机8块V100
- 在每个GPU上做shuffle_BN
- 共迭代$epochs:200$
- lr schedule 在$epch=[120, 160]$, $lr=lr*.0.1$
- 学习率衰减策略$cosine $
### metricPaddleClas已有实现
- top1
- top5
### dataset
- 数据集ImageNet
- 数据增强PaddleClas已有基本变换实现
```Python
#pytorch 代码
augmentation = [
transforms.RandomResizedCrop(224, scale=(0.2, 1.0)),
transforms.RandomApply(
[transforms.ColorJitter(0.4, 0.4, 0.4, 0.1)], p=0.8 # not strengthened
),
transforms.RandomGrayscale(p=0.2),
transforms.RandomApply([moco.loader.GaussianBlur([0.1, 2.0])], p=0.5),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
normalize,
]
```
- 图像对随机变换和高斯模糊(**PSSL已有基本变换实现,需要转为PaddleClas项目实现**
```python
# pytorch 代码
class TwoCropsTransform:
"""Take two random crops of one image as the query and key."""
def __init__(self, base_transform):
self.base_transform = base_transform
def __call__(self, x):
q = self.base_transform(x)
k = self.base_transform(x)
return [q, k]
class GaussianBlur(object):
"""Gaussian blur augmentation in SimCLR https://arxiv.org/abs/2002.05709"""
def __init__(self, sigma=[0.1, 2.0]):
self.sigma = sigma
def __call__(self, x):
sigma = random.uniform(self.sigma[0], self.sigma[1])
x = x.filter(ImageFilter.GaussianBlur(radius=sigma))
return x
```
### PSSL项目和PaddleClas项目框架对比
- 两个项目基础模型ResNet50的每层参数名称不同需要将PASSL项目的训练权重转化为PaddleClas项目使用
- PSSL项目采用Register类方式将模型的architecture、backbone、neck、head、数据集、优化器、钩子函数链接在一起使得整个模型的训练过程都可以通过命令行提供一份yaml文件搞定这一点与PaddleClas项目类似
## 三、功能模块测试方法
|功能模块|测试方法|
|---|---|
|前向完全对齐|给定相同的输入分别对比PaddleClas实现的模型输出是否和官方的Pytorch版本相同|
|反向完全对齐|给定相同的输入检查反向参数更新分别对比PaddleClas实现和官方的Pytorch版本参数更新是否一致|
|图像预处理|对照官方实现编写paddle版本|
|超参数配置|保持和官方实现一致|
|训练环境|最好也是8块V100显卡环境采用单机多卡分布式训练方式和官方保持一致|
|精度对齐|在提供的小数据集上预训练并finetune后实现精度和原PSSL项目模型相同|
## 四、可行性分析和排期规划
|时间|开发排期规划|时长|
|---|---|---|
|03.11-03.19|熟悉相关工具、前向对齐|9days|
|03.20-04.02|反向对齐|14days|
|04.03-04.16|训练对齐|14days|
|04.16-04.29|代码合入|14days|
## 五、风险点与影响面
风险点:
- MoCo模型训练后一般作为图像特征提取器使用并不存在所谓的推理过程
- **PaddleClas中所有模型和算法需要通过飞桨训推一体认证,当前只需要通过新增模型只需要通过训练和推理的基础认证即可**。但是这个与MoCo模型的训练推理原则相违背是否可以对MoCo-v2模型的认证给出明确的指定
- 合入代码题目是MoCo-v2,代码合入的时候是否需要同时考虑MoCo-v1代码模块原PSSL项目有该项实现
- 原PSSL有MoCo-Clas分类模型代码合入的时候是否需要同时加入此模块原PSSL项目有该项实现
影响面:
数据的Dataloader、数据增强和model均为新增脚本不对其它模块构成影响
# 名词解释
MoCo(Momentum Contrast动量对比)
# 附件及参考资料
<div id="moco-v1"></div>
[1] He K, Fan H, Wu Y, et al. Momentum contrast for unsupervised visual representation learning[C]//Proceedings of the IEEE/CVF conference on computer vision and pattern recognition. 2020: 9729-9738.
<div id="moco-v2"></div>
[2] Chen X, Fan H, Girshick R, et al. Improved baselines with momentum contrastive learning[J]. arXiv preprint arXiv:2003.04297, 2020.