基于 LLaMA-Factory 多模态大模型微调步骤和效果

在实际场景中,对垂直领域的图像识别一般以小样本训练的小模型为主,小模型实时性高算力消耗少,更适合边缘端的实时检测,大模型准确率高,但是需要强大的算力支持,所以可以将小模型与大模型结合以提高检测效果。

本文在 Ubuntu 系统上使用消费级显卡 3060,在小样本集上完成基于千问多模态大模型实际场景的图片检测的微调。

1. 安装 LLaMA-Factory

1.1. 创建 conda 环境

conda create --name llm-factory python=3.11

1.2. 拉取 LLaMA-Factory

git clone --depth 1 https://github.com/hiyouga/LLaMA-Factory.git

1.3. 安装 LLaMA-Factory

pip install -e ".[torch,metrics]"

1.4. 启动 LLaMA-Factory

llamafactory-cli webui

2. 准备数据集

2.1. 标注和准备 CSV 格式数据集

标注好的 CSV 格式数据集示例

2.2. 使用转换脚本,将 CSV 格式转换成 JSON 格式

def csv_to_sharegpt_json(csv_file_path, output_json_path, image_base_dir=""):
    """
    将CSV文件转换为ShareGPT格式的JSON文件
    Args:
        csv_file_path (str): 输入的CSV文件路径
        output_json_path (str): 输出的JSON文件路径
        image_base_dir (str): 图像文件的基础目录,用于构建相对路径
    """
    # 检查输入文件是否存在
    if not os.path.exists(csv_file_path):
        raise FileNotFoundError(f"CSV文件不存在: {csv_file_path}")

    # 读取CSV文件并转换为目标格式
    converted_data = []
    with open(csv_file_path, 'r', encoding='utf-8') as csv_file:
        # 读取CSV文件
        csv_reader = csv.reader(csv_file)

        # 跳过标题行(如果有)
        try:
            headers = next(csv_reader)
            print(f"检测到CSV列: {headers}")
        except StopIteration:
            print("CSV文件为空")
            return

        # 处理每一行数据
        for row_idx, row in enumerate(csv_reader):
            if len(row) < 3:
                print(f"警告: 第{row_idx + 1}行数据不足3列,跳过")
                continue

            image_path = row[0].strip()
            user_question = row[1].strip()
            ai_answer = row[2].strip()

            # 构建图像路径(如果需要添加基础目录)
            if image_base_dir and not image_path.startswith(image_base_dir):
                # 如果图像路径不是绝对路径,则相对于基础目录
                if not os.path.isabs(image_path):
                    final_image_path = os.path.join(image_base_dir, image_path)
                else:
                    final_image_path = image_path
            else:
                final_image_path = image_path

            # 创建对话条目
            conversation_entry = {
                "system": "你是一个专业的视觉识别模型。请执行以下任务:观察:查看图像中的滤网。注意其整体的颜色分布和视觉印象,不要聚焦于微小斑点。"
                         "判断:根据整体印象,"
                         "从以下四个等级中选出最符合的一项:"
                         "等级1(洁净):整体为均匀的绿色。"
                         "等级2(轻度):整体为绿色,但均匀分布着灰色杂质。"
                         "等级3(中度):整体呈灰绿色,绿色感已不鲜明。"
                         "等级4(重度):整体为灰色,仅隐约可见少量绿色或完全不可见。",
                "images": [final_image_path],
                "conversations": [
                    {
                        "from": "human",
                        "value": f"{user_question}\n<image>"
                    },
                    {
                        "from": "gpt",
                        "value": ai_answer
                    }
                ]
            }
            converted_data.append(conversation_entry)

    # 保存为JSON文件
    with open(output_json_path, 'w', encoding='utf-8') as json_file:
        json.dump(converted_data, json_file, ensure_ascii=False, indent=2)

    print(f"✅ 转换完成!")
    print(f"📊 总共转换了 {len(converted_data)} 条对话记录")
    print(f"💾 结果已保存至: {output_json_path}")

转换后的数据集格式:

转换后的 ShareGPT JSON 格式数据集

2.3. 制作数据集说明

数据集说明配置示例

2.4. 将素材拷贝到训练服务器上

3. 模型训练

3.1. 打开 LLaMA-Factory 页面,设置各种微调参数

LLaMA-Factory WebUI 微调参数设置一

LLaMA-Factory WebUI 微调参数设置二

3.2. 开始训练

3060 的显卡,5 轮次需要 14 个小时

4. 模型测试

微调后模型测试效果

5. 模型合并导出

根据训练的检查点路径导出完成模型。

6. 模型量化

使用完成模型,导出8bit 或者 4bit 的模型,需要借助更高显存 GPU 服务器,实测3060 显存无法量化 Qwen2.5-VL-3B-Instruct 模型

7. 模型发布

7.1. 安装并使用 vLLM 部署量化后的模型

7.2. 使用 open-webui 界面进行模型测试和使用

也可以使用vLLM 接口,以API 接口的方式提供给第三方应用程序调用。

8. 总结

可以通过提示词工程改进和优化模型效果。