LLaMA-Factory微調多模態大語言模型教程

BUAADreamer發表於2024-05-31

本文旨在結合筆者自身的實踐經歷,詳細介紹如何使用 LLaMA-Factory 來微調多模態大語言模型。目前倉庫已支援若干流行的MLLM比如LLaVA-1.5,Yi-VL,Paligemma等。

2024.5.29 注本文後續不再更新,如果想了解更新的特性和功能歡迎訪問知乎部落格https://zhuanlan.zhihu.com/p/699777943

值得注意的是現在LLaMA-Factory引入了CLI,因此呼叫方式更加簡單,只需要簡單的幾行命令即可開始微調。

環境準備

首先安裝LLaMA-Factory

git clone https://github.com/hiyouga/LLaMA-Factory.git
cd LLaMA-Factory
pip install -e .[torch,metrics]

檢查機器含有可用GPU

import torch
try:
  assert torch.cuda.is_available() is True
except AssertionError:
  print("Please set up a GPU before using LLaMA Factory")

多模態多輪對話資料集構建

這裡出於方便的考慮,以倉庫自帶的 mllm_demo 資料集作為例子。在此也推薦一些筆者建立的hf資料集可供使用,都能適配LLaMA-Factory,場景分別是通用,醫學,動漫。

https://huggingface.co/datasets/BUAADreamer/llava-en-zh-300k

https://huggingface.co/datasets/BUAADreamer/llava-med-zh-instruct-60k

https://huggingface.co/datasets/BUAADreamer/pokemon-gpt4-1k

本地影像準備

專案的 data/mllm_demo_data 目錄下有三張比較新的影像,兩張為拜仁慕尼黑的球員本賽季在主場慶祝,1張為桂海潮教授在演講。本文以這三張影像作為例子進行講解,讀者可以換成任意的自己的影像

img

​ data/mllm_demo_data/1.jpg

img

​ data/mllm_demo_data/2.jpg

img

​ data/mllm_demo_data/3.jpg

本地多輪對話資料構建

直接修改 data/mllm_demo.json 即可,這裡用python寫入檔案作為演示,格式遵循類似openai的聊天格式。images 引數設定為含有一張影像所在路徑的列表。注意:這裡的影像路徑為絕對路徑相對於當前位置的相對路徑

[
  {
    "messages": [
      {
        "content": "他們是誰",
        "role": "user"
      },
      {
        "content": "他們是來自拜仁慕尼黑的主力中鋒凱恩和主力中場格雷茨卡。",
        "role": "assistant"
      },
      {
        "content": "他們在做什麼?",
        "role": "user"
      },
      {
        "content": "他們在拜仁慕尼黑主場激情慶祝。",
        "role": "assistant"
      }
    ],
    "images": [
      "data/mllm_demo_data/1.jpg"
    ]
  },
  {
    "messages": [
      {
        "content": "他是誰?",
        "role": "user"
      },
      {
        "content": "他是拜仁慕尼黑的功勳前鋒托馬斯穆勒。",
        "role": "assistant"
      },
      {
        "content": "他為什麼在地上?",
        "role": "user"
      },
      {
        "content": "因為他正在雙膝跪地滑行慶祝。",
        "role": "assistant"
      }
    ],
    "images": [
      "data/mllm_demo_data/2.jpg"
    ]
  },
  {
    "messages": [
      {
        "content": "請描述這張影像",
        "role": "user"
      },
      {
        "content": "中國航天員桂海潮正在發表演講",
        "role": "assistant"
      },
      {
        "content": "他取得過哪些成就?",
        "role": "user"
      },
      {
        "content": "他於2022年6月被任命為神舟十六號任務的有效載荷專家,從而成為2023年5月30日進入太空的首位平民宇航員。他負責在軌操作空間科學實驗有效載荷。",
        "role": "assistant"
      }
    ],
    "images": [
      "data/mllm_demo_data/3.jpg"
    ]
  }
]

本地資料更新至dataset_info.json

如果是自己建立的本地新資料集,需要在 data/dataset_info.json 里加入對應的資訊

"mllm_demo": {
    "file_name": "mllm_demo.json",
    "formatting": "sharegpt",
    "columns": {
      "messages": "messages",
      "images": "images"
    },
    "tags": {
      "role_tag": "role",
      "content_tag": "content",
      "user_tag": "user",
      "assistant_tag": "assistant"
    }
},

上傳資料集到huggingface

以上是影像儲存在本地的使用方法,如果想分享自己的資料集,可以使用下列程式碼,需要先到huggingface申請自己的key:https://huggingface.co/settings/tokens

import huggingface_hub
huggingface_hub.login("hf_xxxxx") #替換為你自己的key從而登入hf

from datasets import Dataset, Features, Image, Sequence, Value
def gen():
    for data in examples:
        yield data

#構建資料集feature
features = Features(
    {
        'messages': [
            {
                'role': Value(dtype='string', id=None),
                'content': Value(dtype='string', id=None),
            }
        ],
        'images': Sequence(feature=Image(decode=True, id=None), length=-1, id=None),
    }
)

