💻
QMMMS的笔记
博客
  • QMMMS的笔记
  • agent
    • MCP的背景、原理和开发
    • Agent 历史与背景
    • Agentic Workflows
    • 环境检查与基础工具
    • Tool Call
    • 工具与运行时的值
    • temp
    • 处理 Tool Call error
    • trick
  • algorithm
    • 线性结构
    • 二叉树
    • 图
    • 查找
    • 排序
    • 动态规划
    • 优化方法
    • 数学
    • 迁移至Java
  • computer_composition
    • 系统总线
    • 存储器
    • 输入输出系统
    • 计算机的运算方法
    • 指令系统
    • 补充
  • computer_network
    • 引入
    • 应用层
    • 传输层
    • 网络层(数据平面)
    • 网络层(控制平面)
    • 链路层
    • 常见问答
    • 实验
  • database
    • SQL实战
    • 关系代数
    • 数据库设计
    • 规范化
    • 数据库基本概念
    • 查询原理
    • 数据库恢复技术
    • 并发控制
  • dev_tools
    • Git
    • Nginx
    • Spring
    • LangChain
    • PyTorch Cheat Sheet
    • MyBatis
    • MySQL Cheat Sheet
    • MySQL 补充
    • Redis
    • Docker
    • RocketMQ
    • Chrome
  • linux
    • Linux基础命令与使用
    • 文件与权限
    • 文件与目录操作
    • 权限属性高级
    • 命令与文件的查找
    • 文件压缩和打包
    • vim编辑器
    • shell变量
    • 命令补充
    • 数据流重定向
    • 管道命令
    • shell脚本
    • 用户管理
    • 用户间交流
    • 计划任务
    • 进程管理
    • 软件管理
    • 认识系统服务
    • 运维常用命令
    • 常用命令
  • llm
    • 大规模语言模型概述
    • 分布式训练概述
    • 有监督微调概述
    • 强化学习与LLM
    • LLM评估概述
    • 大模型应用
    • 理解大模型
    • 量化
    • 预训练
    • 上下文学习
  • machine_learning
    • 引入
    • 大致正确学习
    • 一致收敛
    • 偏差还是过拟合?
    • 可学习的充要条件
    • 非均匀可学习性
    • 计算复杂性
  • mathematics
    • 概率与统计基础
    • 线性代数基础
  • operating_system
    • 操作系统基本概念
    • 进程和线程
    • 同步,互斥与死锁
    • 内存管理
    • 文件系统
    • I/O系统
    • 保护与安全
    • 《现代操作系统》
  • statistical_learning
    • 统计学习引入
    • 线性回归
    • 分类
    • 重抽样方法
    • 线性模型选择与正则化
    • 非线性模型
    • 基于树的方法
    • 支持向量机
    • 无指导学习
    • 马尔科夫链和蒙托卡罗方法简明理解
    • R语言速查
  • deep_learning
    • basic_concepts
      • 逻辑回归与损失函数
      • 神经网络
      • 正则化、预处理、权重初始化
      • 优化算法
      • 机器学习策略
      • 复习:从计算机视觉的角度
      • 卷积神经网络
      • 深度卷积网络示例
      • 计算机视觉任务
      • 循环神经网络
      • 自然语言处理任务
      • 注意力
      • Transformers 家族
      • 显卡扫盲
      • 强化学习概述
    • semi-supervise
      • 半监督学习简介
      • Consistency Regularization
      • Proxy-label Methods
      • Holistic Methods
      • Generative Models
      • Graph-Based SSL
      • Self-Supervision for SSL
      • Other SSL methods
  • programming
    • cpp
      • STL
      • C++基础
      • 内存管理
      • 面向对象
    • java
      • 环境和介绍
      • 注释
      • String
      • 面向对象思想
      • Object
      • 包
      • 访问权限修饰符
      • 初始化块
      • 接口
      • 内部类
      • 注解
      • 枚举
      • 集合框架
      • List
      • Map
      • 泛型
      • 迭代
      • IO与流
      • 序列化
      • 异常
      • Lambda
      • Stream流
      • Socket
      • 缓冲
      • 命名规范
      • 拆箱装箱
      • 值传递
      • 深拷贝
      • 反射
      • JVM
      • 并发编程基础
    • python
      • 并发编程
      • 环境管理
  • software_engineering
    • basic_concepts
      • 系统分析与设计概述
      • 规划
      • 需求分析与原型设计
      • 项目管理
      • 建模
      • 数据库设计
      • 架构
      • 配置管理
      • 测试管理
      • 安全
      • 编码原则
      • 微服务
      • 补充内容
    • software_testing
      • CMMI基础
      • PPQA与SQA
      • 软件测试基础
      • 黑盒测试
      • 白盒测试
      • 集成测试
      • 系统测试
      • 测开面试补充
