将 huggingface 仓库的 FlagAlpha/Llama2-Chinese-7b-Chat 模型下载到本地并做训练

一、下载模型到本地并训练

要将 Hugging Face 仓库中的 FlagAlpha/Llama2-Chinese-7b-Chat 模型下载到本地,并从本地路径加载和训练该模型,可以按照以下步骤进行操作:

1. 环境准备

安装必要的软件包

首先,确保你已经安装了所需的 Python 包,包括 transformersacceleratedatasetshuggingface_hub。你可以使用 pip 来安装这些包:

pip install transformers accelerate datasets huggingface_hub

确保硬件要求

Llama2-7B 模型非常大,训练和推理需要强大的硬件支持,通常需要多块高性能 GPU(例如 NVIDIA A100)。确保你的计算环境满足以下要求:

  • GPU:推荐至少一块具有 40GB 显存的 GPU。
  • 内存:至少 64GB 的系统内存。
  • 存储:至少 100GB 的可用磁盘空间。

2. 获取 Hugging Face 访问权限

注册并获取访问令牌

  1. 前往 Hugging Face 网站并注册一个账户(如果尚未注册)。
  2. 登录后,进入账户设置,找到 Access Tokens 页面。
  3. 生成一个新的访问令牌,并复制保存该令牌。

登录 Hugging Face

在终端中运行以下命令并输入你的访问令牌以登录 Hugging Face:

huggingface-cli login

3. 下载模型到本地

创建本地存储目录

选择一个目录来存储下载的模型,例如 ./models/Llama2-Chinese-7b-Chat

mkdir -p ./models/Llama2-Chinese-7b-Chat

使用 transformers 下载模型

以下是一个 Python 脚本示例,用于下载模型和分词器到本地目录:

# pip install --upgrade transformers bitsandbytes accelerate peft
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
import os

# 定义模型名称和本地路径
model_name = "FlagAlpha/Llama2-Chinese-7b-Chat"
local_model_path = "./models/Llama2-Chinese-7b-Chat"

# 创建本地存储目录(如果不存在)
os.makedirs(local_model_path, exist_ok=True)

# 配置 BitsAndBytesConfig
bnb_config = BitsAndBytesConfig(
    load_in_8bit=True,  # 启用 8-bit 量化
    llm_int8_threshold=6.0,  # 可选参数,根据需要调整
    llm_int8_has_fp16_weight=False  # 可选参数,根据需要调整
)

# 下载并加载分词器,确保传递 trust_remote_code=True 以支持自定义代码
print("正在下载分词器...")
tokenizer = AutoTokenizer.from_pretrained(
    model_name,
    trust_remote_code=True
)

# 下载并加载模型,确保传递 trust_remote_code=True 以支持自定义代码
print("正在下载模型...")
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    quantization_config=bnb_config,
    device_map="auto",
    trust_remote_code=True  # 如果模型使用了自定义代码
)

# 显式保存模型和分词器到本地路径
print("正在保存模型和分词器到本地路径...")
model.save_pretrained(local_model_path)
tokenizer.save_pretrained(local_model_path)

print(f"模型和分词器已成功保存到 {local_model_path}")

将上述脚本保存为 download_and_save_model.py,然后在终端中运行:

预期输出应包含:

  • config.json:模型配置文件。
  • pytorch_model.bin 或 model.safetensors:模型权重文件。
  • 分词器相关文件,如 tokenizer.json、vocab.txt、merges.txt 等。
  • 如果所有这些文件都存在,您可以继续加载模型和分词器。

注意

  • device_map="auto" 会自动将模型分配到可用的 GPU 上。如果只有 CPU 可用,可以设置为 device_map=None 并使用 torch_dtype=torch.float32
  • load_in_8bit=True 需要安装 bitsandbytes 库,可以通过 pip install bitsandbytes 安装。如果不支持,可以去掉此参数,但会占用更多显存。

手动下载(可选)

如果你希望手动下载模型文件,可以使用 huggingface_hub

from huggingface_hub import hf_hub_download

model_name = "FlagAlpha/Llama2-Chinese-7b-Chat"
local_model_path = "./models/Llama2-Chinese-7b-Chat"

# 下载模型文件
model_files = hf_hub_download(repo_id=model_name, repo_type="model", local_dir=local_model_path, allow_patterns=["*.bin", "*.json"])

# 下载分词器文件
tokenizer_files = hf_hub_download(repo_id=model_name, repo_type="model", local_dir=local_model_path, allow_patterns=["*.json", "*.tokenizer.json", "*.vocab"])

