LLM-3-ChatGLM2

1 训练

1.1 训练参数配置理解

训练的输入长度=source的长度+target的长度

–pre_seq_len:pre_seq_len的取值范围一般是1到512,它表示自然语言指令的长度,即输入序列中的前pre_seq_len个token,具体的值需要根据自然语言指令的长度和复杂度来确定。一般来说,指令越长越复杂,pre_seq_len就需要越大,以便模型能够充分理解指令的含义。但是,pre_seq_len也不能太大,否则会占用过多的输入序列长度,导致生成内容过于单一或重复。因此,pre_seq_len的取值需要在保证指令完整性和生成多样性之间进行权衡。一种可能的方法是,根据不同的指令类型设置不同的pre_seq_len值,例如,对于简单的指令,如“生成一个笑话”,可以设置pre_seq_len为4;对于复杂的指令,如“生成一个关于环保主题的故事”,可以设置pre_seq_len为16。当然,这些值也需要根据实际的效果进行调整和优化。

–pre_seq_len和max_source_length的含义是差不多的,或者取值是可以参照的?不完全是的,pre_seq_len和max_source_length的含义是不同的,但是它们之间有一定的关系。pre_seq_len是指自然语言指令的长度,而max_source_length是指整个输入序列的最大长度。一般来说,pre_seq_len应该小于或等于max_source_length,因为输入序列除了包含指令之外,还可能包含其他内容,例如上下文信息或对话历史。如果pre_seq_len大于max_source_length,那么模型就无法接收到完整的指令,也就无法正确地生成输出内容。因此,pre_seq_len和max_source_length的取值需要协调一致,以保证模型能够有效地利用输入信息。

P-Tuning的时候的 soft prompt的长度,越大可微调的参数越多

PRE_SEQ_LEN=128
LR=2e-2
NUM_GPUS=2

torchrun --standalone --nnodes=1 --nproc-per-node=$NUM_GPUS main.py \
    --do_train \
    --train_file AdvertiseGen/train.json \
    --validation_file AdvertiseGen/dev.json \
    --preprocessing_num_workers 10 \
    --prompt_column content \
    --response_column summary \
    --overwrite_cache \
    --model_name_or_path /usr/local/serving/models/chatglm/chatglm2-6b \
    --output_dir output/adgen-chatglm2-6b-pt-$PRE_SEQ_LEN-$LR \
    --overwrite_output_dir \
    --max_source_length 64 \
    --max_target_length 128 \
    --per_device_train_batch_size 1 \
    --per_device_eval_batch_size 1 \
    --gradient_accumulation_steps 16 \
    --predict_with_generate \
    --max_steps 3000 \
    --logging_steps 10 \
    --save_steps 1000 \
    --learning_rate $LR \
    --pre_seq_len $PRE_SEQ_LEN \
    --quantization_bit 4


这段代码使用了 `torchrun` 命令来以分布式训练的方式运行 `main.py` 文件。具体来说,代码参数解释如下:

- `--standalone` 表示以独立模式启动分布式训练(即在同一台机器上的多个 GPU 上运行)。如果在多个机器上运行,则需要设置其他参数,例如 `--nnodes` 和 `--nproc-per-node` 等。

- `--nnodes` 指定节点数。在这个例子中,只有一个节点,所以设置为 1- `--nproc-per-node` 指定每个节点上的进程数。在这个例子中,只使用一个 GPU,所以设置为 1- `--do_train` 表示执行训练任务。

- `--train_file` 指定训练数据文件路径。

- `--validation_file` 指定验证数据文件路径。

- `--preprocessing_num_workers` 指定数据预处理时的工人数。

- `--prompt_column` 指定输入数据中输入文本所在的列。

- `--response_column` 指定输出数据中输出文本所在的列。

- `--overwrite_cache` 表示覆盖缓存文件。

- `--model_name_or_path` 指定使用的预训练模型的名称或路径。

- `--output_dir` 指定输出目录,即训练结果和模型保存目录。

- `--overwrite_output_dir` 表示覆盖输出目录。