由 GitBook 提供支持
在本页
  • 简化代码
  • Loss 计算
  • 数据处理
在GitHub上编辑
  1. llm

预训练

上一页量化下一页上下文学习

最后更新于4个月前

预训练的两种情况

  • 从零开始预训练:训练起始时,模型所有参数随机初始化。这种方式需要大量语料、众多显卡以及漫长时间,才能训练出性能良好的大模型。

  • 基于开源预训练模型微调:在已有的开源预训练大模型基础上,针对特定行业(如金融、医疗领域)进行加强训练,提升通用模型在特定领域的知识与能力,这是更常见的情况。

简化代码

我们来看看预训练的

设置模型、tokenizer

model_path = '/data04/llama3/Meta-Llama-3.1-8B-Instruct'
tokenizer = AutoTokenizer.from_pretrained(model_path)

模型放入显卡

model = AutoModelForCausalLM.from_pretrained(
    model_path,
    low_cpu_mem_usage=True,
)
model.to("cuda")

定义优化器

optimizer = torch.optim.AdamW(model.parameters())

定义文本,分词,放入显卡

text = "今天天气不错。"
input = tokenizer(text, return_tensors="pt")
input = {k: v.to("cuda") for k, v in input.items()}
input["labels"] = input["input_ids"].clone()

前向传播,后向传播,更新模型,保存参数

output = model(**input)

#获取模型的loss
loss = output.loss
loss.backward()
optimizer.step()
optimizer.zero_grad()

#保存模型
model.save_pretrained("output_dir")

若要从头训练大模型,可通过llama config初始化默认配置文件,按需修改网络配置(如解码器模块个数、隐藏层大小),构造新模型。

config = LlamaConfig() # 创建一个默认的Llama config
config.num_hidden_layers = 12 # 配置网络结构
config.hidden_size = 1024
config.intermediate_size = 4096
config.num_key_value_heads = 8
# 用配置文件初始化一个大模型
model = LlamaForCausalLM(config)

为减少显存占用,采用四比特加载模型,并添加量化配置信息。

bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_use_double_quant=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16
)

model = AutoModelForCausalLM.from_pretrained(
    model_path,
    low_cpu_mem_usage=True,
    quantization_config=bnb_config
)

生成 LoRA 模型配置,结合原始模型生成 LoRA 模型。

peft_config = LoraConfig(
        r=8,
        target_modules=["q_proj",
                        "v_proj",
                        "k_proj",
                        "o_proj",
                        "gate_proj",
                        "down_proj",
                        "up_proj"
                        ],
        task_type=TaskType.CAUSAL_LM,
        lora_alpha=16,
        lora_dropout=0.05
    )
model = get_peft_model(model, peft_config)

这样普通的机器也可以训练大模型了