4. 从本地加载模型

一旦模型和分词器下载到本地目录,可以通过指定本地路径来加载它们:

from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig, GenerationConfig
import torch

# 定义本地模型路径
MODEL_PATH = "./models/Llama2-Chinese-7b-Chat"

# 配置 BitsAndBytesConfig
bnb_config = BitsAndBytesConfig(
    load_in_8bit=True,  # 启用 8-bit 量化
    llm_int8_threshold=6.0,
    llm_int8_has_fp16_weight=False
)

# 从本地路径加载分词器
print("正在加载分词器...")
tokenizer = AutoTokenizer.from_pretrained(
    MODEL_PATH,
    trust_remote_code=True,
    local_files_only=True  # 强制仅从本地加载
)
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "left"

# 从本地路径加载模型
print("正在加载模型...")
model = AutoModelForCausalLM.from_pretrained(
    MODEL_PATH,
    device_map="auto",
    quantization_config=bnb_config,
    trust_remote_code=True,  # 如果模型使用了自定义代码
    local_files_only=True  # 强制仅从本地加载
)

# 配置生成参数
generation_config = GenerationConfig(
    do_sample=True,    # 启用采样
    temperature=0.9,
    top_p=0.6,
    max_new_tokens=50  # 根据需要调整
)

# 示例文本生成
prompt = "你好,Llama2!"
inputs = tokenizer(prompt, return_tensors="pt").to("cuda")

# 生成文本
with torch.no_grad():
    outputs = model.generate(**inputs, generation_config=generation_config)

# 解码并打印生成的文本
print(tokenizer.decode(outputs[0], skip_special_tokens=True))

5. 准备训练数据

使用 datasets 库加载和准备你的训练数据。例如,假设你有一个自定义数据集:

from datasets import load_dataset

# 加载自定义数据集
# 这里假设你有一个名为 "my_dataset" 的数据集
dataset = load_dataset("path_to_your_dataset")

# 预处理数据(例如,分词)
def tokenize_function(examples):
    return tokenizer(examples["text"], padding="max_length", truncation=True)

tokenized_datasets = dataset.map(tokenize_function, batched=True)

注意:确保你的数据集格式与模型输入要求一致。

6. 配置训练参数

使用 transformersTrainingArgumentsTrainer 进行训练。以下是一个示例:

from transformers import Trainer, TrainingArguments

training_args = TrainingArguments(
    output_dir="./results",                    # 输出目录
    per_device_train_batch_size=2,             # 训练批次大小
    per_device_eval_batch_size=2,              # 验证批次大小
    num_train_epochs=3,                        # 训练轮数
    save_steps=10_000,                         # 每 10,000 步保存一次模型
    save_total_limit=2,                        # 最多保存 2 个检查点
    fp16=True,                                 # 使用半精度训练
    logging_steps=500,                         # 日志记录间隔
    evaluation_strategy="steps",               # 评估策略
    eval_steps=1_000,                          # 评估间隔
    load_best_model_at_end=True,               # 在训练结束时加载最佳模型
    metric_for_best_model="accuracy",          # 评估指标
)

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_datasets["train"],
    eval_dataset=tokenized_datasets["validation"],
)

注意

  • 根据你的硬件资源调整 per_device_train_batch_sizeper_device_eval_batch_size
  • 确保你的数据集包含 trainvalidation 分支,或者根据需要调整。

7. 开始训练

运行以下命令启动训练:

trainer.train()

8. 保存训练后的模型

训练完成后,可以将模型和分词器保存到指定目录:

trainer.save_model("./trained_model")
tokenizer.save_pretrained("./trained_model")

完整示例代码

以下是一个完整的 Python 脚本,整合了上述步骤:

from transformers import AutoModelForCausalLM, AutoTokenizer, Trainer, TrainingArguments
from datasets import load_dataset
import torch

# 定义模型名称和本地路径
model_name = "FlagAlpha/Llama2-Chinese-7b-Chat"
local_model_path = "./models/Llama2-Chinese-7b-Chat"

# 下载并缓存模型和分词器
tokenizer = AutoTokenizer.from_pretrained(model_name, cache_dir=local_model_path)
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    cache_dir=local_model_path,
    device_map="auto",
    load_in_8bit=True  # 如果显存不足,可以启用 8-bit 精度
)

# 如果已经下载到本地,使用本地路径加载
# tokenizer = AutoTokenizer.from_pretrained(local_model_path)
# model = AutoModelForCausalLM.from_pretrained(
#     local_model_path,
#     device_map="auto",
#     load_in_8bit=True
# )

