找回密码
 立即注册
首页 业界区 科技 大模型预训练

大模型预训练

悯拄等 6 天前
1.分组
  1. '1. 两种训练方法'
  2. 从零开始预训练:BV1xhYtewEum 4分30秒
  3. 二次特定预训练:BV1xhYtewEum
复制代码
2.创建LLM
  1. '1. 创建模型核心流程'
  2. (1)加载模型->(2)将模型放入显卡->(3)输入文本并分词->
  3. (4)将分词放入显卡->(5)设置label->(6)模型输出->
  4. (7)获取模型loss->(8)更新参数->(9)保存模型
复制代码
  1. '2. 创建模型核心代码'
  2. #加载模型
  3. model_path = '/data04/llama3/Meta-Llama-3.1-8B-Instruct'
  4. tokenizer = AutoTokenizer.from_pretrained(model_path)
  5. #将模型放入显卡
  6. model.to("cuda")
  7. optimizer = torch.optim.AdamW(model.parameters())
  8. #输入文本,文本分词
  9. text = "今天天气不错。"
  10. input = tokenizer(text, return_tensors="pt")
  11. input = {k: v.to("cuda") for k, v in input.items()}
  12. #设置labels和inputs一致
  13. input["labels"] = input["input_ids"].clone()
  14. output = model(**input)
  15. #获取模型的loss
  16. loss = output.loss
  17. loss.backward()
  18. optimizer.step()
  19. optimizer.zero_grad()
  20. #保存模型
  21. model.save_pretrained("output_dir")
复制代码
  1. '3. 大模型计算内部Loss'
  2. step1. LLM获取“今天”,输出概率最高的词是“天气”
  3. step2. LLM输出“天气”,根据“今天”、“天气”选择输出概率最高的“不错”
  4. step3. LLM输出“不错”,根据“今天”、“天气”、“不错”选择输出概率最高的“。”
  5. step4. LLM输出“。”,由于输入的内容已经学习完毕,LLM便丢弃最后一个预测
复制代码
  1. '4. llama的loss计算'
  2. #丢弃预测的最后一个token;
  3. #logits是预测结果,形状为 (batch_size, seq_len, classes)
  4. #labels是真实标签,形状为 (batch_size, seq_len)
  5. shift_logits = logits[...,;-1,:].contiguous()
  6. shift_labels = labels[...,1:].contiguous()
  7. #创建交叉熵损失函数
  8. loss_fct = nn.CroassEntropyLoss()
  9. #调整形状
  10. ##logits原始形状:(batch_size, seq_len-1, vocab_size)
  11. ##logits目标形状:(batch_size*(seq_len-1), vocab_size)
  12. shift_logits = shift_logits.view(-1,self.config.vocab_size)
  13. ##labels原始形状:(batch_size, seq_len-1)
  14. ##labels目标形状:(batch_size*(seq_len-1))
  15. shift_labels = shift_labels.view(-1)
  16. #确保 logits和 labels在同一设备计算
  17. shift_labels = shift_labels.to(shift_logits.device)
  18. #损失计算​
  19. loss = loss_fct(shift_logits,shift_labels)
复制代码
  1. '5. 缩小显存需求-量化加载'
  2. # 4bit load
  3. bnb_config = BitsAndBytesConfig(
  4.     load_in_4bit=True,
  5.     bnb_4bit_use_double_quant=True,
  6.     bnb_4bit_quant_type="nf4",
  7.     bnb_4bit_compute_dtype=torch.bfloat16
  8. )
复制代码
  1. '6. 缩小显存需求-LoRA'
  2. # 4bit load
  3. peft_config = LoraConfig(
  4.         r=8,
  5.         target_modules=["q_proj",
  6.                         "v_proj",
  7.                         "k_proj",
  8.                         "o_proj",
  9.                         "gate_proj",
  10.                         "down_proj",
  11.                         "up_proj"
  12.                         ],
  13.         task_type=TaskType.CAUSAL_LM,
  14.         lora_alpha=16,
  15.         lora_dropout=0.05
  16.     )
  17. model = get_peft_model(model, peft_config)
  18. model.print_trainable_parameters()
