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的秩等)需要根据实验结果进行调整。
- 模型评估:在训练过程中,建议定期在验证集上评估模型性能,以确保模型没有过拟合。