# 加载训练数据
dataset = load_dataset("path_to_your_dataset")

# 定义预处理函数
def tokenize_function(examples):
    return tokenizer(examples["text"], padding="max_length", truncation=True)

# 预处理数据
tokenized_datasets = dataset.map(tokenize_function, batched=True)

# 定义训练参数
training_args = TrainingArguments(
    output_dir="./results",
    per_device_train_batch_size=2,
    per_device_eval_batch_size=2,
    num_train_epochs=3,
    save_steps=10_000,
    save_total_limit=2,
    fp16=True,
    logging_steps=500,
    evaluation_strategy="steps",
    eval_steps=1_000,
    load_best_model_at_end=True,
    metric_for_best_model="accuracy",
)

# 初始化 Trainer
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_datasets["train"],
    eval_dataset=tokenized_datasets["validation"],
)

# 开始训练
trainer.train()

# 保存模型
trainer.save_model("./trained_model")
tokenizer.save_pretrained("./trained_model")

9. 进一步优化和注意事项

使用 accelerate 优化训练

accelerate 可以帮助你更高效地利用多 GPU 或分布式训练资源。确保在开始训练前配置 accelerate

accelerate config

按照提示选择适合你的硬件设置。然后,在训练脚本中使用 accelerate launch 来启动训练:

accelerate launch train_script.py

管理显存

如果在训练过程中遇到显存不足的问题,可以尝试以下方法:

  • 减小 per_device_train_batch_size
  • 使用梯度累积(gradient_accumulation_steps)。
  • 启用 8-bit 精度(load_in_8bit=True)。
  • 使用混合精度训练(fp16=True)。

监控训练过程

使用 TensorBoard 或其他监控工具来跟踪训练过程中的损失、准确率等指标:

pip install tensorboard
tensorboard --logdir=./results

然后在浏览器中访问 http://localhost:6006 查看训练日志。

保存和加载最佳模型

通过 Trainerload_best_model_at_end=True 参数,可以在训练结束时自动加载表现最好的模型。如果需要手动保存和加载模型,可以使用以下代码:

# 保存最佳模型
trainer.save_model("./best_model")
tokenizer.save_pretrained("./best_model")

# 从最佳模型加载
best_model = AutoModelForCausalLM.from_pretrained("./best_model")
best_tokenizer = AutoTokenizer.from_pretrained("./best_model")

总结

通过以上步骤,你可以将 Hugging Face 上的 FlagAlpha/Llama2-Chinese-7b-Chat 模型下载到本地,并使用 transformersTrainer 进行训练。请确保你的硬件资源充足,并根据实际需求调整训练参数和配置。如果在操作过程中遇到问题,可以参考 Hugging Face 的官方文档或在社区中寻求帮助。

二、通过lora 来减少参数,优化资源不足的问题

在上边的示例中,通过lora 来减少参数,优化资源不足的问题,请改进上边的训练方法。

好的,使用 LoRA(Low-Rank Adaptation)可以显著减少训练过程中需要调整的参数数量,从而优化资源不足的问题。以下是在之前示例的基础上,集成 LoRA 的改进方法。

1. 环境准备

安装必要的软件包

除了之前提到的包外,还需要安装 peft(Parameter-Efficient Fine-Tuning)库,它支持 LoRA 等参数高效微调方法。

pip install transformers accelerate datasets huggingface_hub peft

注意:确保 peft 版本兼容 transformers。如果遇到版本冲突,可以参考 PEFT 的官方文档 进行调整。

2. 下载并加载模型

与之前步骤类似,但在加载模型后,我们将应用 LoRA 到模型中。

from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import get_peft_config, get_peft_model, LoraConfig, TaskType

# 定义模型名称和本地路径
model_name = "FlagAlpha/Llama2-Chinese-7b-Chat"
local_model_path = "./models/Llama2-Chinese-7b-Chat"

# 加载分词器
tokenizer = AutoTokenizer.from_pretrained(local_model_path)

# 加载模型
model = AutoModelForCausalLM.from_pretrained(
    local_model_path,
    device_map="auto",
    load_in_8bit=True  # 使用 8-bit 精度,减少显存占用
)

# 配置 LoRA
lora_config = LoraConfig(
    r=8,  # 低秩分解的秩
    lora_alpha=32,  # LoRA 的缩放系数
    target_modules=["q_proj", "v_proj"],  # 要应用 LoRA 的模块名称,根据模型架构调整
    lora_dropout=0.1,
    bias="none",
    task_type=TaskType.CAUSAL_LM
)

