Qwen-VL-Chat进行Qlora微调全过程讲解

序言

        Qwen-VL-Chat的Qlora微调有很多博主都讲的非常好,我也是参考的几个博主的文章之后,成功进行了微调。由于我是一个小白,在微调过程中,遇到了一些问题,然而许多博主并没有提及到这些问题,所以写这篇文章有两个目的:(1)记录自己的学习;(2)如果有向我一样刚接触这一块的小白,根据这篇文章可以更好,更方便的去动手微调。

        情况说明:本微调教程是在AutoDL平台上租用容器实例进行的,如果有小伙伴是用自己的电脑进行本地微调,那么需要自行根据需求做出相应调整(我没试过,所以不做评价)。

建议及推荐:

  • 显存至少需要10GB以上,低于10GB微调无法进行。
  • python 3.8及以上版本
  • pytorch 1.12及以上版本,推荐2.0及以上版本
  • 建议使用CUDA 11.4及以上(GPU用户需考虑此选项)

目录

序言

模型部署

1.1 下载Qwen-VL-chat模型

1.2 下载Qwen-VL-Chat所需要的依赖环境

1.3 使用Qwen-VL-Chat进行推理

数据准备

2.1 数据格式要求

2.2 数据预处理

模型微调

3.1 Qwen-VL-Chat微调相关文件下载

3.2 Qwen-VL-Chat微调所需的依赖环境

3.3 Qwen-VL-Chat开始微调

3.4 将微调好的Qwen-VL-Chat与原模型进行合并

3.5 对新Qwen-VL-Chat模型进行推理测试


模型部署

1.1 下载Qwen-VL-chat模型

        首先在AutoDL平台上租一台容器实例,我租用的配置如下图所示:

        我下载模型用的是modelscope,官网为:魔搭社区。(使用modelscope下载速度更快)

# 创建虚拟环境
conda create --name qwenvl python=3.10 -y
# 激活虚拟环境
source activate qwenvl

# 下载modelscope工具,用于下载qwen-vl-chat模型
pip install modelscope

# 下载qwen-vl-chat模型
# --cache_dir xxpathxx (xxpathxx可更换你的存储文件夹路径) 
modelscope download --model qwen/qwen-vl-chat --cache_dir '/root/autodl-tmp'


1.2 下载Qwen-VL-Chat所需要的依赖环境

pip install modelscope -U
pip install transformers accelerate tiktoken -U
pip install einops transformers_stream_generator -U
pip install "pillow==9.*" -U
pip install torchvision
pip install matplotlib -U
pip install bitsandbytes

1.3 使用Qwen-VL-Chat进行推理

        准备一张图片,我们一起去试一下利用Qwen-Vl-Chat进行推理,看模型能不能跑起来。运行代码如下(modelscope上有两种调用方式,这里选取一种)

import os
os.environ['CUDA_VISIBLE_DEVICES'] = '0'
from modelscope import (
    snapshot_download, AutoModelForCausalLM, AutoTokenizer, GenerationConfig,
)
from transformers import BitsAndBytesConfig
import torch
#model_id = 'qwen/Qwen-VL-Chat'
#revision = 'v1.1.0'

#model_dir = snapshot_download(model_id, revision=revision)
# model_dir为大模型路径,你可以根据自己的需求进行修改
model_dir = '/root/autodl-tmp/qwen/qwen-vl-chat'
torch.manual_seed(1234)
quantization_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_compute_dtype=torch.float16,
    bnb_4bit_quant_type='nf4',
    bnb_4bit_use_double_quant=True,
    llm_int8_skip_modules=['lm_head', 'attn_pool.attn'])

