BEiTv2模型先在ImageNet-1k(1419万张图像,1000个类别)数据集上以自监督的方式进行预训练,并在ImageNet-21k(1400万张图像,21,841个类别)数据集上进行微调,得到的预训练模型在下游ImageNet-1k分类任务上进行微调后,BEiTv2-base在ImageNet-1k验证集上达到了86.5%的top-1精度,在其它下游任务上也分别达到了SOTA的结果。
本系列还有如下模型,欢迎试用:
BEiT(Bidirectional Encoder Image Transformers)是一个自监督视觉表示模型。受BERT在NLP领域中的启发,BEiT提出掩码图像建模(masked image modeling,MIM)任务来预训练Vision Transformer。
BEiT预训练过程如下:预训练之前,通过自编码器dVAE学习一个image tokenizer,其根据学习到的vocabulary,可以将一幅图像tokenized为离散visual tokens。在预训练期间,每个图像有两种视角:image patches和visual tokens。随机掩盖Image patches的一部分,并且用特定的mask embedding替换,然后将patches输入到backbone vision Transformer。预训练的目标是基于掩盖的image patches来恢复原有visual tokens。预训练BEiT之后,可以通过在预训练的encoder上添加特定任务的层,直接对下游任务的模型参数进行微调,预训练过程如图:
BEiTv2在BEiT的基础上对dVAE学到的语义空间进行深入的探讨和优化:使用矢量量化-知识蒸馏(Vector-quantized Knowledge Distillation,VQ-KD)的方法来学习生成视觉标志,该方法的核心思想是通过一个训练好的模型,例如CLIP或DINO作为Teacher来指导视觉标志的学习。BEiTv2和BEiT一样,它也是一个两阶段的模型:它的第一阶段是VQ-KD的训练,第二阶段是预训练模型的训练。为了提升BEiT的效果,BEiTv2做了如下改进:
提出了VQ-KD方法来对图像进行编码,它将原始图像作为输入,使用另外一个模型作为教师系统来引导视觉标志模型的训练。在通过VQ-KD得到图像的视觉标志之后,使用这个视觉标志作为预训练模型的训练目标。
VQ-KD计算流程:
为了学习图像的全局信息,BEiTv2在输入编码中拼接了[CLS]标志,然后通过对[CLS]标志的预训练来得到图像的全局信息,从而使得BEiTv2在线性探测(Linear Probe)方式也能拥有非常高的准确率。
掩码图像模型的计算流程:
在ImageNet-1K上,patch为16,分辨率为224x224,BEiTv2-base的top-1准确率相比BEiT-base从85.2%提高到了86.5%,超过从头开始训练DeiT模型的准确率。
本模型基于BEiTv2-base,patch为16,分辨率为224x224,先在ImageNet-1k进行预训练1600个epoch,并在ImageNet-21k上进行微调90个epoch,得到预训练模型后在ImageNet-1k上进行微调30个epoch,最终在ImageNet-1k验证集上的top-1精度为86.5%。
本模型作为一个Transformer预训练模型,可直接作为分类、检测、分割等下游任务的预训练backbone,在下游任务数据集上进行少量微调即可得到很好的结果。
在ModelScope框架上,提供输入图片,即可通过简单的Pipeline调用来使用。
from modelscope.pipelines import pipeline
from modelscope.utils.constant import Tasks
img_path = 'https://modelscope.oss-cn-beijing.aliyuncs.com/test/images/bird.JPEG'
image_classification = pipeline(Tasks.image_classification,
model='damo/cv_beitv2-base_image-classification_patch16_224_pt1k_ft22k_in1k')
result = image_classification(img_path)
print(result)
测试时主要的预处理如下:
模型在ImageNet1K验证集上的评估结果:
Model | top-1 acc | top-5 acc | #params | Remark |
---|---|---|---|---|
BEiTv2-base | 86.5 | 98.0 | 86.5M | modelscope |
论文中模型在ImageNet1K验证集上的评估结果:
使用托管在modelscope DatasetHub上的小型数据集mini_imagenet100进行finetune训练的示例代码:
from modelscope.msdatasets import MsDataset
from modelscope.metainfo import Trainers
from modelscope.trainers import build_trainer
import tempfile
model_id = 'damo/cv_beitv2-base_image-classification_patch16_224_pt1k_ft22k_in1k'
# 加载数据
ms_train_dataset = MsDataset.load(
'mini_imagenet100', namespace='tany0699',
subset_name='default', split='train') # 加载训练集
ms_val_dataset = MsDataset.load(
'mini_imagenet100', namespace='tany0699',
subset_name='default', split='validation') # 加载验证集
tmp_dir = tempfile.TemporaryDirectory().name # 使用临时目录作为工作目录
# 修改配置文件
def cfg_modify_fn(cfg):
cfg.train.dataloader.batch_size_per_gpu = 16 # batch大小
cfg.train.dataloader.workers_per_gpu = 2 # 每个gpu的worker数目
cfg.train.max_epochs = 1 # 最大训练epoch数
cfg.model.mm_model.head.num_classes = 100 # 分类数
cfg.model.mm_model.head.loss.num_classes = 100
cfg.train.optimizer.lr = 1e-4 # 学习率
cfg.train.lr_config.warmup_iters = 1 # 预热次数
cfg.train.evaluation.metric_options = {'topk': (1, 5)} # 训练时的评估指标
cfg.evaluation.metric_options = {'topk': (1, 5)} # 评估时的评估指标
return cfg
# 构建训练器
kwargs = dict(
model=model_id, # 模型id
work_dir=tmp_dir, # 工作目录
train_dataset=ms_train_dataset, # 训练集
eval_dataset=ms_val_dataset, # 验证集
cfg_modify_fn=cfg_modify_fn # 用于修改训练配置文件的回调函数
)
trainer = build_trainer(name=Trainers.image_classification, default_args=kwargs)
# 进行训练
trainer.train()
# 进行评估
result = trainer.evaluate()
print('result:', result)
训练说明见示例代码中的注释,更详细的训练说明和用法见官方的训练文档。训练过程产生的log和模型权重文件保存在work_dir工作目录中,并以前缀为’best_'的文件保存了在验证集上最优精度的权重。evaluate()默认使用精度最高的模型权重进行评估。
使用训练好的模型对需要评估的数据集进行精度评估示例代码如下:
from modelscope.msdatasets import MsDataset
from modelscope.metainfo import Trainers
from modelscope.trainers import build_trainer
import tempfile
model_id = 'damo/cv_beitv2-base_image-classification_patch16_224_pt1k_ft22k_in1k'
# 加载用于评估的数据集
ms_val_dataset = MsDataset.load(
'imagenet_val', namespace='tany0699',
subset_name='default', split='validation')
tmp_dir = tempfile.TemporaryDirectory().name # 使用临时目录作为工作目录
# 构建训练器
kwargs = dict(
model=model_id, # 模型id
work_dir=tmp_dir, # 工作目录
train_dataset=None,
eval_dataset=ms_val_dataset # 评估的数据集
)
trainer = build_trainer(name=Trainers.image_classification, default_args=kwargs)
# 开始评估
result = trainer.evaluate()
print('result:', result)
评估过程默认使用模型中自带的预训练权重进行评估,以上对ImageNet1K验证集的评估结果为: result: {‘accuracy_top-1’: 86.47200775146484, ‘accuracy_top-5’: 97.99000549316406}
git clone https://www.modelscope.cn/damo/cv_beitv2-base_image-classification_patch16_224_pt1k_ft22k_in1k.git
如果该模型对你有所帮助,请引用相关的论文:
@inproceedings{beit,
title={{BEiT}: {BERT} Pre-Training of Image Transformers},
author={Hangbo Bao and Li Dong and Songhao Piao and Furu Wei},
booktitle={International Conference on Learning Representations},
year={2022},
url={https://openreview.net/forum?id=p-BhZSz59o4}
}
@article{beitv2,
title={{BEiT v2}: Masked Image Modeling with Vector-Quantized Visual Tokenizers},
author={Zhiliang Peng and Li Dong and Hangbo Bao and Qixiang Ye and Furu Wei},
year={2022},
eprint={2208.06366},
archivePrefix={arXiv},
primaryClass={cs.CV}
}