
1、第一阶段:二次预训练
模型选择与转换
在开始训练之前,需要选择一个合适的基础模型。本文以LLaMA-7B为例,简单介绍下。为了方便后续的操作,将LLaMA-7B模型转换为Hugging Face格式。
复制from transformers import AutoModelForCausalLM, AutoTokenizer # 加载原始LLaMA模型 model_path = "original_llama_7b" tokenizer = AutoTokenizer.from_pretrained(model_path) model = AutoModelForCausalLM.from_pretrained(model_path) # 保存为Hugging Face格式 hf_path = "llama_7b_hf" model.save_pretrained(hf_path) tokenizer.save_pretrained(hf_path)
此外,为了更好地处理中文文本,还需要扩充中文词表。可以参考Chinese-LLaMA项目,它在原始词表的基础上新增了大量汉字token,从而让模型能够更好地理解和生成中文内容。
复制from transformers import AddedToken
# 加载原始tokenizer
tokenizer = AutoTokenizer.from_pretrained("llama_7b_hf")
# 添加中文字符
new_tokens = ["中文", "中国", "人工智能"] # 实际应用中需要更全面的词表
new_tokens = [AddedToken(token) for token in new_tokens]
# 扩充词表
tokenizer.add_tokens(new_tokens)
model.resize_token_embeddings(len(tokenizer))
# 保存扩充后的tokenizer
tokenizer.save_pretrained("llama_7b_zh_extended")数据准备
数据是训练模型的关键。需要根据任务需求收集海量的中文文本数据。例如,这些数据可以来自中文维基百科、新闻文章、小说等多个领域。这样可以确保模型能够学习到丰富的知识。在收集数据之后,还需要对数据进行清洗和预处理,去除其中的噪声和无关内容,以保证数据的质量。
下面是一个简单的清晰流程实例:
复制def clean_text(text):
# 去除HTML标签
text = re.sub(r'<[^>]+>', '', text)
# 去除特殊字符和多余空格
text = re.sub(r'\s+', ' ', text).strip()
# 其他自定义清洗规则
return text
# 假设我们有一个文本文件列表
text_files = ["data/wiki_zh.txt", "data/news_zh.txt"]
cleaned_data = []
for file in text_files:
with open(file, 'r', encoding='utf-8') as f:
for line in tqdm(f):
cleaned = clean_text(line)
if len(cleaned) > 10: # 过滤过短文本
cleaned_data.append(cleaned)
# 保存清洗后的数据
with open("cleaned_zh_data.txt", 'w', encoding='utf-8') as f:
f.write('\n'.join(cleaned_data))训练设置
为了降低计算资源的需求,可以使用LoRA(Low-Rank Adaptation)技术进行二次预训练。LoRA通过在模型中添加低秩矩阵来实现高效的微调,大大减少了需要训练的参数数量。例如,原本全参微调7B模型需要8卡A100,使用LoRA后,单卡3090就足够了。此外,还需要设置合适的超参数,如学习率、批次大小等。这些超参数可以根据实验结果进行调整,以达到更好的训练效果。
复制from transformers import Trainer, TrainingArguments
from peft import LoraConfig, get_peft_model
# 配置LoRA
lora_config = LoraConfig(
r=8, # 低秩矩阵的维度
lora_alpha=32,
target_modules=["q_proj", "v_proj"], # 对query和value矩阵进行适配
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM"
)
# 应用LoRA到模型
model = get_peft_model(model, lora_config)
model.print_trainable_parameters() # 查看可训练参数数量
# 准备训练参数
training_args = TrainingArguments(
output_dir="./output",
overwrite_output_dir=True,
num_train_epochs=3,
per_device_train_batch_size=4,
save_steps=10_000,
save_total_limit=2,
learning_rate=1e-4,
fp16=True,
logging_steps=100,
evaluation_strategy="steps",
eval_steps=5_000,
load_best_model_at_end=True
)
# 创建数据集
from datasets import load_dataset
dataset = load_dataset("text", data_files={"train": "cleaned_zh_data.txt"})
# 开始训练
trainer = Trainer(
model=model,
args=training_args,
train_dataset=dataset["train"],
tokenizer=tokenizer
)
trainer.train()2、第二阶段:指令微调
数据准备
在第一阶段的预训练之后,需要对模型进行指令微调,以使其能够更好地理解和执行指令。为此,需要构造指令微调数据集,这些数据集包括中文指令和对应的回答。可以参考Alpaca-CoT项目,它提供了丰富的指令数据集。如果模型需要应用于特定的领域,如金融领域,还可以收集相关的领域指令数据。
训练设置
在第一阶段的预训练模型基础上进行指令微调。同样可以使用LoRA技术,进一步降低计算成本。如果希望模型更好地理解下游任务信息,可以将指令微调数据集拼接成文档格式,放入第一阶段进行增量预训练。
训练过程
使用FT(Full-Tuning)+LoRA SFT(Sparse Fine-Tuning)的方式进行微调。在训练过程中,模型会学习如何更好地理解和执行指令。为了确保模型的性能,需要定期评估模型在指令微调数据集上的表现,并根据评估结果调整训练策略。
复制from transformers import DataCollatorForLanguageModeling
# 加载预训练模型
model = AutoModelForCausalLM.from_pretrained("./output/checkpoint-final")
tokenizer = AutoTokenizer.from_pretrained("llama_7b_zh_extended")
# 准备数据集
def preprocess_function(examples):
texts = []
for inst in examples["text"]:
try:
data = json.loads(inst)
text = f"指令:{data['instruction']}\n输入:{data['input']}\n输出:{data['output']}"
texts.append(text)
except:
continue
return tokenizer(texts, truncatinotallow=True, max_length=512)
dataset = load_dataset("json", data_files={"train": "instruction_data.json"})
tokenized_dataset = dataset.map(preprocess_function, batched=True)
# 数据收集器
data_collator = DataCollatorForLanguageModeling(
tokenizer=tokenizer,
mlm=False
)
# 微调参数
training_args = TrainingArguments(
output_dir="./sft_output",
per_device_train_batch_size=4,
num_train_epochs=5,
learning_rate=5e-5,
fp16=True,
save_steps=10_000,
logging_steps=100,
evaluation_strategy="no",
)
# 开始微调
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized_dataset["train"],
data_collator=data_collator,
tokenizer=tokenizer
)
trainer.train()低成本方案
例如8-bit优化:
复制from transformers import BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(
load_in_8bit=True,
llm_int8_threshold=6.0
)
model = AutoModelForCausalLM.from_pretrained(
"llama_7b_hf",
quantization_cnotallow=quantization_config
)3、注意事项
- 数据质量:在实际应用中,数据清洗和预处理的逻辑可能需要根据具体数据进行调整。
- 超参数调整:超参数(如学习率、批次大小、LoRA的秩等)需要根据实验结果进行调整。
- 模型评估:在训练过程中,建议定期在验证集上评估模型性能,以确保模型没有过拟合。