#使用迭代生成
dataset = Dataset.from_generator(gen, features=features)

#push到huggingface
dataset.push_to_hub("BUAADreamer/mllm_demo")

huggingface資料更新至dataset_info.json

將上傳好的huggingface資料集資訊更新在 data/dataset_info.json 中

"mllm_demo_hf": {
    "hf_hub_url": "BUAADreamer/mllm_demo",
    "formatting": "sharegpt",
    "columns": {
      "messages": "messages",
      "images": "images"
    },
    "tags": {
      "role_tag": "role",
      "content_tag": "content",
      "user_tag": "user",
      "assistant_tag": "assistant"
    }
},

多模態對話微調

配置監督微調Yaml檔案

這裡以lora為例,我們建立一個 config/llava_lora_sft.yaml

根據自己需求,需要修改的引數主要有:

  • model_name_or_path 和 template,對應模型和聊天模板,目前主要支援:
  • llava-1.5 和 vicuna
  • yi-vl 和 yi_vl
  • paligemma 和 gemma
  • finetuning_type 和 lora_target ,finetuning_type 可以改為 full 從而全引數微調
  • dataset 對應 data/dataset_info.json 對應的資料集的key名字,這裡以本地的 mllm_demo 為例
  • 其他訓練引數比如 learning_rate num_train_epochs output_dir 等。由於llava-1.5主要面向英文,因此中文資料需要較多輪次才能擬合。
### model
model_name_or_path: llava-hf/llava-1.5-7b-hf
visual_inputs: true


### method
stage: sft
do_train: true
finetuning_type: lora
lora_target: q_proj,v_proj

### dataset
dataset: mllm_demo
template: vicuna
cutoff_len: 1024
max_samples: 1000
overwrite_cache: true
preprocessing_num_workers: 16

### output
output_dir: saves/llava1_5-7b/lora/sft
logging_steps: 10
save_steps: 500
plot_loss: true
overwrite_output_dir: true

### train
per_device_train_batch_size: 1
gradient_accumulation_steps: 8
learning_rate: 0.0001
num_train_epochs: 50.0
lr_scheduler_type: cosine
warmup_steps: 0.1
fp16: true
train_mm_proj_only: false

### eval
do_eval: false

配置LLaVA式的預訓練yaml檔案

LLaVA中的預訓練是隻訓練 multi_modal_projector ,凍結 language_model 和 vision_tower 。因此我們需要將 finetuning_type 設定為 full ,將 train_mm_proj_only 設定為 true。預訓練資料使用單輪圖生文對話資料,可以參考以下 mllm_pt_demo 資料集:

https://huggingface.co/datasets/BUAADreamer/mllm_pt_demo

開始微調

一條命令微調。Lora微調只需要16G視訊記憶體,2min即可跑完

CUDA_VISIBLE_DEVICES=0 llamafactory-cli train config/llava_lora_sft.yaml

網頁聊天測試

一條命令部署。LLaVA-7B只需要16G視訊記憶體。注意如果是其他模型需要更換為訓練中使用的template

CUDA_VISIBLE_DEVICES=0 llamafactory-cli webchat \
--model_name_or_path llava-hf/llava-1.5-7b-hf \
--adapter_name_or_path saves/llava1_5-7b/lora/sft \
--template vicuna \
--visual_inputs

微調後Demo展示

以下是三條資料的測試,對於這些比較新鮮的知識模型完全擬合了,(仁迷狂喜

data/mllm_demo_data/1.jpg 測試結果:

img

data/mllm_demo_data/2.jpg 測試結果:

img

data/mllm_demo_data/3.jpg 測試結果:

img

模型匯出和上傳huggingface

先配置 config/llava_lora_sft_export.yaml 檔案,記得替換 export_hub_model_id 和 hf_hub_token

# model
model_name_or_path: llava-hf/llava-1.5-7b-hf
adapter_name_or_path: saves/llava1_5-7b/lora/sft
template: vicuna
finetuning_type: lora
visual_inputs: true

# export
export_dir: models/llava1_5-7b
export_size: 2
export_device: cpu
export_legacy_format: false
export_hub_model_id: xxxxx/My-LLaVA-7B
hf_hub_token: xxxxx

一行命令匯出並上傳到huggingface

CUDA_VISIBLE_DEVICES=0 llamafactory-cli export config/llava_lora_sft_export.yaml

總結

所有程式碼都可以在以下倉庫復現

https://github.com/BUAADreamer/MLLM-Finetuning-Demo

同時,筆者也使用 LLaMA-Factory 訓練了一箇中文醫學多模態大模型 Chinese-LLaVA-Med,目前還在探索中,歡迎關注!更多MLLM的微調例子可以參考此專案:

https://github.com/BUAADreamer/Chinese-LLaVA-Med

此外,還有 @hiyouga 大佬訓練的多輪對話版本paligemma,值得一提的是,這個模型小而強大,可以做許多多模態任務,還是多語言的:

https://huggingface.co/hiyouga/PaliGemma-3B-Chat-v0.1

相關文章