tokenizer = AutoTokenizer.from_pretrained(model_dir, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(model_dir, device_map="auto", 
                                             trust_remote_code=True, fp16=True,
                                             quantization_config=quantization_config).eval()
model.generation_config = GenerationConfig.from_pretrained(model_dir, trust_remote_code=True)

query = tokenizer.from_list_format([
    {'image': '/root/autodl-tmp/Data/image.jpg'},
    {'text': '这是什么'},
])
response, history = model.chat(tokenizer, query=query, history=None)
print(response)

response, history = model.chat(tokenizer, '输出检测框', history=history)
print(response)
image = tokenizer.draw_bbox_on_latest_picture(response, history)
image.save('/root/autodl-tmp/Data/output_chat2.jpg')

        正常运行该代码后,可以看到如下结果,说明模型跑通了,及Qwen-VL-Chat部署成功,及可以进行后续操作了。


数据准备

2.1 数据格式要求

        你的图片数据集需要转换成Json数据形式,才能进行训练。Json数据格式如下所示:

[
  {
    "id": "identity_0",
    "conversations": [
      {
        "from": "user",
        "value": "Picture 1: <img>/root/autodl-tmp/check/ImageInput/部件数据/0001201905261055369600000110202000200000000000000000000000.jpg</img>\n描述下图片的主要对象以及他们的位置信息"
      },
      {
        "from": "assistant",
        "value": "<ref>复合绝缘子</ref><box>(760,414),(844,892)</box> <ref>防震锤</ref><box>(341,814),(446,873)</box> <ref>防震锤</ref><box>(337,911),(441,971)</box> <ref>挂点金具</ref><box>(731,941),(805,1080)</box> <ref>均压环</ref><box>(737,873),(820,941)</box> <ref>均压环</ref><box>(784,371),(865,431)</box>"
      }
    ]
  },
  {
    "id": "identity_1",
    "conversations": [
      {
        "from": "user",
        "value": "Picture 2: <img>/root/autodl-tmp/check/ImageInput/部件数据/0001201905261057013250000120202000200000000000000000000000.jpg</img>\n描述下图片的主要对象以及他们的位置信息"
      },
      {
        "from": "assistant",
        "value": "<ref>复合绝缘子</ref><box>(671,748),(768,1080)</box> <ref>复合绝缘子</ref><box>(844,735),(948,1080)</box> <ref>避雷器</ref><box>(529,522),(645,1072)</box> <ref>均压环</ref><box>(641,677),(769,787)</box> <ref>均压环</ref><box>(811,666),(940,773)</box>"
      }
    ]
  }
]

2.2 数据预处理

       如果你准备的图谱数据集如下图所示,同时有.jpg图片和对应的.xml信息,那接下来我教您如何将数据集转换成所需要的json数据集。

        将你的数据集,进行预处理,转换成符合要求的数据格式。转换代码如下:

import json
import os
import xml.etree.ElementTree as ET

# 初始化JSON数据结构

all_data = []

# 指定XML文件所在的目录
xml_directory = '/root/autodl-tmp/Data/ImageInput/部件数据'
i = 0
# 遍历目录下的所有XML文件
for filename in os.listdir(xml_directory):

    if filename.endswith('.xml'):
        # 构建完整的文件路径
        file_path = os.path.join(xml_directory, filename)
        i = i + 1
        # 解析XML文件
        tree = ET.parse(file_path)
        root = tree.getroot()
        file_name = root.find('filename').text
        json_data = {
            "id": f"identity_{i - 1}",
            "conversations": []
        }

        conversation1 = {
            "from": "user",
            "value": f"Picture {i}: <img>/root/autodl-tmp/Data/ImageInput/部件数据/{file_name}</img>\n描述下图片的主要对象以及他们的位置信息"
        }
        json_data['conversations'].append(conversation1)
        conversation = {
            "from": "assistant",
            "value": ""
        }
        for obj_elem in root.findall('object'):
            # 提取必要的数据
            object_name = obj_elem.find('name').text
            bbox = obj_elem.find('bndbox')
            if bbox is not None:  # 确保bndbox元素存在
                xmin = int(bbox.find('xmin').text)
                ymin = int(bbox.find('ymin').text)
                xmax = int(bbox.find('xmax').text)
                ymax = int(bbox.find('ymax').text)
            else:
                # 处理bndbox不存在的情况
                print(f"Warning: No bounding box found in {filename}")
                continue
            a = f'<ref>{object_name}</ref><box>({xmin},{ymin}),({xmax},{ymax})</box>'
            # 创建单个conversation对象并添加到JSON数组中
            if conversation["value"] == "":
                conversation["value"] = a
            else:
                conversation["value"] += " " + a

        json_data['conversations'].append(conversation)

        all_data.append(json_data)

# 将JSON对象转换为字符串并保存到文件中
with open('/root/autodl-tmp/Data/ImageJsonData', 'w', encoding='utf-8') as f:
    json.dump(all_data, f, ensure_ascii=False, indent=2)

print("转换完成,所有XML文件的数据已整合到json文件中。")

该代码中的注意事项:在代码处该三处位置,根据自己的需求进行修改。

(1)

(2)

(3)

        正常运行该代码后,会有如下结果和json数据:


模型微调

3.1 Qwen-VL-Chat微调相关文件下载

        Qwen-VL-Chat模型部署好,而且json数据集准备好之后,还需要下载一个用于模型微调的文件。

git clone https://github.com/QwenLM/Qwen-VL.git

        如果使用git clone 失败或者报错,你可以直接进入该网站,下载ZIP文件,解压缩后导入Autodl中的容器实例。

        文件内容如下:


3.2 Qwen-VL-Chat微调所需的依赖环境

# 在终端窗口输入指令,进入到刚刚下载得Qwen-VL文件
cd autodl-tmp/qwen/Qwen-VL

# 根据requierment下载依赖环境
pip install -r requirements.txt
pip install -r requirements_openai_api.txt
pip install -r requirements_web_demo.txt
pip install peft

3.3 Qwen-VL-Chat开始微调

        在Qwen-VL文件夹下,创建.sh文件,命名为qlora.sh。并将下列指令复制到qlora.sh文件中。指令如下:

python3 /root/autodl-tmp/qwen/Qwen-VL/finetune.py     --model_name_or_path /root/autodl-tmp/qwen/qwen-vl-chat      --data_path /root/autodl-tmp/Data/ImageJsonData/data.json     --bf16 True     --fix_vit True     --output_dir output_qwen     --num_train_epochs 5     --per_device_train_batch_size 1     --per_device_eval_batch_size 1     --gradient_accumulation_steps 8     --evaluation_strategy "no"     --save_strategy "steps"     --save_steps 1000     --save_total_limit 10     --learning_rate 1e-5     --weight_decay 0.1     --adam_beta2 0.95     --warmup_ratio 0.01     --lr_scheduler_type "cosine"     --logging_steps 1     --report_to "none"     --model_max_length 600     --lazy_preprocess True     --gradient_checkpointing true     --use_lora

 注意事项:该指令必须是一行,不能有手动换行。如下图片是为了方便大家查看。

然后在终端执行如下命令:

sh qlora.sh

如果出现权限问题,请自行查询解决方法。

正确运行开始微调时如图所示(如遇到报错,此步骤后有详细讲解,请参考):

如果遇到如下错误,可以根据下列操作进行解决。

错误一:运行 sh qlora.sh时,出现如下报错。且执行pip install deepspeed后同样报错。

解决方法:

# 添加下载源
conda config --add channels https://anaconda.org

# 添加完之后在进行下载
pip install deepspeed

错误二:运行 sh qlora.sh时,出现如下错误。

解决方法:

        (1)在1.1步骤中下载的Qwen-VL-Chat模型中,找到modeling_qwen.py文件。

        (2)打开modeling_qwen.py文件,在代码654行处,作出如下修改。


3.4 将微调好的Qwen-VL-Chat与原模型进行合并

        在微调好之后,需要将微调好的Qwen-VL-Chat模型与原大模型进行合并,合并之后就可以正常推理了。合并代码如下:

from peft import AutoPeftModelForCausalLM  # 确保导入所需的模块
from modelscope import (
     AutoTokenizer
)
 
path_to_adapter = "/root/autodl-tmp/qwen/Qwen-VL/output_qwen"
# 从预训练模型中加载自定义适配器模型
model = AutoPeftModelForCausalLM.from_pretrained(
    path_to_adapter,  # 适配器的路径
    device_map="auto",  # 自动映射设备
    trust_remote_code=True  # 信任远程代码
).eval()  # 设置为评估模式
new_model_directory = "/root/autodl-tmp/qwen/New-Model-qwenvl"
tokenizer = AutoTokenizer.from_pretrained(
    path_to_adapter, trust_remote_code=True,
)
tokenizer.save_pretrained(new_model_directory)
 
# 合并并卸载模型
merged_model = model.merge_and_unload()
# 保存合并后的模型
merged_model.save_pretrained(new_model_directory, max_shard_size="2048MB", safe_serialization=True)

注意事项:

如若出现错误:AttributeError: 'QWenTokenizer' object has no attribute 'IMAGE_ST'
请参考以下链接:

[BUG] <title>合并lora权重时遇到AttributeError: 'QWenTokenizer' object has no attribute 'IMAGE_ST'问题 · Issue #287 · QwenLM/Qwen-VL (github.com)


3.5 对新Qwen-VL-Chat模型进行推理测试

        推理测试的代码与1.3中的代码一致,只需将模型路径修改成微调后新模型的路径即可。测试输入的数据自己根据需求修改即可。

输出结果:

测试通过!!!!!!!!!!!!!

完结撒花!!!!!!!!!!!!!

参考文章:

通义千问(Qwen-VL)本地微调_qwen-vl 微调-优快云博客

Qwen-VL Best Practice — swift 2.5.0.dev0 documentation

Qwen-VL大模型LoRA微调、融合及部署_qwen-vl微调-优快云博客

通义千问-VL-Chat · 模型库 (modelscope.cn)

[BUG] <title>合并lora权重时遇到AttributeError: 'QWenTokenizer' object has no attribute 'IMAGE_ST'问题 · Issue #287 · QwenLM/Qwen-VL (github.com)

Update modeling_qwen.py · Qwen/Qwen-VL-Chat at e718765 (huggingface.co)

<think>好的,我现在需要帮助用户解决关于Qwen-VL-OCR的使用指南或错误解决的问题。首先,回顾之前的对话,用户遇到了GLIBC版本不兼容的问题,并得到了解决方案。现在用户转向Qwen-VL-OCR,可能是在部署过程中遇到问题,或者想了解如何正确使用OCR功能。 首先,用户提到的站内引用[1]是关于Qwen-VL的Docker部署指南,引用[2]是关于微调后的推理脚本。虽然这些引用可能不是直接针对OCR的,但需要结合这些信息来推断可能的OCR相关步骤。Qwen-VL本身是多模态模型,可能包含OCR功能,因此需要查找Qwen-VL的官方文档或社区资源来确认OCR的具体使用方法。 用户的需求是查找Qwen-VL-OCR的信息或解决方案,特别是使用指南或错误处理。可能的步骤包括: 1. **确认Qwen-VL是否包含OCR模块**:查阅官方文档,确认OCR是否是Qwen-VL的内置功能,或是需要额外安装的组件。 2. **部署指南**:如果用户已经按照引用[1]部署了Qwen-VL,可能需要进一步配置OCR相关依赖,如安装Tesseract或其他OCR库。 3. **使用示例**:提供调用OCR功能的代码示例,比如如何加载图像并进行文本识别。 4. **常见错误**:比如依赖缺失、模型加载失败、GPU内存不足等,需要给出相应的解决方案,例如安装依赖库、调整模型参数或检查CUDA版本。 5. **参考资源**:引导用户查阅官方GitHub仓库、ModelScope文档或社区讨论,以获取最新信息。 同时,需要考虑用户可能遇到的典型问题,如环境配置错误、模型路径不正确、缺少OCR引擎等。结合之前的GLIBC问题,可能需要提醒用户确保系统依赖项已正确安装,如GLIBC版本足够,或其他系统库的兼容性。 最后,确保回答结构清晰,分步骤说明,并预生成相关问题,帮助用户进一步探索可能的需求。</think>### Qwen-VL-OCR使用与问题排查指南 #### 一、Qwen-VL-OCR功能定位 Qwen-VL系列模型原生支持**多模态图文理解**,其OCR能力通过以下方式实现: 1. **内置视觉编码器**:自动提取图像中的文本位置信息 2. **文本解码模块**:结合语言模型生成结构化文本输出 3. **扩展插件支持**:可通过集成Tesseract/PaddleOCR等开源OCR工具增强识别精度[^1] --- #### 二、基础使用流程(以ModelScope部署为例) ```bash # 1. 克隆仓库(已包含OCR相关接口) git clone https://www.modelscope.cn/qwen/Qwen-VL-Chat.git cd Qwen-VL-Chat # 2. 安装OCR增强依赖(推荐) pip install pytesseract paddleocr>=2.6 # 3. 示例代码:带OCR的图文问答 from modelscope import AutoModelForCausalLM, AutoTokenizer model = AutoModelForCausalLM.from_pretrained("qwen/Qwen-VL-Chat", device_map="auto") tokenizer = AutoTokenizer.from_pretrained("qwen/Qwen-VL-Chat") query = tokenizer.from_list_format([ {'image': 'https://example.com/invoice.jpg'}, # 支持本地/URL路径 {'text': '识别图中的所有文字'} ]) response, _ = model.chat(tokenizer, query=query) print(response) # 输出结构化文本[^1] ``` --- #### 三、常见错误解决方案 1. **OCR识别率低** - 安装PaddleOCR增强包: ```bash pip install "paddleocr>=2.6" --extra-index-url=https://pypi.tuna.tsinghua.edu.cn/simple ``` - 代码中显式指定OCR引擎: ```python model.eval(ocr_fn='paddleocr') # 可选tesseract/paddleocr/auto ``` 2. **CUDA内存不足** ```python # 降低视觉编码器分辨率 model = AutoModelForCausalLM.from_pretrained( "qwen/Qwen-VL-Chat", device_map="auto", image_size=448 # 默认896,可调整为448/224 ) ``` 3. **依赖库冲突** - 使用官方Docker镜像避免环境问题: ```dockerfile FROM registry.cn-hangzhou.aliyuncs.com/modelscope-repo/modelscope:ubuntu20.04-cuda11.8.0-py38-torch2.0.1-tf2.13.0-1.9.5 RUN pip install paddleocr pytesseract ``` --- #### 四、高级应用示例 **场景:发票信息提取** ```python # 加载自定义OCR配置 from paddleocr import PaddleOCR custom_ocr = PaddleOCR(use_angle_cls=True, lang="ch") response = model.chat( tokenizer, query=[ {'image': 'invoice.jpg'}, {'text': '提取发票号、金额和开票日期'} ], ocr_fn=custom_ocr.ocr # 注入自定义OCR实例 ) ``` --- #### 五、关键文档索引 1. [Qwen-VL技术报告](https://arxiv.org/abs/2308.12966) - OCR评估指标说明(第4.3节) 2. [ModelScope Notebook示例](https://modelscope.cn/studios/qwen/Qwen-VL-Chat-Demo/summary) - 含OCR增强对比实验 3. [PaddleOCR集成指南](https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.7/doc/doc_ch/whl.md) -语言模型配置方法 ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值