百川大模型微调指令详解
AI大模型learner 2024-09-09 16:31:04 阅读 77
下载百川大模型的开源项目,https://github.com/baichuan-inc/Baichuan2,根据fine-tune目录下README.md获取微调指令:
deepspeed --hostfile=$hostfile fine-tune.py \
--report_to "none" \
--data_path "data/belle_chat_ramdon_10k.json" \
--model_name_or_path "baichuan-inc/Baichuan2-7B-Chat" \
--output_dir "output" \
--model_max_length 512 \
--num_train_epochs 4 \
--per_device_train_batch_size 16 \
--gradient_accumulation_steps 1 \
--save_strategy epoch \
--learning_rate 2e-5 \
--lr_scheduler_type constant \
--adam_beta1 0.9 \
--adam_beta2 0.98 \
--adam_epsilon 1e-8 \
--max_grad_norm 1.0 \
--weight_decay 1e-4 \
--warmup_ratio 0.0 \
--logging_steps 1 \
--gradient_checkpointing True \
--deepspeed ds_config.json \
--bf16 True \
--tf32 True \
--use_lora True
微调指令参数的含义
deepspeed --hostfile=$hostfile fine-tune.py:
deepspeed --hostfile=$hostfile fine-tune.py
使用 DeepSpeed 启动分布式训练,–hostfile 参数指定主机文件,fine-tune.py 是要运行的微调脚本。
–report_to “none”:
--report_to "none"
禁用训练过程中的报告功能,通常用于不向外部服务(如 WandB)报告训练进展。
–data_path “./baichuan_formatted_data_copy.json”:
--data_path "./baichuan_formatted_data_copy.json"
指定用于训练的数据集路径。
–model_name_or_path “./Baichuan2-7B-Chat”
--model_name_or_path "./Baichuan2-7B-Chat"
指定预训练模型的路径或名称。
–output_dir “output”:
--output_dir "output"
指定保存微调后模型的输出目录。
–model_max_length 512:
–model_max_length 512 是一个参数,用于设置模型输入序列的最大长度为 512。以下是详细解释:
解释 --model_max_length 512
参数名称:–model_max_length
参数值:512
含义和作用
输入序列长度:
此参数指定了模型在处理输入数据时的最大序列长度。在这个例子中,最大长度被设置为 512 个标记(tokens)。
输入截断或填充:
如果输入文本序列的长度超过 512 个标记,模型会截断输入序列,使其长度不超过 512 个标记。
如果输入文本序列的长度少于 512 个标记,模型会填充序列,使其长度达到 512 个标记。这通常通过添加特殊的填充标记(如 [PAD])来实现。
计算资源和性能:
设置合理的最大序列长度可以优化计算资源的使用。例如,较长的序列会消耗更多的内存和计算时间,而过短的序列可能无法捕捉足够的上下文信息。
在处理固定长度的输入序列时,模型的计算效率通常更高,因为批处理操作可以更容易地进行。
代码示例
以下是一个示例代码,展示如何使用 --model_max_length 参数:
from transformers import AutoTokenizer, AutoModelForCausalLM
# 加载预训练模型和tokenizer
model_name = "gpt2"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name)
# 定义最大序列长度
model_max_length = 512
# 准备输入数据
input_text = "这是一个测试输入,用于演示如何使用最大序列长度。"
# 将输入文本转换为模型输入的张量格式,并指定最大序列长度
inputs = tokenizer(input_text, return_tensors="pt", max_length=model_max_length, truncation=True, padding='max_length')code>
# 查看输入数据的形状
print(inputs['input_ids'].shape) # 输出: torch.Size([1, 512])
# 使用模型进行推理
outputs = model(**inputs)
print(outputs.logits)**加粗样式**
–num_train_epochs 4
–num_train_epochs 4 是一个参数,用于设置模型训练的轮数为 4。以下是详细解释:
解释 --num_train_epochs 4
参数名称:–num_train_epochs
参数值:4
含义和作用
训练轮数:
这个参数指定了模型在整个训练数据集上进行训练的次数。在这个例子中,模型将对训练数据集进行 4 轮完整的训练。
训练过程:
每个训练轮(epoch)都包括一次完整的前向传递(forward pass)和后向传递(backward pass),并进行参数更新。
在每轮训练中,模型会依次处理训练数据集中的每个样本,通过优化器更新模型参数以最小化损失函数。
模型性能:
训练轮数的选择影响模型的收敛和性能。过少的轮数可能导致模型未充分训练,而过多的轮数可能导致过拟合。
通常会通过验证集(validation set)监控训练过程,选择合适的训练轮数。
代码示例
以下是一个示例代码,展示如何使用 --num_train_epochs 参数:
from transformers import Trainer, TrainingArguments, AutoModelForCausalLM, AutoTokenizer
# 加载预训练模型和tokenizer
model_name = "gpt2"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name)
# 准备训练数据集(示例数据集)
train_dataset = [{ "input_text": "示例输入文本"}]
# 将输入文本转换为模型输入的张量格式
def preprocess_function(examples):
return tokenizer(examples["input_text"], truncation=True, padding='max_length', max_length=512)code>
train_dataset = [preprocess_function(example) for example in train_dataset]
# 定义训练参数
training_args = TrainingArguments(
output_dir="./results",code>
num_train_epochs=4,
per_device_train_batch_size=2,
save_steps=10,
save_total_limit=2,
)
# 创建Trainer对象
trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_dataset,
)
# 开始训练
trainer.train()
–per_device_train_batch_size 16
per_device_train_batch_size 是在使用 PyTorch 和 Hugging Face Transformers 库进行模型训练时常用的一个参数。它指定了每个设备(例如 GPU 或 TPU)上的训练批次大小。下面详细解释这个参数的含义及其作用:
作用
定义批次大小:per_device_train_batch_size 指定了每个训练设备上处理的样本数。在分布式训练中,如果你有多个设备(比如多张 GPU),这个参数定义了每张设备上处理的样本数,而不是所有设备上的总批次大小。
影响训练效率:批次大小影响到模型训练的效率和效果。较大的批次大小可以提高计算效率,但需要更多的显存(GPU 内存)来存储每个批次的数据。较小的批次大小则可以节省显存,但可能需要更多的训练时间。
示例
假设你使用的是 Hugging Face 的 Trainer 类进行训练,以下是如何使用 per_device_train_batch_size 参数:
from transformers import Trainer, TrainingArguments
training_args = TrainingArguments(
per_device_train_batch_size=16, # 每个设备上的批次大小为 16
num_train_epochs=3, # 训练轮数
logging_dir='./logs', # 日志目录code>
logging_steps=10, # 日志记录步数
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_dataset
)
参数详细解释
per_device_train_batch_size:这是一个整数值,表示每个训练设备(如 GPU)上使用的批次大小。例如,per_device_train_batch_size=16 表示每个 GPU 上的批次大小为 16。如果你有 4 张 GPU,那么每次前向传播和反向传播将处理 16 * 4 = 64 个样本。
计算总批次大小
总批次大小:如果你有多个设备并且设置了 per_device_train_batch_size,总批次大小是每个设备上的批次大小乘以设备的数量。例如,如果你有 2 张 GPU,每张 GPU 的批次大小是 32,那么总批次大小是 32 * 2 = 64。
如何选择批次大小
显存限制:根据你的硬件配置(特别是显存),选择适合的批次大小。如果显存不足,可以尝试减小批次大小。
训练稳定性:较大的批次大小有时可以使训练过程更加稳定,但需要注意避免过大的批次大小导致显存溢出。
性能优化:选择一个合适的批次大小来平衡计算效率和显存使用。可以通过实验找到最佳值。
总结
per_device_train_batch_size 是一个控制每个训练设备上数据批次大小的重要参数。它影响训练过程的效率、显存使用和模型性能。在实际使用中,你可能需要根据硬件配置和训练需求来调整这个参数,以获得最佳的训练效果。
–gradient_accumulation_steps 1
–gradient_accumulation_steps 是一个用于控制梯度累积的训练参数。梯度累积是深度学习训练中的一种技术,特别在处理大批次数据时,可以有效地减少显存消耗并提高训练效率。
什么是梯度累积(Gradient Accumulation)?
梯度累积是指在多个小批次(mini-batches)的梯度计算中,累积这些梯度,然后在一定步骤后再进行一次参数更新。这允许你在使用较小的批次大小的同时,相当于使用更大的批次进行训练,从而在硬件资源受限的情况下获得更大的批次效果。
–gradient_accumulation_steps 的作用
定义:–gradient_accumulation_steps 设定了在更新模型参数之前,累积的梯度批次数。即,在执行梯度更新之前,你需要处理的批次数量。
示例:–gradient_accumulation_steps 1 表示每处理一个批次后,就进行一次梯度更新。在这种情况下,梯度累积是等同于批次大小的效果。
梯度累积的工作原理
前向传播:对一个批次的数据进行前向传播,计算损失。
反向传播:计算梯度但不进行更新。
梯度累积:将当前批次的梯度累积到之前的梯度中。
重复步骤 1-3:重复处理多个批次的数据,累积梯度。
参数更新:当累计的步骤数达到 --gradient_accumulation_steps 设定的值时,进行一次参数更新,并将梯度清零。使用 --gradient_accumulation_steps 的效果
显存消耗:允许使用较小的批次大小,减小显存消耗,同时能够模拟更大的批次。较大的梯度累积步数可以使得显存消耗与实际批次大小不成正比。
训练稳定性:通过梯度累积,可以提高训练过程中的稳定性,因为更新参数的频率减少,计算的梯度更新的平均效果更稳定。
训练效率:可以减少参数更新的频率,使得训练过程中的计算和优化步骤更为高效。实际例子
假设你有以下设置:
批次大小(per_device_train_batch_size):8
梯度累积步骤(gradient_accumulation_steps):4
在这种情况下:
每个批次包含 8 个样本。
梯度将会累积 4 个批次的梯度,总共处理 8 * 4 = 32 个样本。
每处理 4 个批次(32 个样本),才会进行一次参数更新。
这样设置可以让你使用较小的批次大小,而实际进行的梯度更新效果相当于使用了更大的批次。
总结
–gradient_accumulation_steps 是一个重要的参数,用于控制梯度累积的步数。通过设置该参数,可以有效地模拟更大的批次大小,减少显存使用,并在硬件资源受限的情况下提高训练效率。–gradient_accumulation_steps 的值需要根据具体的训练需求和硬件资源进行调整,以获得最佳的训练效果。
–save_strategy epoch
–save_strategy epoch 是一个用于控制模型保存策略的训练参数。它决定了在训练过程中何时保存模型检查点。具体解释如下:
模型保存策略的概念
在深度学习模型的训练过程中,定期保存模型检查点(checkpoint)是一个常见的做法。这不仅可以防止训练过程中出现意外中断(如硬件故障、进程崩溃等)导致训练进度丢失,还允许你在训练结束后回溯到之前保存的模型状态,以便进行验证或继续训练。
–save_strategy 参数的作用
定义:–save_strategy 参数用于指定模型保存检查点的策略。
可选值:这个参数通常有几种可选值,比如 no, epoch, steps 等。
–save_strategy epoch 的具体含义
epoch:选择 epoch 表示在每个训练轮次(epoch)结束时保存模型检查点。
优点:这种策略简单且直观,每轮次结束后模型都会被保存一次,非常适合较短的训练过程或每轮次的训练时间较短的情况。
其他可能的保存策略
no:表示不保存任何模型检查点。
steps:表示在每经过一定数量的训练步骤(steps)后保存模型检查点,通常还需要指定 --save_steps 参数来设置保存间隔。
实际例子
假设你的训练参数设置如下:
--num_train_epochs 4
--per_device_train_batch_size 16
--save_strategy epoch
在这种设置下,模型将会在每个训练轮次结束时保存一次。如果你有 4 个训练轮次,模型会在第 1、2、3 和 4 轮次结束时各保存一个检查点,总共保存 4 次。
代码中的体现
在 transformers 库的 Trainer 类中,–save_strategy 参数会被用来控制 Trainer 的保存行为。例如:
training_args = TrainingArguments(
output_dir="./results",code>
num_train_epochs=4,
per_device_train_batch_size=16,
save_strategy="epoch",code>
# 其他参数
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
# 其他参数
)
trainer.train()
总结
–save_strategy epoch 是一个用于控制模型保存策略的参数,表示在每个训练轮次结束时保存模型检查点。这种策略非常适合每轮次训练时间较短或希望在每轮次结束后保存模型的情况。选择合适的保存策略有助于更好地管理训练过程中的模型版本和恢复训练。
–learning_rate 2e-5
–learning_rate 2e-5 是用于设置模型训练过程中学习率(learning rate)的参数。学习率是影响训练过程和模型性能的重要超参数之一。
学习率(Learning Rate)的概念
学习率控制了模型在每次参数更新时的步伐大小。在梯度下降算法中,学习率决定了参数调整的幅度。学习率的值直接影响训练的速度和稳定性。
较高的学习率:可能导致训练过程中的震荡或发散,因为参数更新步伐太大,可能越过最优点。
较低的学习率:可能导致训练过程非常缓慢,甚至陷入局部最优。
2. --learning_rate 参数的作用
定义:–learning_rate 参数用于设置训练过程中使用的初始学习率。
格式:通常以浮点数表示,例如 2e-5 相当于 0.00002。
3. 2e-5 的具体含义
数值:2e-5 表示科学记数法中的 2 × 10^-5,即 0.00002。
应用:这个值在大多数情况下是一个较小的学习率,适用于大型预训练模型的微调过程,以保证训练的稳定性和逐步优化。
4. 学习率的选择和调优
选择合适的学习率对于模型训练的成功至关重要。通常情况下,可以通过以下方式选择和调优学习率:
经验值:使用已有研究和文献中的推荐值。例如,对于BERT和GPT等预训练模型的微调,2e-5 是一个常见的选择。
学习率调度(Scheduler):使用学习率调度器动态调整学习率,例如线性下降、余弦退火等。
实验验证:通过实验来验证和调整学习率,选择能够在验证集上表现最好的学习率。
5. 代码示例
在使用 transformers 库进行模型训练时,可以在 TrainingArguments 中指定学习率:
from transformers import TrainingArguments, Trainer
training_args = TrainingArguments(
output_dir="./results",code>
num_train_epochs=4,
per_device_train_batch_size=16,
learning_rate=2e-5, # 设置学习率为2e-5
# 其他参数
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
# 其他参数
)
trainer.train()
总结
–learning_rate 2e-5 参数用于设置模型训练的初始学习率,值为 0.00002。学习率是一个关键的超参数,直接影响模型训练的速度和效果。选择合适的学习率需要结合经验和实验结果,并可以通过学习率调度器动态调整。
–lr_scheduler_type constant
lr_scheduler_type constant 是指定学习率调度器类型的参数,表示在训练过程中使用恒定的学习率(constant learning rate)。学习率调度器(learning rate scheduler)是调整训练过程中学习率的重要机制,可以帮助优化模型训练。
学习率调度器的作用
学习率调度器在训练过程中根据预设策略调整学习率,以提高模型训练的效果和效率。不同的学习率调度策略可以帮助模型在不同阶段获得更好的训练结果。
恒定学习率(Constant Learning Rate)
定义:恒定学习率指的是在整个训练过程中使用固定不变的学习率。换句话说,学习率在训练的每一步都保持相同,不进行任何变化。
用法:–lr_scheduler_type constant 说明在训练过程中不使用学习率的动态调整策略,而是始终保持初始设定的学习率。
适用场景
简单任务:对于一些简单或短时间的训练任务,恒定学习率可能足够,因为训练过程中的动态调整不一定带来显著的性能提升。
初始调试:在进行模型的初步调试时,使用恒定学习率可以简化设置,使开发者能够快速验证模型和数据处理的正确性。
训练稳定性:在某些情况下,尤其是使用具有较低学习率的深度学习模型,保持恒定的学习率可以帮助训练过程保持稳定。
示例代码
在使用 transformers 库进行训练时,可以在 TrainingArguments 中指定 lr_scheduler_type 为 constant,例如:
from transformers import TrainingArguments, Trainer
training_args = TrainingArguments(
output_dir="./results", # 保存模型和日志的目录code>
num_train_epochs=3, # 训练的轮次
per_device_train_batch_size=8, # 每个设备的训练批次大小
learning_rate=5e-5, # 初始学习率
lr_scheduler_type="constant", # 使用恒定学习率调度器code>
logging_dir="./logs", # 日志文件夹code>
logging_steps=100 # 每100步记录日志
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
)
trainer.train()
与其他学习率调度策略的对比
线性下降(Linear Decay):学习率从初始值线性下降到0。
余弦退火(Cosine Annealing):学习率根据余弦函数的曲线变化。
阶梯下降(Step Decay):每隔一定步数,学习率按预设的比例下降。优缺点
优点:
简单易用:设置和理解简单,适合初学者和简单任务。
稳定性:在某些情况下可以提供稳定的训练过程。
缺点:
灵活性差:无法适应训练过程中的动态变化,可能不适合所有任务。
潜在过拟合:可能无法在训练后期有效避免过拟合问题,因为没有调整学习率来适应不同阶段的需求。
总结
lr_scheduler_type constant 参数用于在训练过程中指定使用恒定的学习率。它适用于简单任务和初步调试场景,但在复杂任务和长期训练中,使用动态学习率调度策略通常能带来更好的性能和训练效果。
–adam_beta1 0.9
–adam_beta1 0.9 是指定 Adam 优化器的第一个动量参数(beta1)的值。Adam 是一种常用的优化算法,它结合了动量(Momentum)和自适应学习率(AdaGrad)的优点,用于优化深度学习模型的训练过程。
Adam 优化器简介
Adam(Adaptive Moment Estimation)优化器是一种流行的优化算法,具有以下特点:
自适应学习率:根据每个参数的梯度的历史平方和梯度的一阶矩来调整学习率。
动量:使用一阶矩(梯度的均值)来加速收敛,并减少梯度下降中的振荡。
Adam 优化器的主要参数
学习率(learning_rate):
控制每次参数更新的步长。常用的默认值是 1e-3,但可以根据具体任务进行调整。
beta1:
一阶矩估计的衰减率。通常设为 0.9。
作用:决定了历史梯度的影响程度。较高的 beta1 值表示历史梯度对当前梯度的影响较大。
beta2:
二阶矩估计的衰减率。通常设为 0.999。
作用:决定了历史梯度平方的影响程度。较高的 beta2 值表示历史梯度平方对当前梯度的影响较大。
epsilon:
防止除零错误的一个小常数。通常设为 1e-8。
weight_decay:
权重衰减(L2 正则化)系数,用于控制过拟合。通常设为 0 或一个小的正值。
参数解释
–adam_beta1 0.9:
这是 Adam 优化器中的一个参数,表示一阶矩估计的衰减率(动量)。设置为 0.9 是因为在许多应用中,这个值可以平衡历史梯度的影响和当前梯度的影响,有助于稳定训练过程。
使用示例
在 transformers 库中,你可以通过 TrainingArguments 来设置 Adam 优化器的参数。例如:
from transformers import TrainingArguments, Trainer
training_args = TrainingArguments(
output_dir="./results", # 保存模型和日志的目录code>
num_train_epochs=3, # 训练的轮次
per_device_train_batch_size=8, # 每个设备的训练批次大小
learning_rate=5e-5, # 初始学习率
adam_beta1=0.9, # 动量参数 beta1
adam_beta2=0.999, # 二阶矩估计参数 beta2
adam_epsilon=1e-8, # 防止除零错误的常数 epsilon
weight_decay=0.01, # 权重衰减(L2 正则化)系数
logging_dir="./logs", # 日志文件夹code>
logging_steps=100 # 每100步记录日志
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
)
trainer.train()
作用与效果
较高的 beta1(例如 0.9):
能够平滑梯度更新,使得优化过程更加稳定。
增加历史梯度的影响,有助于减小梯度的振荡。
较低的 beta1(例如 0.5):
历史梯度的影响较小,优化过程可能更敏感,训练过程可能会变得不稳定或收敛较慢。
总结
–adam_beta1 0.9 参数用于设置 Adam 优化器中的动量估计衰减率。这个参数影响梯度的更新方式,能够帮助优化过程稳定和加速收敛。通常情况下,默认值 0.9 在大多数任务中表现良好。
–adam_beta2 0.98
–adam_beta2 0.98 是用于设置 Adam 优化器中的第二个动量参数(beta2)的值。Adam 优化器是一种常用的深度学习优化算法,通过结合动量和自适应学习率来提升训练过程的效果和效率。
Adam 优化器参数简介
Adam(Adaptive Moment Estimation)优化器有三个主要的超参数:
学习率(learning_rate):控制每次参数更新的步长。
beta1:一阶矩估计的衰减率,控制历史梯度的影响程度。
beta2:二阶矩估计的衰减率,控制历史梯度平方的影响程度。
epsilon:防止除零错误的一个小常数。
参数解释
–adam_beta2 0.98:
这是 Adam 优化器中的一个超参数,用于设置二阶矩估计的衰减率。默认情况下,beta2 通常设为 0.999,但在你的设置中,它被设为 0.98。
作用:beta2 控制了梯度平方的历史影响程度。具体来说,它决定了过去梯度平方的加权平均值对当前梯度的影响。
beta2 的作用
较高的 beta2(接近 1):
表示二阶矩估计(即梯度的平方的加权平均)的衰减率较低,历史梯度平方对当前梯度的影响较大。
优点:能够更平滑地估计梯度的方差,减少梯度更新中的噪声,提升训练过程的稳定性。
缺点:如果设定得过高,可能导致更新缓慢,因为估计的历史梯度方差影响过大。
较低的 beta2(远离 1):
表示二阶矩估计的衰减率较高,历史梯度平方对当前梯度的影响较小。
优点:可能使得优化过程更灵活,能够更快地响应新的梯度信息。
缺点:可能导致梯度更新过程中更多的噪声和不稳定性。
使用示例
在 transformers 库中,你可以通过 TrainingArguments 来设置 Adam 优化器的参数。例如:
python
复制代码
from transformers import TrainingArguments, Trainer
training_args = TrainingArguments(
output_dir=“./results”, # 保存模型和日志的目录
num_train_epochs=3, # 训练的轮次
per_device_train_batch_size=8, # 每个设备的训练批次大小
learning_rate=5e-5, # 初始学习率
adam_beta1=0.9, # 动量参数 beta1
adam_beta2=0.98, # 二阶矩估计参数 beta2
adam_epsilon=1e-8, # 防止除零错误的常数 epsilon
weight_decay=0.01, # 权重衰减(L2 正则化)系数
logging_dir=“./logs”, # 日志文件夹
logging_steps=100 # 每100步记录日志
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
)
trainer.train()
总结
–adam_beta2 0.98 参数用于设置 Adam 优化器的二阶矩估计的衰减率。它控制了历史梯度平方对当前梯度更新的影响程度。设定 beta2 为 0.98 比默认的 0.999 稍低,可能会使得优化过程对历史信息的依赖程度降低,从而提高优化过程的灵活性,但也可能增加训练过程中的噪声。通常情况下,0.999 是比较常见的默认值,但根据具体的任务和实验,调整 beta2 可能会带来不同的效果。
历史梯度对现有梯度的影响
ChatGPT
在使用 Adam 或其他类似的优化算法(如 RMSprop、Adagrad)时,历史梯度对当前梯度的影响主要体现在如何计算梯度的动量(即梯度的移动平均)和梯度的平方的动量(即梯度平方的移动平均)。这些历史信息用于更新模型参数,进而影响优化过程的稳定性和效率。
Adam 优化器中的梯度影响
Adam 优化器结合了一阶矩(梯度的移动平均)和二阶矩(梯度平方的移动平均)来调整每个参数的学习率。
–adam_epsilon 1e-8
–adam_epsilon 1e-8 是在使用 Adam 或 AdamW 优化器时设置的一个参数。它控制了优化器中用于稳定数值计算的一个小常数。这个参数对于避免在计算中出现数值不稳定问题非常重要。
adam_epsilon 的作用
在 Adam 和 AdamW 优化器中,adam_epsilon 用于防止在计算梯度更新时发生除零错误或数值不稳定。具体来说,它在计算梯度的更新步骤中作为一个小常数加到分母中,以确保在计算过程中不会因为梯度平方的估计非常小而导致除零错误或数值不稳定。
–max_grad_norm 1.0
–max_grad_norm 1.0 是一个用于控制梯度裁剪的参数。它在训练过程中对梯度的大小进行限制,以防止梯度爆炸或梯度过大的情况,从而提高训练的稳定性。
梯度裁剪(Gradient Clipping)
梯度裁剪是一种技术,用于控制梯度的范数(即梯度的大小),以避免梯度爆炸(即梯度过大)问题。梯度爆炸可能导致模型参数更新过大,导致训练过程不稳定甚至发散。
max_grad_norm 的作用
max_grad_norm 参数指定了梯度裁剪的阈值。训练过程中,当梯度的范数超过这个阈值时,梯度将被裁剪,以确保它不会超过这个阈值。
–weight_decay 1e-4
–weight_decay 1e-4 是在训练深度学习模型时设置的一个参数,用于正则化以防止模型过拟合。这个参数与 权重衰减 相关,通常用于优化器中来改善模型的泛化能力。
权重衰减(Weight Decay)
权重衰减是一种正则化技术,通过在损失函数中添加一个关于模型参数的惩罚项来减少模型的复杂度。这可以防止模型在训练数据上过拟合,从而提高模型在未见数据上的泛化能力。
作用
权重衰减的主要作用是:
减少过拟合:通过对较大的权重施加惩罚,使得模型更加泛化。
促使模型参数更小:鼓励模型学习到较小的权重值,防止参数过大。
–warmup_ratio 0.0
–warmup_ratio 0.0 是在深度学习训练过程中设置的一个参数,用于调整学习率的预热(warm-up)策略。预热策略是优化器学习率调度中的一个重要部分,它有助于训练的稳定性,特别是在训练开始时。
学习率预热(Warm-up)
学习率预热是指在训练初期,学习率从一个较小的值逐渐增加到预设的学习率,这样可以使模型在训练的早期阶段以较小的步伐进行更新,从而提高训练的稳定性。预热阶段通常在训练的开始几轮中进行。
作用
稳定训练:在训练初期使用较小的学习率可以帮助模型在参数空间中找到更好的位置,减少梯度的剧烈波动,从而提高训练的稳定性。
避免梯度爆炸:预热可以防止在训练开始时,学习率过大导致的梯度爆炸。
改善收敛速度:逐渐增加学习率可以帮助模型更快地收敛到较好的解。
–warmup_ratio 0.0 的含义
–warmup_ratio 参数指定了学习率预热的比例。如果设置为 0.0,表示在训练过程中不会进行学习率预热。即训练开始时直接使用预设的学习率,而没有逐渐增加的过程。
在没有预热的情况下,训练开始时就会使用设置的学习率,这对于某些模型和任务可能是合适的,但对于其他任务来说,可能会导致训练不稳定或收敛较慢。
–logging_steps 1
–logging_steps 1 是深度学习训练中用于设置日志记录频率的一个参数。它指定了每隔多少步(即训练迭代次数)记录一次训练日志。
作用
这个参数主要用于控制训练过程中的日志记录频率,以便监控训练的进度、损失值、学习率等指标。通过记录这些信息,可以更好地理解模型的训练动态,进行调试,和进行性能评估。
详细解释
–logging_steps 参数定义了记录日志的频率。例如,设置为 1 意味着每进行一步训练就记录一次日志。如果将其设置为 100,则每完成 100 步训练后记录一次日志。
训练日志的内容
在每次记录日志时,通常会记录以下信息:
训练损失(Training Loss):当前步骤的训练损失值。
学习率(Learning Rate):当前的学习率。
时间(Time):训练所用的时间。
其他自定义指标(Custom Metrics):如准确率、F1 分数等。
–gradient_checkpointing True
–gradient_checkpointing True 是一个用于深度学习训练的参数,它用于启用“梯度检查点”技术(Gradient Checkpointing)。该技术主要用于优化内存使用,特别是在处理大型模型时,能够显著减少显存占用。
梯度检查点(Gradient Checkpointing)的作用
梯度检查点是一种技术,通过在前向传播过程中保存中间激活(即模型中间计算的中间结果)来减少内存的使用。具体来说,它的工作机制如下:
前向传播过程:
在传统的训练过程中,模型在前向传播时会计算并保存所有中间激活,用于后续的反向传播计算梯度。这些中间激活占用大量的显存。
梯度检查点:
使用梯度检查点技术时,模型不会保存所有中间激活,而是在必要时重新计算这些激活。具体做法是在前向传播过程中,模型只保存一部分检查点(即中间激活),并在需要计算梯度时,基于这些检查点重新计算丢失的激活。
这种方法会使得显存使用减少,因为不需要保存所有的中间激活。
反向传播:
在进行反向传播计算梯度时,模型会利用保存的检查点重新计算需要的中间激活,然后用这些激活来计算梯度。
作用与优点
减少显存占用:可以显著降低训练大模型时的显存占用,使得在有限的显存条件下能够训练更大的模型。
允许更大的模型:通过减少显存使用,可以训练更大的模型,或者使用更大的批次大小。
缺点
计算开销增加:由于需要在反向传播阶段重新计算部分中间激活,这会增加计算的时间开销。尽管减少了显存使用,但会增加训练时间。
实现复杂性:需要在模型中进行适当的实现和配置,可能会增加实现的复杂性。
–deepspeed ds_config.json
–deepspeed ds_config.json 是一个在训练深度学习模型时使用 DeepSpeed 优化框架的参数。这一参数允许你通过 DeepSpeed 加速和优化训练过程。具体来说,它的作用是指示训练脚本使用 DeepSpeed,并提供一个配置文件来定义 DeepSpeed 的设置。
DeepSpeed 介绍
DeepSpeed 是一个深度学习训练优化库,旨在通过高效的训练技术来提高训练速度和降低内存使用。它提供了多种优化功能,如:
分布式训练:在多个 GPU 或机器上并行训练模型。
混合精度训练:通过使用半精度浮点数(FP16)来减少内存使用并加速训练。
模型并行:将模型划分到多个设备上,处理更大的模型。
优化器和学习率调度器:改进的优化算法和学习率调度策略。
–deepspeed 参数
–deepspeed ds_config.json 参数的作用如下:
启用 DeepSpeed:通过指定 --deepspeed 参数,训练脚本会使用 DeepSpeed 框架来优化训练过程。
指定配置文件:ds_config.json 是一个 JSON 文件,用于定义 DeepSpeed 的配置设置。该文件包含各种优化参数和选项,DeepSpeed 将根据这些配置进行训练。
–bf16 True
–bf16 True 参数用于启用 Brain Floating Point Format (BF16),这是一种专门设计的浮点数格式,旨在提高深度学习训练中的性能和效率。下面是对 BF16 的详细解释及其在训练中的作用:
什么是 BF16?
BF16 (Brain Floating Point Format) 是一种 16 位浮点数格式,主要由 Google 和其他公司开发用于加速深度学习计算。它是对 IEEE 754 标准中的 32 位浮点数(即 FP32)的简化,具有以下特性:
16 位总长度:BF16 使用 16 位来表示浮点数,其中 1 位是符号位,8 位是指数位,7 位是尾数位(有效数字部分)。
与 FP32 兼容的指数范围:BF16 的指数部分与 FP32 相同,因此它具有与 FP32 相同的动态范围,但尾数部分的精度较低。
计算性能:BF16 能够在不显著降低数值精度的情况下,减少计算和内存需求,这对于深度学习模型训练非常有用。
BF16 的优势
提高计算效率:
由于 BF16 使用 16 位而不是 32 位,它可以显著减少计算所需的内存带宽和存储需求,从而加速训练过程。
BF16 运算可以利用专用的硬件支持,例如 Google 的 TPU 和一些现代 GPU 对 BF16 的优化支持。
减少内存使用:
减少每个浮点数的内存占用,有助于在显存有限的情况下训练更大的模型或使用更大的批次大小。
兼容性:
BF16 保留了 FP32 的指数范围,这意味着在处理大范围值时,BF16 能够提供类似的数值范围。
计算稳定性:
BF16 在计算稳定性上优于其他低精度格式(如 FP16),特别是在涉及到较大的数值范围时。
如何使用 BF16?
在训练脚本中使用 --bf16 True 参数来启用 BF16,通常配合支持 BF16 的硬件(例如某些 NVIDIA A100 GPU 或 Google TPU)。这个参数会使得训练过程中所有适用的浮点计算都使用 BF16 格式,从而提高训练效率。
–tf32 True
–tf32 True 参数用于启用 TensorFloat-32 (TF32) 精度格式。这是一种专门设计的浮点数格式,旨在提升深度学习训练中的性能,特别是在 NVIDIA 的 A100 GPU 上。下面是 TF32 的详细解释及其在训练中的作用:
什么是 TF32?
TensorFloat-32 (TF32) 是 NVIDIA 在其 A100 GPU 中引入的一种浮点数格式。它结合了 FP32 和 FP16 的优点,旨在加速训练过程,同时保留足够的数值精度。TF32 的特点如下:
数值表示:
TF32 使用 32 位来表示浮点数,其中 8 位是指数位,10 位是尾数位(有效数字部分),其余 14 位用于隐藏位和符号。
TF32 在指数部分和 FP32 相同,这使得它具有 FP32 的动态范围,但在尾数部分采用较低的精度(10 位),以减小内存和计算带宽的需求。
计算性能:
TF32 设计用于在处理深度学习模型时提供更高的计算效率。它能够在加速计算的同时保持足够的精度,特别是在训练深度学习模型时。
硬件支持:
TF32 主要在 NVIDIA 的 A100 GPU 上得到优化支持,这些 GPU 能够以更高的速度执行 TF32 运算。
TF32 的优势
提高计算效率:
TF32 格式能够在计算性能和数值精度之间取得良好的平衡,从而加速训练过程。
与 FP32 相比,TF32 可以提供更高的吞吐量,因为它使用较少的尾数位来减少计算和内存需求。
兼容性:
TF32 提供了与 FP32 相似的指数范围,但尾数精度略低,这意味着在许多深度学习任务中可以使用 TF32 来加速计算,而不会显著影响训练结果的质量。
简化训练过程:
使用 TF32 可以简化训练过程中的精度管理问题,因为它在精度和性能之间提供了一个良好的折衷。
如何使用 TF32?
在训练脚本中使用 --tf32 True 参数来启用 TF32。这通常与支持 TF32 的硬件(如 NVIDIA A100 GPU)一起使用,以实现加速训练。
–use_lora True
–use_lora True 参数用于启用 LoRA(Low-Rank Adaptation)技术,在深度学习模型的微调过程中进行轻量级的调整。LoRA 是一种有效的微调技术,特别适用于大规模预训练模型。下面是详细解释:
什么是 LoRA?
LoRA (Low-Rank Adaptation) 是一种模型微调方法,通过将预训练模型的权重矩阵分解为低秩矩阵来进行高效的微调。其主要目标是减少微调过程中的计算和存储开销,同时保持模型的性能。LoRA 主要通过以下几个方面实现:
低秩矩阵分解:
LoRA 将模型的权重矩阵分解为两个低秩矩阵的乘积。这种分解减少了参数的数量,从而降低了微调的计算和存储需求。
在微调时,只有这两个低秩矩阵的参数会被更新,原始模型的参数保持不变。
高效微调:
由于只更新低秩矩阵的参数,LoRA 能够显著减少训练过程中的计算和存储需求。
这种方法特别适合于大规模预训练模型(如 GPT-3、BERT 等),因为它能够在保持模型性能的同时,大大减少所需的计算资源。
保持模型性能:
尽管仅更新低秩矩阵的参数,但 LoRA 在实践中能够保持预训练模型的高性能。
这种方法适用于各种下游任务(如文本生成、分类等),可以有效地调整模型以适应特定任务的需求。
如何使用 LoRA?
启用 LoRA 的方法通常涉及将 --use_lora True 作为训练参数传递给训练脚本。以下是启用 LoRA 的一般步骤:
修改训练脚本:
在训练脚本中检查是否设置了 --use_lora True。
如果启用了 LoRA,需要在模型初始化时应用 LoRA 配置。例如,在脚本中使用 peft(Parameter-Efficient Fine-Tuning)库来应用 LoRA。
配置 LoRA:
使用 LoRA 时,可以指定 LoRA 的超参数,如低秩矩阵的秩 ®、LoRA 的 alpha (lora_alpha)、LoRA 的 dropout (lora_dropout) 等。
这些参数控制低秩矩阵的大小和训练过程中的正则化。
示例
假设你有一个微调脚本 fine-tune.py,启用 LoRA 可能会像下面这样配置:
deepspeed --hostfile=hostfile fine-tune.py \
--deepspeed ds_config.json \
--use_lora True \
--model_name_or_path "./Baichuan2-7B-Chat" \
--data_path "./baichuan_formatted_data_copy.json" \
--output_dir "output" \
--num_train_epochs 4 \
--per_device_train_batch_size 16 \
--learning_rate 2e-5
在脚本中的处理
在脚本中启用 LoRA 通常会涉及以下步骤:
if training_args.use_lora:
from peft import LoraConfig, TaskType, get_peft_model
peft_config = LoraConfig(
task_type=TaskType.CAUSAL_LM, # 任务类型,例如语言模型
target_modules=["W_pack"], # 需要应用 LoRA 的模型模块
inference_mode=False,
r=1, # 低秩矩阵的秩
lora_alpha=32, # LoRA 的 alpha 参数
lora_dropout=0.1 # LoRA 的 dropout 参数
)
model.enable_input_require_grads()
model = get_peft_model(model, peft_config)
model.print_trainable_parameters()
总结
–use_lora True 参数用于启用 LoRA(Low-Rank Adaptation)技术,这是一种高效的微调方法,通过低秩矩阵分解来减少训练的计算和存储需求。启用 LoRA 后,只有低秩矩阵的参数会被更新,从而减少了训练过程中的计算负担,同时保持了预训练模型的性能。
微调过程参数解析
在深度学习模型的微调过程中,日志记录提供了实时反馈,用于监控训练的进展和性能。这条日志记录中的各个字段的含义如下:
‘loss’: 2.5156:
这是当前训练步骤中的损失值(loss)。损失值是衡量模型预测与真实标签之间差异的指标,值越低,表示模型的预测越准确。在训练过程中,损失值应该逐渐下降。
‘grad_norm’: 5.068607052198324:
这是梯度的范数(norm)。梯度范数是所有参数的梯度平方和的平方根,表示梯度的大小。过大的梯度范数可能导致梯度爆炸,过小的梯度范数可能导致梯度消失。通过监控梯度范数,可以确保模型训练的稳定性和有效性。
‘learning_rate’: 2e-05:
这是当前的学习率(learning rate)。学习率是一个超参数,控制模型每次更新权重时步长的大小。学习率过高可能导致模型不收敛,过低可能导致训练时间过长。通常,学习率会在训练过程中进行调整。
‘epoch’: 0.0:
这是当前的训练周期(epoch)数。在这个例子中,epoch 值是 0.0,表示训练还在第一个周期内。一个 epoch 是指模型已经看过所有训练样本一次。通常,模型需要多个 epoch 的训练才能达到较好的性能。
结合上下文理解
在模型微调过程中,这些日志记录提供了关键的实时反馈:
损失值(loss):通过监控损失值的变化,可以了解模型的学习进展。随着训练的进行,损失值应该逐步下降,表明模型在不断学习和优化。
梯度范数(grad_norm):监控梯度范数有助于检测训练中的问题,如梯度爆炸或梯度消失,并可以调整优化器的参数(如学习率)以解决这些问题。
学习率(learning_rate):学习率是影响训练速度和稳定性的关键超参数。根据训练的进展,可以使用学习率调度器(scheduler)来调整学习率,以提高模型的收敛速度和性能。
训练周期(epoch):通过记录 epoch,可以了解训练的进度,确保模型在合理的训练时间内完成训练。
启动训练后的模型:
<code>import torch
from modelscope import AutoTokenizer, GenerationConfig
from peft import AutoPeftModelForCausalLM
#路径要与微调代码中的本地模型地址 --model_name_or_path "../Baichuan2-7B-Chat" \ 保持一致
model_dir = "../Baichuan2-7B-Chat/output"
# 确保模型和 tokenizer 已经加载到 GPU,并使用混合精度,没有这行代码默认使用cpu加载,对话响应速度非常慢
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
tokenizer = AutoTokenizer.from_pretrained("../Baichuan2-7B-Chat",
trust_remote_code=True,
torch_dtype=torch.float16)
model = AutoPeftModelForCausalLM.from_pretrained(model_dir,
trust_remote_code=True,
torch_dtype=torch.float16)
model.to(device)
model.generation_config = GenerationConfig.from_pretrained("../Baichuan2-7B-Chat")
while True:
text = input("please input your question: ")
if text == 'q':
break
messages = [{ "role": "user", "content": text}]
answer=model.chat(tokenizer,messages)
print(f"your answer is: {answer}")
测试结果:
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。