# 应用 LoRA 到模型
model = get_peft_model(model, lora_config)

# 打印 LoRA 模型信息
print(model)

说明

  • target_modules:指定哪些模块应用 LoRA。对于 LLaMA 模型,通常选择查询(q_proj)和值(v_proj)投影层。请根据具体模型架构调整。
  • rlora_alpha:这些参数控制 LoRA 的低秩分解维度和缩放系数,可以根据资源情况进行调整。

3. 准备训练数据

与之前相同,使用 datasets 库加载和预处理训练数据。

from datasets import load_dataset

# 加载自定义数据集
dataset = load_dataset("path_to_your_dataset")

# 定义预处理函数
def tokenize_function(examples):
    return tokenizer(examples["text"], padding="max_length", truncation=True, max_length=512)

# 预处理数据
tokenized_datasets = dataset.map(tokenize_function, batched=True)

注意:根据你的数据集结构,调整 examples["text"] 部分。

4. 配置训练参数

使用 transformersTrainingArgumentsTrainer 进行训练,同时配置 peft 相关参数。

from transformers import Trainer, TrainingArguments
from peft import PeftModel

training_args = TrainingArguments(
    output_dir="./results",
    per_device_train_batch_size=2,
    per_device_eval_batch_size=2,
    num_train_epochs=3,
    save_steps=10_000,
    save_total_limit=2,
    fp16=True,
    logging_steps=500,
    evaluation_strategy="steps",
    eval_steps=1_000,
    load_best_model_at_end=True,
    metric_for_best_model="accuracy",
    optim="adamw_torch",  # 使用 AdamW 优化器
    lr_scheduler_type="linear",
    learning_rate=5e-5,  # 根据需要调整学习率
)

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_datasets["train"],
    eval_dataset=tokenized_datasets["validation"],
    tokenizer=tokenizer,
)

说明

  • 优化器和学习率:根据 LoRA 的特性,通常需要较小的学习率,如 5e-5。你可以根据训练效果调整。
  • 梯度累积:如果显存仍然不足,可以通过设置 gradient_accumulation_steps 来累积梯度,例如 gradient_accumulation_steps=4

5. 开始训练

运行训练过程。

trainer.train()

6. 保存训练后的模型

训练完成后,保存包含 LoRA 权重的模型和分词器。

# 保存 LoRA 模型
model.save_pretrained("./trained_model")

# 保存分词器
tokenizer.save_pretrained("./trained_model")

7. 使用训练后的模型

加载训练后的 LoRA 模型进行推理时,需要使用 peft 来加载 LoRA 权重。

from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel

# 加载分词器
tokenizer = AutoTokenizer.from_pretrained("./trained_model")

# 加载基础模型
base_model = AutoModelForCausalLM.from_pretrained(
    "FlagAlpha/Llama2-Chinese-7b-Chat",
    device_map="auto",
    load_in_8bit=True
)

# 加载 LoRA 权重
model = PeftModel.from_pretrained(base_model, "./trained_model")

# 进行推理
prompt = "你好,Llama2!"
inputs = tokenizer(prompt, return_tensors="pt").to("cuda")
outputs = model.generate(**inputs, max_new_tokens=50)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))

8. 完整示例代码

以下是整合 LoRA 的完整 Python 脚本:

from transformers import AutoModelForCausalLM, AutoTokenizer, Trainer, TrainingArguments
from transformers import BitsAndBytesConfig
from datasets import load_dataset
from peft import get_peft_model, LoraConfig, TaskType
import os

# 定义模型名称和本地路径
model_name = "FlagAlpha/Llama2-Chinese-7b-Chat"
local_model_path = "./models/Llama2-Chinese-7b-Chat"

# 创建本地存储目录(如果不存在)
os.makedirs(local_model_path, exist_ok=True)

# 配置 BitsAndBytesConfig
bnb_config = BitsAndBytesConfig(
    load_in_8bit=True,  # 启用 8-bit 量化
    llm_int8_threshold=6.0,
    llm_int8_has_fp16_weight=False
)

# 下载并加载分词器,确保传递 trust_remote_code=True
print("正在下载分词器...")
tokenizer = AutoTokenizer.from_pretrained(
    model_name,
    trust_remote_code=True
)

# 下载并加载模型,确保传递 trust_remote_code=True
print("正在下载模型...")
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    quantization_config=bnb_config,
    device_map="auto",
    trust_remote_code=True
)

# 显式保存模型和分词器到本地路径
print("正在保存模型和分词器到本地路径...")
model.save_pretrained(local_model_path)
tokenizer.save_pretrained(local_model_path)