复制代码
3.训练LLM
  1. '1. 数据处理'
  2. step1 将数据保存为txt文件
  3. step2 在文件的各个节点添加<|begin_of_text|>、<|start_header_id|>、
  4.       <|end_header_id|>、<|end_header_id|>
  5. '2. 参数初始化'
  6. 根据需要选择“验证策略”、“优化器”、“学习率”等参数
  7. # 定义一个参数类
  8. @dataclass
  9. class CustomArguments(transformers.TrainingArguments):
  10.     # LoRA_r
  11.     lora_r: int = field(default=8)
  12.     # 数据处理时的并行进程数
  13.     num_proc: int = field(default=1)
  14. # 使用类
  15. parser = transformers.HfArgumentParser(CustomArguments)
  16. training_args, = parser.parse_args_into_dataclasses()
复制代码
  1. '3. 处理输入数据'
  2. # 加载数据
  3. train_dataset = load_dataset("text", data_dir="/train_data", split="train")
  4. eval_dataset = load_dataset("text", data_dir="/eval_data", split="train")
  5. # 定义分词函数:对传入的数据分词处理
  6. #example是数据集中单条样本的字典,必须包含text字段
  7. def tokenization(example):
  8.     return tokenizer(example["text"])
  9. # 对所以样本进行分词
  10. # main_process_first保证分布式训练只在主进程处理
  11. with training_args.main_process_first(desc="dataset map tokenization"):
  12.     train_dataset = train_dataset.map(tokenization, remove_columns=["text"], num_proc=training_args.num_proc)
  13.     eval_dataset = eval_dataset.map(tokenization, remove_columns=["text"], num_proc=training_args.num_proc)