hugging face 的Trainer类可简化训练代码,只需准备好数据、模型和配置参数,无需编写训练循环代码。可通过参数配置实现基础功能(如设置batch size、打印loss)和高级功能(如混合精度训练、梯度检查点、梯度累积),且支持分布式训练

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=train_dataset,
    eval_dataset=eval_dataset
)
trainer.train()
trainer.save_model("/data04/xuepeng/test_train")

数据集处理见后面的章节

使用accelerator进行分布式训练,通过accelerator config配置分布式训练,选择单机多卡模式,设置使用的 GPU 卡和混合精度训练类型。使用accelerator launch命令启动训练脚本,并指定输出模型路径、LoRA参数等

Loss 计算

以输入 “今天天气不错” 为例,模型将其拆分为多个token。模型根据前一个或多个token输出下一个token的概率分布,期望目标token的概率尽可能大,其他token概率尽可能小,这本质上是一个分类问题

由于句子结束,训练时丢弃最后输出的token,不进行loss计算。在 hugging face 的llama model中,先丢弃预测的最后一个token,将input左移一位形成最终的label,使用交叉熵损失函数计算loss

数据处理

数据清洗与添加特殊token:假设数据已完成清洗,我们还需要在文本中添加特殊token,即tokenizer的BOS(Begin of Sequence)和EOS(End of Sequence)。不同模型的BOS和EOS不同,可查看tokenizer配置文件获取,例子如下

<|begin_of_text|>神州数码接管 深圳地税核心征管系统
  羊城晚报讯  记者韩平报道:中国最大的IT服务提供商神州数码控股有限公司17日正式对外宣布,已正式接管中国第三大地税收入过千亿的副省级城市——— 深圳市地税核心征管系统,公司将进一步拓展深圳及整个华南区市场。这是继海南省地税项目中标后,神州数码接获的又一个副省级以上地税“核心征管系统”。神州数码主席兼首席执行官郭为表示,神州数码将加大在深圳的市场拓展力度。<|eot_id|>

加载与分词数据:使用 hugging face datasets库的load_dataset方法加载文件夹中的所有 TXT 文件,分别加载训练集和验证集。

train_dataset = load_dataset("text", data_dir="/home/xuepeng/pretrain_test/train_data", split="train")
eval_dataset = load_dataset("text", data_dir="/home/xuepeng/pretrain_test/eval_data", split="train")

定义分词函数,对训练集和验证集调用map函数进行分词,并确保在分布式训练时仅主进程进行数据处理。

def tokenization(example):
    return tokenizer(example["text"])

with training_args.main_process_first(desc="dataset map tokenization"):
    train_dataset = train_dataset.map(tokenization, remove_columns=["text"], num_proc=training_args.num_proc)
    eval_dataset = eval_dataset.map(tokenization, remove_columns=["text"], num_proc=training_args.num_proc)

分组处理数据:定义分组函数,将一组分词后的序列样本首尾相连,按用户定义的最长序列长度进行切分,丢弃剩余部分。最后增加labels列,其token id与input token id相同。

def group_texts(examples):
    # Concatenate all texts.
    concatenated_examples = {k: list(chain(*examples[k])) for k in examples.keys()}
    total_length = len(concatenated_examples[list(examples.keys())[0]])
    # We drop the small remainder, and if the total_length < block_size  we exclude this batch and return an empty dict.
    # We could add padding if the model supported it instead of this drop, you can customize this part to your needs.
    total_length = (total_length // training_args.max_seq_length) * training_args.max_seq_length
    # Split by chunks of max_len.
    result = {
        k: [t[i: i + training_args.max_seq_length] for i in range(0, total_length, training_args.max_seq_length)]
        for k, t in concatenated_examples.items()
    }
    result["labels"] = result["input_ids"].copy()
    return result
# 分组操作
with training_args.main_process_first(desc="dataset map tokenization"):
    train_dataset = train_dataset.map(group_texts, num_proc=training_args.num_proc, batched=True)
    eval_dataset = eval_dataset.map(group_texts, num_proc=training_args.num_proc, batched=True)
简化代码