print(f"模型和分词器已成功保存到 {local_model_path}")

# 从本地路径加载分词器
print("正在从本地路径加载分词器...")
tokenizer = AutoTokenizer.from_pretrained(
    local_model_path,
    trust_remote_code=True,
    local_files_only=True  # 强制仅从本地加载
)
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "left"

# 从本地路径加载模型
print("正在从本地路径加载模型...")
model = AutoModelForCausalLM.from_pretrained(
    local_model_path,
    device_map="auto",
    quantization_config=bnb_config,
    trust_remote_code=True,
    local_files_only=True
)

# 配置 LoRA
print("正在配置 LoRA...")
lora_config = LoraConfig(
    r=8,
    lora_alpha=32,
    target_modules=["q_proj", "v_proj"],  # 根据模型架构调整
    lora_dropout=0.1,
    bias="none",
    task_type=TaskType.CAUSAL_LM
)

# 应用 LoRA 到模型
model = get_peft_model(model, lora_config)

# 加载训练数据(替换为您的数据集路径)
print("正在加载训练数据...")
dataset = load_dataset("path_to_your_dataset")

# 定义预处理函数
def tokenize_function(examples):
    return tokenizer(examples["text"], padding="max_length", truncation=True, max_length=512)

# 预处理数据
print("正在预处理数据...")
tokenized_datasets = dataset.map(tokenize_function, batched=True)

# 定义训练参数
training_args = TrainingArguments(
    output_dir="./results",
    per_device_train_batch_size=2,
    per_device_eval_batch_size=2,
    num_train_epochs=3,
    save_steps=10_000,
    save_total_limit=2,
    fp16=True,
    logging_steps=500,
    evaluation_strategy="steps",
    eval_steps=1_000,
    load_best_model_at_end=True,
    metric_for_best_model="accuracy",
    optim="adamw_torch",
    lr_scheduler_type="linear",
    learning_rate=5e-5,
    gradient_accumulation_steps=4  # 根据需要调整
)

# 初始化 Trainer
print("正在初始化 Trainer...")
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_datasets["train"],
    eval_dataset=tokenized_datasets["validation"],
    tokenizer=tokenizer,
)

# 开始训练
print("开始训练...")
trainer.train()

# 保存 LoRA 模型和分词器
print("正在保存 LoRA 模型和分词器...")
model.save_pretrained("./trained_model")
tokenizer.save_pretrained("./trained_model")

print("模型微调和保存完成。")

将上述代码保存为 fine_tune_with_lora.py,然后在终端中运行:

9. 进一步优化和注意事项

使用 accelerate 优化训练

accelerate 可以帮助更高效地利用多 GPU 或分布式训练资源。

accelerate config

按照提示选择适合你的硬件设置。然后,使用 accelerate launch 启动训练:

accelerate launch train_script.py

管理显存

如果在训练过程中仍然遇到显存不足的问题,可以尝试以下方法:

  • 减小 per_device_train_batch_size:例如,从 2 调整为 1
  • 增加 gradient_accumulation_steps:例如,设置为 4,以在多个小批次上累积梯度。
  • 调整 LoRA 参数:减少 r 的值,例如从 8 调整为 4,以进一步减少参数数量。
  • 使用更低的 max_length:如果你的输入序列较长,可以尝试减小 max_length

监控训练过程

使用 TensorBoard 或其他监控工具来跟踪训练过程中的损失、准确率等指标:

pip install tensorboard
tensorboard --logdir=./results

然后在浏览器中访问 http://localhost:6006 查看训练日志。

保存和加载最佳模型

通过 Trainerload_best_model_at_end=True 参数,可以在训练结束时自动加载表现最好的模型。如果需要手动保存和加载模型,可以使用以下代码:

# 保存最佳模型
trainer.save_model("./best_model")
tokenizer.save_pretrained("./best_model")

# 从最佳模型加载
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel

# 加载分词器
tokenizer = AutoTokenizer.from_pretrained("./best_model")

# 加载基础模型
base_model = AutoModelForCausalLM.from_pretrained(
    "FlagAlpha/Llama2-Chinese-7b-Chat",
    device_map="auto",
    load_in_8bit=True
)

# 加载 LoRA 权重
model = PeftModel.from_pretrained(base_model, "./best_model")

10. 参考资源

通过以上步骤,你可以有效地使用 LoRA 进行参数高效的微调,减少显存和计算资源的消耗。如果在操作过程中遇到问题,可以参考相关文档或在社区中寻求帮助。

为者常成,行者常至