- `--max_source_length` 指定输入文本的最大长度。

- `--max_target_length` 指定输出文本的最大长度。

- `--per_device_train_batch_size` 指定每个 GPU 上每次训练时的批量大小。

- `--per_device_eval_batch_size` 指定每个 GPU 上每次验证时的批量大小。

- `--gradient_accumulation_steps` 指定累积多少个梯度之后再进行一次反向传播。

- `--predict_with_generate` 表示在预测时使用生成模式。

- `--max_steps` 指定最大训练步数。

- `--logging_steps` 指定多少步记录一次日志。

- `--save_steps` 指定多少步保存一次模型。

- `--learning_rate` 指定初始学习率。

- `--pre_seq_len` 指定预处理时选取的序列长度。

- `--quantization_bit` 指定量化位数。

该命令将会在 PyTorch 1.7 或更高版本上运行。在此之前的版本中,可能需要单独设置分布式环境,享用多 GPU 训练所带来的好处。

1.2 多级多卡运行配置

好的,请容许我再详细解释一下多级多卡运行的调整步骤:

假设我们有两台机器 m1 和 m2,每台机器上有两块 GPU,我们希望在这两台机器上使用 PyTorch 的分布式训练模式运行代码:

1. 安装 PyTorch

首先在 m1 和 m2 上安装 PyTorch,并确保安装相同版本的 PyTorch。

2. 设置环境变量

在每台机器上设置相同的环境变量,以指定 PyTorch 使用分布式训练模式:

export WORLD_SIZE=
export RANK=
export MASTER_ADDR=
export MASTER_PORT=


其中,`number_of_processes` 是进程数,假设使用四个 GPU,所以 `number_of_processes` 是 4 。`rank_of_current_process` 是当前进程的排名,假设在 m1 中的排名为 0 和 1,m2 中的排名为 2 和 3。`address_of_master_machine` 是主节点的 IP 地址或主机名,假设主节点为 m1。`port_of_master_machine` 是主节点的端口号,假设主节点端口号为 1234。

3. 同步时间

确保所有机器的系统时间是同步的,可以使用如下命令同步时间:

sudo ntpdate cn.pool.ntp.org


4. 配置 SSH 免密登录

在每台机器上都需要通过 SSH 连接到其他机器。为此,需要在每台机器上配置 SSH 免密登录,以便不需要密码就可以登录到其他机器。可以使用如下命令生成公私钥对:

ssh-keygen -t rsa -P “”


然后将生成的公钥复制到其他机器的 `authorized_hosts` 文件中。

5. 编写工作节点程序

在工作节点上,需要自己定义需要运行的 Python 脚本代码。例如,我们编写了 worker.py 文件:

```python
# worker.py
import torch

# 定义需要执行的 PyTorch 代码
def run():
    rank = torch.distributed.get_rank()
    print(f"Rank {rank} is running on {torch.cuda.device_count()} GPUs.")

if __name__ == '__main__':
    # 设置分布式环境
    torch.distributed.init_process_group(backend='nccl')
    
    # 执行 PyTorch 代码
    run()

可以发现,这段程序中主要定义了需要运行的 PyTorch 代码。在 main.py/dataload.py/… 中,您可以根据自己的需要修改和编写相应的代码,例如模型定义、数据加载等等。

  1. 启动多进程

在 m1 的启动终端中运行以下命令:

# 启动第一个进程
python -m torch.distributed.launch --nproc_per_node=2 --use_env --master_port=1234 --node_rank=0 worker.py &

# 启动第二个进程
python -m torch.distributed.launch --nproc_per_node=2 --use_env --master_port=1234 --node_rank=1 worker.py &

在 m2 的启动终端中运行以下命令:

# 启动第三个进程
python -m torch.distributed.launch --nproc_per_node=2 --use_env --master_addr=<m1-ip> --master_port=1234 --node_rank=2 worker.py &

# 启动第四个进程
python -m torch.distributed.launch --nproc_per_node=2 --use_env --master_addr=<m1-ip> --master_port=1234 --node_rank=3 worker.py &

注意:

  • --use_env 参数,以便子进程能够继承主节点的环境变量。
  • --nproc_per_node 参数指定每台机器上的 GPU 数量。
  • 对于每个进程指定不同的 --node_rank 参数,对应上面步骤 2 中设置的当前进程的排名。
  • 对于主节点,可以选择启动 main.py 文件作为第一个进程。

启动后,各个进程就会分别运行 worker.py 文件中定义的函数,并借助分布式环境来执行其任务。

1.3 @dataclass 装饰器

@dataclass 是 Python 3.7 及更高版本中提供的一个装饰器。它能够自动为类生成一些常用的方法和属性,例如 `__init__` 方法、`__repr__` 方法以及属性的 getter 和 setter 方法。

在上面的代码中,@dataclass 被用于定义了两个类:ModelArguments 和 DataTrainingArguments。

这样使用 @dataclass 装饰器的类可以省略一些常见的代码,例如不再需要手动定义 init 方法、repr 方法和 getter/setter 方法。取而代之的是,使用 @dataclass 装饰器后, Python 会自动根据类的字段生成这些方法。

此外,通过给字段添加 field() 函数的调用,还可以为字段提供额外的元数据,例如字段的默认值和帮助文档。field()函数通常用于指定字段的元数据,例如默认值和帮助文档。

总之,@dataclass 能够简化类的定义过程,减少重复的代码,提高代码的可读性和可维护性。在上述代码中, @dataclass 装饰器和 field 函数的使用可以使 ModelArguments 和 DataTrainingArguments 类拥有自动生成的初始化方法、表示方法和 getter/setter 方法,并且提供了一些元数据,方便后续使用这些类的对象。

1.4 系统参数,模型参数配置,HF已经内置默认参数

Seq2SeqTrainingArguments(
_n_gpu=0,
adafactor=False,
adam_beta1=0.9,
adam_beta2=0.999,
adam_epsilon=1e-08,
auto_find_batch_size=False,
bf16=False,
bf16_full_eval=False,
data_seed=None,
dataloader_drop_last=False,
dataloader_num_workers=0,
dataloader_pin_memory=True,
ddp_backend=None,
ddp_bucket_cap_mb=None,
ddp_find_unused_parameters=None,
ddp_timeout=1800,
debug=[],
deepspeed=None,
disable_tqdm=False,
do_eval=False,
do_predict=False,
do_train=True,
eval_accumulation_steps=None,
eval_delay=0,
eval_steps=None,
evaluation_strategy=no,
fp16=False,
fp16_backend=auto,
fp16_full_eval=False,
fp16_opt_level=O1,
fsdp=[],
fsdp_config={
   'fsdp_min_num_params': 0, 'xla': False, 'xla_fsdp_grad_ckpt': False},
fsdp_min_num_params=0,
fsdp_transformer_layer_cls_to_wrap=None,
full_determinism=False,
generation_config=None,
generation_max_length=None,
generation_num_beams=None,
gradient_accumulation_steps=16,
gradient_checkpointing=False,
greater_is_better=None,
group_by_length=False,
half_precision_backend=auto,
hub_model_id=None,
hub_private_repo=False,
hub_strategy=every_save,
hub_token=<HUB_TOKEN>,
ignore_data_skip=False,
include_inputs_for_metrics=False,
jit_mode_eval=False,
label_names=None,
label_smoothing_factor=0.0,
learning_rate=0.02,
length_column_name=length,
load_best_model_at_end=False,
local_rank=0,
log_level=passive,
log_level_replica=warning,
log_on_each_node=True,
logging_dir=output/adgen-chatglm-6b-pt-$PRE_SEQ_LEN-$LR\runs\Jul25_14-10-13_Jett,
logging_first_step=False,
logging_nan_inf_filter=True,
logging_steps=10,
logging_strategy=steps,
lr_scheduler_type=linear,
max_grad_norm=1.0,
max_steps=3000

你可能感兴趣的:(人工智能,AIGC,笔记,人工智能,深度学习,算法)