BLIP2¶
模型描述¶
BLIP-2: 全名Bootstrapping Language-Image Pre-training - 2模型是2023 年 Salesforce提出的一种多模态模型,它从现成的冻结预训练图像编码器 (ViT)和冻结的大型语言模型 (LLM)中引导视觉语言预训练 (contrastive_language_image_pretrain), 中间添加一个轻量级的 Querying Transformer 弥补了模态 gap, 该 Transformer 分两个阶段进行预训练:
第一阶段从冻结图像编码器引导视觉-语言表示学习,强制 Q-Former 学习与文本最相关的视觉表示。
第二阶段基于冻结的语言模型引导从视觉到语言的生成学习,将Q-Former的输出连接到冻结的LLM,并对Q-Former进行训练,使其输出视觉表示能够被LLM解释。
论文 Junnan Li,et al., BLIP-2: Bootstrapping Language-Image Pre-training with Frozen Image Encoders and Large Language Models, 2023
预训练数据集下载¶
1. coco2014数据集:
├── annotations
│ ├── coco_karpathy_test.json
│ ├── coco_karpathy_train.json
│ └── coco_karpathy_val.json
│
└── images
├── test2014
├── test2015
├── train2014
└── val2014
可通过LAVIS github库提供的链接下载annotation_files (链接) 和 images (链接)。
2. Visual Genome数据集:
├── annotations
│ └── vg_caption.json
└── images
└── VG_100K
同上,可通过LAVIS github库提供的链接下载annotation_files (链接) 和 images (链接)。
关键配置项说明¶
train_dataset:
text_transforms:
type: CaptionTransform
prompt: "" # 二阶段中语言模型添加的prompt,目前仅支持固定prompt
max_length: 32 # token ids的最大长度
tokenizer:
type: LlamaTokenizer
max_length: 32 # token ids的最大长度
vocab_file: "" # 词表文件路径
model:
model_config:
type: Blip2Config
max_txt_len: 32 # token ids的最大长度,需要与train_dataset.text_transforms.max_length保持一致
checkpoint_name_or_path: "" # 模型的预训练权重,在二阶段训练时,可在此处配置一阶段训练得到的权重
prompt: False # 二阶段训练中,是否使用prompt
prompt_length: 0 # 二阶段训练中,使用的固定prompt的token长度,具体值根据tokenizer及train_dataset.text_transforms.prompt得到
# 以上两项配置与train_dataset.text_transforms.prompt需要对应
vision_config: # ImageEncoder的相关配置
type: ViTConfig
image_size: 224 # 输入图像大小
checkpoint_name_or_path: "vit_g_p16" # vit的权重文件
qformer_config:
type: QformerConfig
query_length: 32 # query数目
text_config: # 二阶段语言模型相关配置
type: LlamaConfig
seq_length: 160 # 语言模型的输入seq_length大小,在训练时该值要等于qformer的query数目+语言模型输入文字token id长度
# 即 seq_length=model.model_config.qformer_config.query_length + model.model_config.max_txt_len
checkpoint_name_or_path: "" # 语言模型权重文件
arch:
type: XXXX
# 推理任务时需要配置
processor:
type: Blip2Processor
image_processor:
type: Blip2ImageProcessor
image_size: 224 # 输入图像大小
tokenizer:
type: LlamaTokenizer
max_length: 128
vocab_file: "" # 词表文件路径
BLIP-2一阶段¶
快速使用¶
脚本启动¶
需开发者提前clone工程。
请参考使用脚本启动
示例命令如下,将会执行一个39层ViT和18层Attention Layer的Qformer的一阶段预训练:
# pretrain
python run_mindformer.py --config configs/blip2/run_blip2_pretrain_stage_1.yaml --run_mode train \
--device_target Ascend \
--train_dataset_dir [PATH_TO_DATASET]
# evaluate
python run_mindformer.py --config configs/blip2/run_blip2_stage1_vit_g_retrieval_flickr30k.yaml --run_mode eval \
--device_target Ascend \
--eval_dataset_dir [PATH_TO_DATASET]
# predict (单图片)
python run_mindformer.py --config configs/blip2/run_blip2_stage1_vit_g_zero_shot_image_classification_cifar100.yaml
--run_mode predict \
--device_target Ascend \
--predict_data [PATH_TO_IMAGE]
# predict (数据集)
python run_mindformer.py --config configs/blip2/run_blip2_stage1_vit_g_zero_shot_image_classification_cifar100.yaml
--run_mode predict \
--device_target Ascend \
--eval_dataset_dir [PATH_TO_DATASET]
调用API启动¶
需开发者提前pip安装。具体接口说明请参考API接口
Model调用接口
from mindformers import Blip2Qformer, Blip2Config
Blip2Qformer.show_support_list()
# 输出:
# support list of Blip2Qformer is:
# ['blip2_stage1_vit_g', 'blip2_stage1_classification']
# -------------------------------------
# 模型标志加载模型
model = Blip2Qformer.from_pretrained('blip2_stage1_vit_g')
#模型配置加载模型
config = Blip2Config.from_pretrained("blip2_stage1_vit_g")
config
# {'img_size': 224,
# 'num_query_token': 32,
# 'cross_attention_freq': 2,
# 'drop_path_rate': 0,
# 'use_grad_checkpoint': False,
# 'vit_model': 'vit_g_p16',
# 'layernorm_dtype': 'float32',
# 'softmax_dtype': 'float32',
# 'model_type': 'blip2',
# 'batch_size': 8,
# 'embed_dim': 256,
# 'vocab_size': 21129,
# ...
# 'is_training': True}
model = Blip2Qformer(config)
Trainer接口开启训练:
from mindformers.dataset.dataloader.multi_image_cap_dataloader import MultiImgCapDataLoader
from mindformers.trainer import Trainer
# 初始化图像-文本数据集
dataset_dir = "/data"
annotation_files = [
"vg/annotations/vg_caption.json",
"coco2014/coco/annotations/coco_karpathy_train.json"
]
image_dirs = [
"vg/images",
"coco2014/coco/images"
]
train_dataset = MultiImgCapDataLoader(dataset_dir=dataset_dir, annotation_files=annotation_files, image_dirs = image_dirs, stage="train")
# blip2一阶段初始化预训练任务
trainer = Trainer(task='contrastive_language_image_pretrain',
model='blip2_stage1_vit_g',
train_dataset=train_dataset)
# 开启预训练
trainer.train()
Trainer接口开启评估:
from mindformers.dataset.dataloader.multi_image_cap_dataloader import MultiImgCapDataLoader
from mindformers.trainer import Trainer
# 初始化图像-文本数据集
dataset_dir: "/data"
annotation_files: [
"flickr30k/annotations/test.json"
]
image_dirs: [
"flickr30k/images"
]
eval_dataset = MultiImgCapDataLoader(dataset_dir=dataset_dir, annotation_files=annotation_files, image_dirs = image_dirs, stage="eval")
# 初始化评估任务
trainer = Trainer(task='blip2_retireval',
model='blip2_stage1_vit_g',
eval_dataset=eval_dataset)
# 开启评估
trainer.eval()
Trainer接口开启推理:
from mindformers.tools.image_tools import load_image
from mindformers import Trainer
cls_trainer = Trainer(task='zero_shot_image_classification',
model='blip2_stage1_classification',
candidate_labels=["sunflower", "tree", "dog", "cat", "toy"])
# 加载输入,一张太阳花图片
input_data = load_image("https://ascend-repo-modelzoo.obs.cn-east-2.myhuaweicloud.com/XFormer_for_mindspore/clip/sunflower.png")
# 加载指定的权重以完成推理
predict_result = cls_trainer.predict(input_data=input_data,
predict_checkpoint='your_path_to/blip2_pretrained.ckpt')
print(predict_result)
# 输出
# output result is: [[{'score': 0.99999976, 'label': 'sunflower'}]]
# output result is saved at: zero_shot_image_classification_result.txt
# .........Predict Over!.............
pipeline推理:
from mindformers.tools.image_tools import load_image
from mindformers.pipeline import ZeroShotImageClassificationPipeline
# 初始化pipeline
classifier = ZeroShotImageClassificationPipeline(
model='blip2_stage1_classification',
candidate_labels=["sunflower", "tree", "dog", "cat", "toy"],
hypothesis_template="This is a photo of {}."
)
# 太阳花图片
img = load_image("https://ascend-repo-modelzoo.obs.cn-east-2.myhuaweicloud.com/XFormer_for_mindspore/clip/sunflower.png")
# 可批次处理,输入图片数组
classifier(img)
# 输出
# [[{'score': 0.99999714, 'label': 'sunflower'},
# {'score': 1.315181e-06, 'label': 'tree'},
# {'score': 7.0368844e-07, 'label': 'toy'},
# {'score': 4.7594781e-07, 'label': 'dog'},
# {'score': 3.93686e-07, 'label': 'cat'}]]
多卡训练¶
参考 快速启动指导 中的多卡启动部分,blip2的任务配置文件默认为单卡启动,如需多卡启动,注意将相关配置文件中的
use_parallel: False
改为
use_parallel: True
blip2现支持数据并行 (data parallel) 和模型并行 (model parallel),需要注意根据卡数和并行模式正确配置data_parallel 和model_parallel的值 (dp * mp = 卡数)。
评估一阶段Loss¶
from mindformers import Blip2Qformer, Blip2Processor
from mindformers.tools.image_tools import load_image
from mindspore import Tensor
# 加载模型
model = Blip2Qformer.from_pretrained('blip2_stage1_vit_g')
# 加载处理器
processor = Blip2Processor.from_pretrained('blip2_stage1_vit_g')
image_processor = processor.image_processor
tokenizer = processor.tokenizer
# 加载输入,一张太阳花图片
image = load_image("https://ascend-repo-modelzoo.obs.cn-east-2."
"myhuaweicloud.com/XFormer_for_mindspore/clip/sunflower.png")
text = ["This is a picture of sunflower."]
# 输入预处理
image_input = image_processor(image)
text_ids = tokenizer(text, max_length=32, padding='max_length')
input_ids = Tensor(text_ids['input_ids'], ms.int32)
# 放入模型计算loss
output = model(image_input, input_ids, return_tuple=True)
print(output)
# (Tensor(shape=[], dtype=Float32, value= 4.45203), -- overall_loss = loss_itc + loss_itm + loss_lm
# Tensor(shape=[], dtype=Float32, value= 0), -- loss_itc
# Tensor(shape=[], dtype=Float32, value= 0.681192), -- loss_itm
# Tensor(shape=[], dtype=Float32, value= 3.77084)) -- loss_lm
模型权重¶
本仓库中的blip2_stage1_classification来自于LAVIS的一阶段预训练权重blip2_stage1_pretrained, 基于下述的步骤获取:
从上述的链接中下载
blip2_stage1_pretrained的pytorch权重,文件名为blip2_pretrained.pth执行转换脚本,得到转换后的输出文件
blip2_stage1_pretrained.ckpt
python mindformers/models/blip2/convert_weight.py --torch_path blip2_pretrained.pth --mindspore_path ./blip2_stage1_pretrained.ckpt
BLIP-2二阶段¶
BLIP-2第二阶段是通过冻结的语言模型引导从视觉到语言的生成学习,将Q-Former的输出连接到冻结的LLM,并对Q-Former进行训练,使其输出视觉表示能够被LLM解释。 当前BLIP-2二阶段支持使用接入Llama-7b及baichuan-7b的推理任务,并暂未提供预训练模型,以下推理任务中,未加载准确的预训练权重,不保证生成结果正确。
快速使用¶
脚本启动¶
需开发者提前clone工程。
请参考使用脚本启动
示例命令如下,将会执行一个39层ViT, 18层Attention Layer的Qformer以及Llama-7b的二阶段推理,Note: 当前二阶段仅支持推理任务,并暂不提供预训练模型:
# predict (单图片) 当前二阶段未提供预训练模型,该预测代码仅展示使用方式,不保证预测结果
python run_mindformer.py --config configs/blip2/run_blip2_stage2_vit_g_llama_7b_image_to_text_generation.yaml
--run_mode predict \
--device_target Ascend \
--predict_data [PATH_TO_IMAGE]
注: 当二阶段使用baichuan_7b作为LLM模型时进行推理时,需要自行在配置文件configs/blip2/run_blip2_stage2_vit_g_baichuan_7b_image_to_text_generation.yaml中
配置对应的baichuan-7b权重文件及词表文件,如何配置可参考上文中关键配置项说明章节;
权重文件和词表文件的获取及转换参考baichuan_7b.
调用API启动¶
需开发者提前pip安装。具体接口说明请参考API接口
Model调用接口
from mindformers import Blip2ImageToTextGeneration, Blip2Config
Blip2ImageToTextGeneration.show_support_list()
# 输出:
# support list of Blip2ImageToTextGeneration is:
# ['itt_blip2_stage2_vit_g_baichuan_7b', 'itt_blip2_stage2_vit_g_llama_7b']
# -------------------------------------
# 初始化模型方式1:直接通过预训练加载
model = Blip2ImageToTextGeneration.from_pretrained('itt_blip2_stage2_vit_g_baichuan_7b')
# 初始化模型方式2:通过配置文件初始化模型
config = Blip2Config.from_pretrained("itt_blip2_stage2_vit_g_baichuan_7b")
# 可通过config配置更改相应的配置
config.model.model_config.text_config.checkpoint_name_or_path = "/path/to/the/llm_checkpoint" # 修改语言模型权重路径
model = Blip2ImageToTextGeneration(config)
Trainer接口开启推理:
from mindformers.tools.image_tools import load_image
from mindformers import Blip2Config, Blip2ImageToTextGeneration, Trainer
config = Blip2Config.from_pretrained("itt_blip2_stage2_vit_g_baichuan_7b")
# 可通过config配置更改相应的配置
config.text_config.checkpoint_name_or_path = "/path/to/the/llm_checkpoint" # 修改语言模型权重路径
config.checkpoint_name_or_path = "/path/to/the/1-st_pretrain_checkpoint" # 修改语言模型权重路径
model = Blip2ImageToTextGeneration(config)
generate_trainer = Trainer(task='image_to_text_generation',
model=model,
model_name='itt_blip2_stage2_vit_g_baichuan_7b')
# 加载输入,一张太阳花图片
input_data = load_image(
"https://ascend-repo-modelzoo.obs.cn-east-2.myhuaweicloud.com/XFormer_for_mindspore/clip/sunflower.png")
# 加载指定的权重以完成推理
predict_result = generate_trainer.predict(input_data=input_data,
hypothesis_template="###问题:\n详细描述图片内容。\n\n###答案:")
print(predict_result)
# 输出
# output result is: ['###问题:\n详细描述图片内容。\n\n###答案:这是一张图片,上面有一朵黄色的花,花朵周围有许多小黄花,它们在阳光下闪闪发光。']
# output result is saved at: zero_shot_image_to_text_generation_result.txt
# .........Predict Over!.............
pipeline推理:
from mindformers.tools.image_tools import load_image
from mindformers import Blip2Config, Blip2ImageToTextGeneration, pipeline
config = Blip2Config.from_pretrained("itt_blip2_stage2_vit_g_baichuan_7b")
# 可通过config配置更改相应的配置
config.text_config.checkpoint_name_or_path = "/path/to/the/llm_checkpoint" # 修改语言模型权重路径
config.checkpoint_name_or_path = "/path/to/the/1-st_pretrain_checkpoint" # 修改语言模型权重路径
model = Blip2ImageToTextGeneration(config)
# 初始化pipeline
generator = pipeline("image_to_text_generation", model=model)
# 太阳花图片
img = load_image(
"https://ascend-repo-modelzoo.obs.cn-east-2.myhuaweicloud.com/XFormer_for_mindspore/clip/sunflower.png")
# 可批次处理,输入图片数组
pipeline_result = generator(img, hypothesis_template='###问题:\n详细描述图片内容。\n\n###答案:')
print(pipeline_result)
# ['###问题:\n详细描述图片内容。\n\n###答案:这是一张图片,上面有一朵黄色的花,花朵周围有许多小黄花,它们在阳光下闪闪发光。']