前言
前几篇里面学习了常见的一些多模态模型的典型架构和源代码,上一篇里面测试使用了minicpm-v系列模型,在尝试RLHF的时候发现swift特别好用特别全,记录一下对swift的一些使用,欢迎批评指正~
前一篇里面写了minicpm-v的使用方法,这里主要记录qwen2-vl的使用。
1.swift安装
- python可以安装3.10版本
- 就在这几天swift更新了3.0版本,本文使用的是swift的2.6.0版本/2.5.0版本,据群里面说swift的3.0是大更新可能差别挺大的
- 安装方法(同时在这里安装flash-attention和vllm)
bash
conda create -n swift pyhton==3.10
pip install torch torchvision
pip install flash-attn vllm qwen_vl_utils optimum transformers==4.46.1
pip install 'ms-swift[llm]' -U
- 如果网络不好,flash-attn先wget https://github.com/Dao-AILab/flash-attention/releases/download/v2.7.2.post1/flash_attn-2.7.2.post1+cu12torch2.5cxx11abiFALSE-cp310-cp310-linux_x86_64.whl,然后在pip install 这个whl【需要在这个仓库里面找符合本机的whl版本】
- 一定要注意使用的transformer库必须是4.46的不然用qwen会报错 assertion error rope
2.模型微调
2.1 SFT
一定要注意,使用qwen2-vl需要指定MAX_PIXELS,脚本里面是MAX_PIXELS,py里面是max_pixels,602112=7682828,这个值越大模型看图片看得越清楚,显存开销越大,如果不指定,默认是非常大的可能直接爆显存了
bash
NPROC_PER_NODE=1 CUDA_VISIBLE_DEVICES=0 MAX_PIXELS=602112 swift sft \
--model_type qwen2-vl-7b-instruct \
--model_id_or_path 模型路径 \
--dataset data.jsonl \
--sft_ype lora \
--use_flash_attn true \ # 提速
--batch_size 2 \
--lora_target_modules DEFAULT \
--output_dir qwen_lora \
--max_steps 3000 \
--save_total_limit 2 \
--logging_steps 10 \
--gradient_checkpointing false # true的话训练变慢
swift和minivpm-v不一样,使用jsonl格式的数据,类似这样,<image>表示这个位置有一张图,图在后面的images里面指定:
bash
#jsonl格式的数据
{"query": "<image>55555", "response": "66666", "images": ["image_path"]}
{"query": "eeeee<image>eeeee<image>eeeee", "response": "fffff", "history": [], "images": ["image_path1", "image_path2"]}
{"query": "EEEEE", "response": "FFFFF", "history": [["query1", "response2"], ["query2", "response2"]], "images": []}
- 注意swift里面如果要微调的目标模块使用正则表达式,就要使用target_regex来指定,例如qwen2-vl的指定--target_regex "^(model)(?!.(lm_head|output|emb|wte|shared|mlp|norm))." \
- 或者--target_regex "model...*layers.\d+.self_attn.(q_proj|k_proj|v_proj|o_proj)"类似这样的,可以具体看文档和模型结构
2.2 merge lora
在SFT之后合并文件,输出的结果会在运行完之后显示,默认在lora结果存储路径里面有一个-merge的文件夹
bash
#!/bin/bash
CUDA_VISIBLE_DEVICES=0 swift export \
--ckpt_dir lora结果存储路径 \
--merge_lora true
2.3 RLHF
支持CPO/DPO/SimPO等,具体参考官方文档
bash
#!/bin/bash
source activate vllm
CUDA_VISIBLE_DEVICES=0 \
swift rlhf \
--rlhf_type cpo \
--model_type minicpm-v-v2_6-chat \ # 模型类型,可以在官方文档支持的模型里面找,或者报错了在报错信息里面找哈哈哈
--model_id_or_path 模型存储路径/ \
--beta 0.1 \
--rpo_alpha 0.1 \
--sft_type lora \
--dataset dataset_dpo.jsonl \
--lora_target_modules DEFAULT \
--max_steps 500 \
--save_steps 250 \
--batch_size 2 \
--learning_rate 5e-5 \
--gradient_checkpointing false \
--warmup_ratio 0.03 \
--save_total_limit 2 \
--output_dir output \
--logging_steps 10
注意RHLF的数据集格式:
bash
{"system": "123", "query": "11111", "response": "22222", "rejected_response": "33333", "images": ["image_path"], "history": [["query1", "response1"], ["query2", "response2"]]}
{"system": "123", "query": "aaaaa", "response": "bbbbb", "rejected_response": "ccccc", "images": ["image_path"], "history": [["query1", "response1"], ["query2", "response2"]]}
{"system": "123", "query": "AAAAA", "response": "BBBBB", "rejected_response": "CCCCC", "images": ["image_path"], "history": [["query1", "response1"], ["query2", "response2"]]}
3. 模型量化和推理
3.1 qwen2-vl量化
- qwen2-vl的int4的模型qlora微调后不支持merge并且推理很慢,官方推荐先lora在merge再量化
- 原始模型微调后,不支持autoawq量化,支持gptq量化,同样需要指定最大像素,否则爆显存
- gptq量化时load_dataset_config为true使用训练时候的数据集来进行量化
- gptq量化后准确率损失不大
bash
CUDA_VISIBLE_DEVICES=0 MAX_PIXELS=1003520 swift export \
--ckpt_dir '训练好的模型路径' \
--merge_lora true --quant_bits 4 \
--load_dataset_config true --quant_method gptq
3.2 模型推理
- 这里可以参考前面一篇minicpm-v使用里面的介绍【多模态】MiniCPM-V多模态大模型使用学习,注意用上加速推理节约时间
- 注意设置最大像素例如os.environ['MAX_PIXELS']='1003520'
python
-----flash-attn用于swift推理
kwargs = {}
# kwargs['use_flash_attn'] = True # use flash_attn
model_id_or_path = None
model, tokenizer = get_model_tokenizer(model_type, model_id_or_path=model_id_or_path,
model_kwargs={'device_map': 'auto'}, **kwargs)
----flash-attn用于qwen2-vl
model_name = "。。。。。。"
model = Qwen2VLForConditionalGeneration.from_pretrained(model_name, torch_dtype="auto", device_map="auto",attn_implementation="flash_attention_2")
model.eval()
-----minicpm-v的推理也flash-attention-2加速
model = AutoModel.from_pretrained('。。。。。。', trust_remote_code=True,attn_implementation='flash_attention_2')
3.3 CLI推理
数据集格式和训练集一样
bash
{"query": "<image>55555", "response": "66666", "images": ["image_path"]}
{"query": "eeeee<image>eeeee<image>eeeee", "response": "fffff", "history": [], "images": ["image_path1", "image_path2"]}
{"query": "EEEEE", "response": "FFFFF", "history": [["query1", "response2"], ["query2", "response2"]], "images": []}
推理脚本,里面的val_dataset是待推理的数据集,result_dir是输出的结果保存的地址,输出的是一个jsonl文件
bash
CUDA_VISIBLE_DEVICES=0 MAX_PIXELS=602112 swift infer --ckpt_dir 模型地址 --use_flash_attn true --val_dataset data_need_infer.jsonl --save_result true --result_dir result_output