复制代码
  1. '4. 分组函数'
  2. # 定义分组函数
  3. def group_texts(examples):
  4.     # 拼接所有样本序列,首位相连
  5.     concatenated_examples = {k: list(chain(*examples[k])) for k in examples.keys()}
  6.     # 计算总长度
  7.     total_length = len(concatenated_examples[list(examples.keys())[0]])
  8.     # 确保总长度是max_seq_length的整数倍,剩余的丢弃
  9.     total_length = (total_length // training_args.max_seq_length) * training_args.max_seq_length
  10.     # 分块处理:将连续序列按固定长度切分
  11.     result = {
  12.         k: [t[i: i + training_args.max_seq_length] for i in range(0, total_length, training_args.max_seq_length)]
  13.         for k, t in concatenated_examples.items()
  14.     }
  15.     # 标签对齐
  16.     result["labels"] = result["input_ids"].copy()
  17.     return result
  18. # 使用分组函数
  19. with training_args.main_process_first(desc="dataset map tokenization"):
  20.     train_dataset = train_dataset.map(group_texts, num_proc=training_args.num_proc, batched=True)
  21.     eval_dataset = eval_dataset.map(group_texts, num_proc=training_args.num_proc, batched=True)
复制代码
4.完整代码
  1. from accelerate import PartialState
  2. from datasets import load_dataset
  3. from peft import TaskType, LoraConfig, get_peft_model
  4. from transformers import Trainer
  5. from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
  6. from dataclasses import dataclass, field
  7. import transformers
  8. from itertools import chain
  9. import torch
  10. import warnings
  11. warnings.filterwarnings("ignore")
  12. @dataclass
  13. class CustomArguments(transformers.TrainingArguments):
  14.     # LoRA_r
  15.     lora_r: int = field(default=8)
  16.     # 数据处理时的并行进程数
  17.     num_proc: int = field(default=1)
  18.     # 最大序列长度
  19.     max_seq_length: int = field(default=32)
  20.     # 验证策略,如不想进行验证,可以设置为 ‘no’
  21.     eval_strategy: str = field(default="steps")
  22.     # 每多少步进行一次验证
  23.     eval_steps: int = field(default=100)
  24.     # 随机种子
  25.     seed: int = field(default=0)
  26.     # 优化器
  27.     optim: str = field(default="adamw_torch")
  28.     # 训练epoch数
  29.     num_train_epochs: int = field(default=2)
  30.     # 每个设备上的批量大小
  31.     per_device_train_batch_size: int = field(default=1)
  32.     # 学习率
  33.     learning_rate: float = field(default=5e-5)
  34.     # 权重衰减
  35.     weight_decay: float = field(default=0)
  36.     # 预热步数
  37.     warmup_steps: int = field(default=10)
  38.     # 学习率规划期类型
  39.     lr_scheduler_type: str = field(default="linear")
  40.     # 是否使用梯度检查点
  41.     gradient_checkpointing: bool = field(default=False)
  42.     # 是否使用bf16作为混合精度训练类型
  43.     bf16: bool = field(default=True)
  44.     # 梯度累加步数
  45.     gradient_accumulation_steps: int = field(default=1)
  46.     # 日志记录的步长频率
  47.     logging_steps: int = field(default=3)
  48.     # checkpoint保存策略
  49.     save_strategy: str = field(default="steps")
  50.     # checkpoint保存的步长频率
  51.     save_steps: int = field(default=3)
  52.     # 总的保存checkpoint的数量
  53.     save_total_limit: int = field(default=2)
  54. # 使用CustomArguments
  55. parser = transformers.HfArgumentParser(CustomArguments)
  56. training_args, = parser.parse_args_into_dataclasses()
  57. # 导入模型参数
  58. model_path = '/data04/llama3/Meta-Llama-3.1-8B-Instruct'
  59. # 4b量化加载
  60. bnb_config = BitsAndBytesConfig(
  61.     load_in_4bit=True,
  62.     bnb_4bit_use_double_quant=True,
  63.     bnb_4bit_quant_type="nf4",
  64.     bnb_4bit_compute_dtype=torch.bfloat16
  65. )
  66. tokenizer = AutoTokenizer.from_pretrained(model_path)
  67. # 创建模型
  68. model = AutoModelForCausalLM.from_pretrained(
  69.     model_path,
  70.     low_cpu_mem_usage=True,
  71.     quantization_config=bnb_config,
  72.     device_map={"": PartialState().process_index}
  73. )
  74. # 将模型导入Lora中
  75. peft_config = LoraConfig(
  76.     r=training_args.lora_r,
  77.     target_modules=["q_proj",
  78.                     "v_proj",
  79.                     "k_proj",
  80.                     "o_proj",
  81.                     "gate_proj",
  82.                     "down_proj",
  83.                     "up_proj"
  84.                     ],
  85.     task_type=TaskType.CAUSAL_LM,
  86.     lora_alpha=16,
  87.     lora_dropout=0.05
  88. )
  89. # 微调模型
  90. model = get_peft_model(model, peft_config)
  91. # 计算模型中的可训练参数数量
  92. model.print_trainable_parameters()
  93. # 加载数据
  94. train_dataset = load_dataset("text", data_dir="/home/xuepeng/pretrain_test/train_data", split="train")
  95. eval_dataset = load_dataset("text", data_dir="/home/xuepeng/pretrain_test/eval_data", split="train")
  96. # 输入数据分词
  97. def tokenization(example):
  98.     return tokenizer(example["text"])
  99. with training_args.main_process_first(desc="dataset map tokenization"):
  100.     train_dataset = train_dataset.map(tokenization, remove_columns=["text"], num_proc=training_args.num_proc)
  101.     eval_dataset = eval_dataset.map(tokenization, remove_columns=["text"], num_proc=training_args.num_proc)
  102. # 输入数据分组
  103. def group_texts(examples):
  104.     # 将数据相连
  105.     concatenated_examples = {k: list(chain(*examples[k])) for k in examples.keys()}
  106.     # 计算总长度
  107.     total_length = len(concatenated_examples[list(examples.keys())[0]])
  108.     # 按定义最大长度分组,剩余token舍弃
  109.     total_length = (total_length // training_args.max_seq_length) * training_args.max_seq_length
  110.    # 分块
  111.     result = {
  112.         k: [t[i: i + training_args.max_seq_length] for i in range(0, total_length, training_args.max_seq_length)]
  113.         for k, t in concatenated_examples.items()
  114.     }
  115.     # 标签对齐
  116.     result["labels"] = result["input_ids"].copy()
  117.     return result
  118. with training_args.main_process_first(desc="dataset map tokenization"):
  119.     train_dataset = train_dataset.map(group_texts, num_proc=training_args.num_proc, batched=True)
  120.     eval_dataset = eval_dataset.map(group_texts, num_proc=training_args.num_proc, batched=True)
  121. # 利用transformers包里面的Trainer做训练
  122. if __name__ == '__main__':
  123.     trainer = Trainer(
  124.         model=model,
  125.         args=training_args,
  126.         train_dataset=train_dataset,
  127.         eval_dataset=eval_dataset
  128.     )
  129.     trainer.train()
  130.     trainer.save_model("/data04/xuepeng/test_train")
复制代码
学习视频:【大模型预训练看这个视频就够了】 https://www.bilibili.com/video/BV1xhYtewEum/?share_source=copy_web&vd_source=050ab764db52d186ab224170392c4055

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册