使用 Qwen2VL 多模态模型(只使用文本部分)在自定义中文语料上进行 LoRA 微调
本文介绍了使用LoRA微调Qwen2VL中文语言模型的完整流程。首先导入必要的库,包括PyTorch、Transformers和PEFT等。然后配置模型路径、数据路径和超参数(如序列长度1024,LoRA秩8)。接着加载分词器和Qwen2VL模型,冻结视觉模块仅保留文本部分,并应用LoRA适配器。数据处理阶段将文本分块并添加续写提示,使用固定长度1024进行分词。训练配置采用batch size
步骤&代码解析~
1. 导入库
import torch
from transformers import (
Qwen2VLForConditionalGeneration,
AutoTokenizer,
AutoModelForCausalLM,
Trainer,
TrainingArguments,
DataCollatorForLanguageModeling
)
from datasets import Dataset
from peft import LoraConfig, get_peft_model
import os
-
import torch:导入 PyTorch,用于张量操作和模型训练。 -
from transformers import ...:-
Qwen2VLForConditionalGeneration:Qwen2VL 模型的生成类,支持视觉和语言,这里仅用文本部分。 -
AutoTokenizer:自动加载对应模型的 tokenizer。 -
AutoModelForCausalLM:用于因果语言模型的基类(此处未直接使用,但保留)。 -
Trainer:Hugging Face 的训练器,简化训练循环。 -
TrainingArguments:配置训练超参数。 -
DataCollatorForLanguageModeling:数据整理器,用于语言模型(MLM=False 表示 CLM)。
-
-
from datasets import Dataset:加载 Hugging Face 的 Dataset 库,方便处理数据。 -
from peft import LoraConfig, get_peft_model:用于 LoRA 微调,配置 LoRA 参数并将模型转换为 LoRA 模型。 -
import os:操作系统接口,可能用于路径操作(但后续未使用)。
2. 配置参数
MODEL_NAME = "./Qwen/qwen2vl7Binstruct/" # 修改为你的文件夹路径
DATA_PATH = "./cleaned_text.txt"
SEQ_LENGTH = 1024 # 根据中文文本长度优化
LORA_RANK = 8
-
MODEL_NAME:预训练模型的本地路径(应是包含config.json等文件的目录)。 -
DATA_PATH:训练数据文本文件路径,假设是清洗后的中文文本。 -
SEQ_LENGTH:每个输入序列的最大长度(token 数),此处设为 1024。 -
LORA_RANK:LoRA 低秩矩阵的秩,控制参数量。
3. 加载模型与分词器
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True)
-
使用
AutoTokenizer从指定路径加载 tokenizer,trust_remote_code=True允许执行自定义代码(Qwen 模型需要)。
model = Qwen2VLForConditionalGeneration.from_pretrained(
MODEL_NAME,
trust_remote_code=True,
torch_dtype=torch.bfloat16,
device_map="auto"
)
-
加载 Qwen2VL 模型:
-
torch_dtype=torch.bfloat16:使用 bfloat16 精度以节省显存。 -
device_map="auto":自动将模型层分配到可用设备(如 GPU/CPU)。
-
# 冻结视觉模块
for name, param in model.named_parameters():
if "vision" in name or "cross_attention" in name:
param.requires_grad = False
-
遍历模型所有参数,如果参数名称包含
"vision"或"cross_attention",则冻结(不计算梯度)。这是因为我们只微调文本部分,视觉模块保持预训练权重不变。
# LoRA配置
peft_config = LoraConfig(
r=LORA_RANK,
lora_alpha=32,
target_modules=["q_proj", "v_proj"],
lora_dropout=0.05, # 中文数据适当降低dropout
bias="none",
task_type="CAUSAL_LM"
)
-
配置 LoRA:
-
r=LORA_RANK:秩为 8。 -
lora_alpha=32:缩放因子,通常为 2*r 经验值。 -
target_modules=["q_proj", "v_proj"]:在注意力层的 Q 和 V 投影上应用 LoRA。 -
lora_dropout=0.05:LoRA 层的 dropout,注释说中文数据适当降低。 -
bias="none":不训练偏置。 -
task_type="CAUSAL_LM":任务类型为因果语言模型。
-
model = get_peft_model(model, peft_config)
-
将原模型包装为 PEFT 模型(添加 LoRA 适配器),返回的模型只训练 LoRA 参数。
4. 数据处理(适配已分块文本)
def load_preprocessed_data(file_path):
# 假设每个段落已经是分块好的文本块
with open(file_path, 'r', encoding='utf-8') as f:
# 按两个换行符分割段落(根据实际数据格式调整)
text_blocks = f.read().split('\n')
-
定义函数读取文件,按换行符
\n分割(注释说可能按两个换行符,但代码实际是按单个换行分割)。 -
注意:分割结果可能包含空行。
# 过滤空行并添加续写提示
processed_blocks = []
for block in text_blocks:
if len(block.strip()) > 10: # 过滤短于10字符的段落
processed_blocks.append(block.strip() + "\n") # 添加续写提示
print("processed_blocks长度:",len(processed_blocks))
-
遍历每个块,去除首尾空格后如果长度 >10,则添加换行符(作为续写提示,即让模型学习在文本后生成后续内容)。
-
打印处理后的块数量。
return {"text": processed_blocks}
-
返回字典,键
"text"对应文本列表。
# 创建数据集
dataset = Dataset.from_dict(load_preprocessed_data(DATA_PATH))
-
使用
Dataset.from_dict将返回的字典转换为 Hugging Face Dataset 对象。
# 分词处理(禁用自动分块)
def tokenize_function(examples):
return tokenizer(
examples["text"],
truncation=True,
max_length=SEQ_LENGTH,
padding='max_length', # 固定长度填充
return_tensors="pt"
)
-
定义分词函数:
-
examples["text"]:一批文本。 -
truncation=True:如果文本超长则截断到max_length。 -
max_length=SEQ_LENGTH:最大长度 1024。 -
padding='max_length':填充到固定长度(所有样本长度统一为 1024)。 -
return_tensors="pt":返回 PyTorch 张量。
-
dataset = dataset.map(
tokenize_function,
batched=True,
remove_columns=["text"],
batch_size=100 # 提升处理效率
)
-
对数据集应用分词函数:
-
batched=True:批量处理。 -
remove_columns=["text"]:移除原始文本列,保留 tokenized 后的列(如input_ids,attention_mask)。 -
batch_size=100:每次处理 100 个样本。
-
5. 训练配置优化
training_args = TrainingArguments(
output_dir="./cizhouyao-output",
per_device_train_batch_size=1, # 因文本长度缩短可增大batch
gradient_accumulation_steps=1,
learning_rate=2e-5, # 中文数据适当提高学习率
num_train_epochs=1,
logging_steps=20,
save_strategy="steps",
save_steps=200,
save_total_limit=2,
fp16=True,
report_to="tensorboard",
eval_strategy="no",
weight_decay=0.01, # 防止中文过拟合
warmup_ratio=0.1 # 中文训练需要更多warmup
)
-
配置训练参数:
-
output_dir:模型保存路径。 -
per_device_train_batch_size=1:每个设备上的 batch size(因显存限制设为 1)。 -
gradient_accumulation_steps=1:梯度累积步数。 -
learning_rate=2e-5:学习率。 -
num_train_epochs=1:训练 1 个 epoch。 -
logging_steps=20:每 20 步打印日志。 -
save_strategy="steps":按步数保存模型。 -
save_steps=200:每 200 步保存一次。 -
save_total_limit=2:最多保留 2 个检查点。 -
fp16=True:启用混合精度训练(16 位浮点)。 -
report_to="tensorboard":日志发送到 TensorBoard。 -
eval_strategy="no":不进行评估。 -
weight_decay=0.01:权重衰减系数。 -
warmup_ratio=0.1:学习率 warmup 比例。
-
data_collator = DataCollatorForLanguageModeling(
tokenizer=tokenizer,
mlm=False
)
-
创建数据整理器:
-
mlm=False:表示不进行掩码语言建模,而是用于因果语言建模(CLM),即自动构建 labels 为 input_ids(标准 CLM 设置)。
-
6. 开始训练
trainer = Trainer(
model=model,
args=training_args,
train_dataset=dataset,
data_collator=data_collator
)
-
实例化 Trainer:
-
model:LoRA 微调后的模型。 -
args:训练参数。 -
train_dataset:训练数据集。 -
data_collator:数据整理器。
-
trainer.train()
-
启动训练。
更多推荐


所有评论(0)