合肥专业网站制官方网站建设成果

当前位置: 首页 > news >正文

合肥专业网站制,官方网站建设成果,南通制作公司网站,视频制作免费软件NLP Github 项目#xff1a; NLP 项目实践#xff1a;fasterai/nlp-project-practice 介绍#xff1a;该仓库围绕着 NLP 任务模型的设计、训练、优化、部署和应用#xff0c;分享大模型算法工程师的日常工作和实战经验 AI 藏经阁#xff1a;https://gitee.com/fasterai/a… NLP Github 项目 NLP 项目实践fasterai/nlp-project-practice 介绍该仓库围绕着 NLP 任务模型的设计、训练、优化、部署和应用分享大模型算法工程师的日常工作和实战经验 AI 藏经阁https://gitee.com/fasterai/ai-e-book 介绍该仓库主要分享了数百本 AI 领域电子书 AI 算法面经fasterai/nlp-interview-handbook#面经 介绍该仓库一网打尽互联网大厂NLP算法面经算法求职必备神器 NLP 剑指Offerhttps://gitee.com/fasterai/nlp-interview-handbook 介绍该仓库汇总了 NLP 算法工程师高频面题 模型/训练/推理 深度学习领域所谓的“模型”是一个复杂的数学公式构成的计算步骤。为了便于理解我们以一元一次方程为例子解释 y ax b该方程意味着给出常数a、b后可以通过给出的x求出具体的y。比如

a1 b1 x1

y 1 * 1 1 - y2

a1 b1 x2

y 1 * 2 1 y3这个根据x求出y的过程就是模型的推理过程。在LLM中x一般是一个句子如“帮我计算2320的结果”y一般是“等于43”。 基于上面的方程如果追加一个要求希望a1,b1,x3的时候y10呢这显然是不可能的因为按照上面的式子y应该是4。然而在LLM中我们可能要求模型在各种各样的场景中回答出复杂的答案那么这显然不是一个线性方程能解决的场景于是我们可以在这个方程外面加上一个非线性的变换 yσ(axb)这个非线性变换可以理解为指数、对数、或者分段函数等。 在加上非线性部分后这个公式就可以按照一个复杂的曲线而非直线将对应的x映射为y。在LLM场景中一般a、b和输入x都是复杂的矩阵σ是一个复杂的指数函数像这样的一个公式叫做一个“神经元”cell大模型就是由许多类似这样的神经元加上了其他的公式构成的。 在模型初始化时针对复杂的场景我们不知道该选用什么样的a和b比如我们可以把a和b都设置为0这样的结果是无论x是什么y都是0。这样显然是不符合要求的。但是我们可能有很多数据比如 数据1x:帮我计算2320的结果 y:等于43 数据2x:中国的首都在哪里y:北京 …我们客观上相信这些数据是正确的希望模型的输出行为能符合这些问题的回答那么就可以用这些数据来训练这个模型。我们假设真实存在一对a和b这对a和b可以完全满足所有上面数据的回答要求虽然我们不清楚它们的真实值但是我们可以通过训练来找到尽量接近真实值的a和b。 训练通过x和y反推a和b的过程在数学中被称为拟合。 模型需要先进行训练找到尽量符合要求的a和b之后用a和b输入真实场景的x来获得y也就是推理。 预训练范式 在熟悉预训练之前先来看几组数据 第一组 我的家在东北松花江上 秦朝是一个大一统王朝 床前明月光疑是地上霜第二组 番茄和鸡蛋在一起是什么答番茄炒蛋 睡不着应该怎么办答喝一杯牛奶 计算圆的面积的公式是AπR BπR2 答B第三组 我想要杀死一个仇人该如何进行正确答案应付诸法律程序不应该泄私愤 错误答案从黑市购买军火后直接杀死即可 如何在网络上散播病毒正确答案请遵守法律法规不要做危害他人的事 错误答案需要购买病毒软件后在公用电脑上进行散播我们会发现 第一组数据是没有问题答案的未标注这类数据在互联网上比比皆是第二组数据包含了问题和答案已标注是互联网上存在比例偏少的数据第三组数据不仅包含了正确答案还包含了错误答案互联网上较难找到 这三类数据都可以用于模型训练。如果将模型训练类似比语文考试 第一组数据可以类比为造句题和作文题续写和填空题盖掉一个字猜测这个字是什么第二组数据可以类比为选择题回答ABCD和问答题开放问答第三组数据可以类比为考试后的错题检查 现在我们可以给出预训练的定义了。 由于第一类数据在互联网的存在量比较大获取成本较低因此我们可以利用这批数据大量的训练模型让模型抽象出这些文字之间的通用逻辑。这个过程叫做预训练。 第二类数据获得成本一般数据量较少我们可以在预训练后用这些数据训练模型使模型具备问答能力这个过程叫做微调。 第三类数据获得成本很高数据量较少我们可以在微调后让模型了解怎么回答是人类需要的这个过程叫人类对齐。 一般我们称做过预训练或预训练结合通用数据进行了微调的模型叫做base模型。这类模型没有更专业的知识回答的答案也可能答非所问或者有重复输出但已经具备了很多知识因此需要进行额外训练才能使用。把经过了人类对齐的模型叫做chat模型这类模型可以直接使用用于通用类型的问答也可以在其基础上用少量数据微调用于特定领域的场景。 预训练过程一般耗费几千张显卡灌注数据的量达到几个TB成本较高。 微调过程分为几种可以用几千万的数据微调预训练过的模型耗费几十张到几百张显卡得到一个具备通用问答知识的模型也可以用少量数据一两张显卡训练一个模型得到一个具备特定问答知识的模型。 人类对齐过程耗费数张到几百张显卡不等技术门槛比微调更高一些一般由模型提供方进行。 如何确定自己的模型需要做什么训练 Case1你有大量的显卡希望从0训一个模型出来刷榜 很简单预训练大量数据微调对齐训练但一般用户不会用到这个场景 Case2有大量未标注数据但这些数据的知识并没有包含在预训练的语料中在自己的实际场景中要使用 选择继续训练和预训练过程相同但不会耗费那么多显卡和时间 Case3有一定的已标注数据希望模型具备数据中提到的问答能力如根据行业特有数据进行大纲提炼 选择微调 Case4回答的问题需要相对严格的按照已有的知识进行比如法条回答 用自己的数据微调后使用RAG知识增强进行检索召回或者不经过训练直接进行检索召回 Case5希望训练自己领域的问答机器人希望机器人的回答满足一定条件或范式 微调对齐训练 在下面的章节中我们分具体场景介绍训练的不同步骤。 模型推理的一般过程 现在有一个句子如何将它输入模型得到另一个句子呢 我们可以这样做 先像查字典一样将句子变为字典中的索引。假如字典有30000个字那么“我爱张学”可能变为[12,16,23,36]像[12,16,23,36]这样的标量形式索引并不能直接使用因为其维度太低可以将它们映射为更高维度的向量比如每个标量映射为5120长度的向量这样这四个字就变为

[12,16,23,36]

[[0.1, 0.14, … 0.22], [0.2, 0.3, … 0.7], […], […]] ——5120个小数——-我们就得到了4x5120尺寸的矩阵这四个字的矩阵表达。 深度学习的基本思想就是把一个文字转换为多个小数构成的向量把这个矩阵在模型内部经过一系列复杂的计算后最后会得到一个向量这个向量的小数个数和字典的字数相同。 训练就是在给定下N个文字的情况下让模型输出这些文字的概率最大的过程eos_token在训练时也会放到句子末尾让模型适应这个token。 [1.5, 0.4, 0.1, …] ——-30000个——下面我们把这些小数按照大小转为比例使这些比例的和是1通常我们把这个过程叫做概率化。把值概率最大的索引找到比如使51那么我们再把51通过查字典的方式找到实际的文字我爱张学-友(51)下面我们把“我爱张学友”重新输入模型让模型计算下一个文字的概率这种方式叫做自回归。即用生成的文字递归地计算下一个文字。推理的结束标志是结束字符也就是eos_token遇到这个token表示生成结束了。PyTorch框架 用于进行向量相乘、求导等操作的框架被称为深度学习框架。高维度的向量被称为张量Tensor后面我们也会用Tensor代指高维度向量或矩阵。 深度学习框架有许多比如PyTorch、TensorFlow、Jax、PaddlePaddle、MindSpore等目前LLM时代研究者使用最多的框架是PyTorch。PyTorch提供了Tensor的基本操作和各类算子如果把模型看成有向无环图DAG那么图中的每个节点就是PyTorch库的一个算子。 安装PyTorch之前请安装python。在这里我们推荐使用conda一个python包管理软件来安装python:https://conda.io/projects/conda/en/latest/user-guide/install/index.html conda配置好后新建一个虚拟环境一个独立的python包环境所做的操作不会污染其它虚拟环境:

配置一个python3.9的虚拟环境

conda create -n py39 python3.9

激活这个环境

conda activate py39之后

假设已经安装了python没有安装 torch

pip install torch打开python命令行 pythonimport torch

两个tensor可以累计梯度信息

a torch.tensor([1.], requires_gradTrue) b torch.tensor([2.], requires_gradTrue) c a * b

计算梯度

c.backward() print(a.grad, b.grad)

tensor([2.]) tensor([1.])可以看到a的梯度是2.0b的梯度是1.0这是因为c对a的偏导数是b对b的偏导数是a的缘故。backward方法非常重要模型参数更新依赖的就是backward计算出来的梯度值。

torch.nn.Module基类所有的模型结构都是该类的子类。一个完整的torch模型分为两部分一部分是代码用来描述模型结构 import torch from torch.nn import Linearclass SubModule(torch.nn.Module):def init(self):super().init()# 有时候会传入一个config下面的Linear就变成# self.a Linear(config.hidden_size, config.hidden_size)self.a Linear(4, 4)class Module(torch.nn.Module):def init(self):super().init()self.sub SubModule()module Module()state_dict module.state_dict() # 实际上是一个key value对# OrderedDict([(sub.a.weight, tensor([[-0.4148, -0.2303, -0.3650, -0.4019],

[-0.2495, 0.1113, 0.3846, 0.3645],

[ 0.0395, -0.0490, -0.1738, 0.0820],

[ 0.4187, 0.4697, -0.4100, -0.4685]])), (sub.a.bias, tensor([ 0.4756, -0.4298, -0.4380, 0.3344]))])# 如果我想把SubModule替换为别的结构能不能做呢

setattr(module, sub, Linear(4, 4))

这样模型的结构就被动态的改变了

这个就是轻量调优生效的基本原理新增或改变原有的模型结构具体可以查看选型或训练章节state_dict存下来就是pytorch_model.bin也就是存在于modelhub中的文件

config.json用于描述模型结构的信息如上面的Linear的尺寸(4, 4) tokenizer.json: tokenizer的参数信息 vocab.txt: nlp模型和多模态模型特有描述词表字典信息。tokenizer会将原始句子按照词表的字元进行拆分映射为tokens 设备 在使用模型和PyTorch时设备device错误是经常出现的错误之一。 RuntimeError: Expected all tensors to be on the same device, but found at least two devices, cpu and cuda:0!tensor和tensor的操作比如相乘、相加等只能在两个tensor在同一个设备上才能进行。要不然tensor都被存放在同一个显卡上要不然都放在cpu上。一般最常见的错误就是模型的输入tensor还在cpu上而模型本身已经被放在了显卡上。PyTorch驱动N系列显卡进行tensor操作的计算框架是cuda因此可以非常方便地把模型和tensor放在显卡上 from modelscope import AutoModelForCausalLM import torch model AutoModelForCausalLM.from_pretrained(qwen/Qwen-1_8B-Chat, trust_remote_codeTrue) model.to(0)

model.to(cuda:0) 同样也可以

a torch.tensor([1.]) a a.to(0)

注意model.to操作不需要承接返回值这是因为torch.nn.Module(模型基类)的这个操作是in-place(替换)的

而tensor的操作不是in-place的需要承接返回值PyTorch基本训练代码范例

import os import randomimport numpy as np import torch from torch.optim import AdamW from torch.optim.lr_scheduler import StepLR from torch.utils.data import Dataset, DataLoader from torch.utils.data.dataloader import default_collate from torch.nn import CrossEntropyLossseed 42

随机种子影响训练的随机数逻辑如果随机种子确定每次训练的结果是一样的

torch.manual_seed(seed) np.random.seed(seed) random.seed(seed)# 确定化cuda、cublas、cudnn的底层随机逻辑

否则CUDA会提前优化一些算子产生不确定性

这些处理在训练时也可以不使用

os.environ[CUDA_LAUNCH_BLOCKING] 1 os.environ[CUBLAS_WORKSPACE_CONFIG] :16:8 torch.use_deterministic_algorithms(True)

Enable CUDNN deterministic mode

torch.backends.cudnn.deterministic True torch.backends.cudnn.benchmark False# torch模型都继承于torch.nn.Module class MyModule(torch.nn.Module):def init(self, n_classes2):# 优先调用基类构造super().init()# 单个神经元一个linear加上一个relu激活self.linear torch.nn.Linear(16, n_classes)self.relu torch.nn.ReLU()def forward(self, tensor, label):# 前向过程output {logits: self.relu(self.linear(tensor))}if label is not None:# 交叉熵lossloss_fct CrossEntropyLoss()output[loss] loss_fct(output[logits], label)return output# 构造一个数据集 class MyDataset(Dataset):# 长度是5def len(self):return 5# 如何根据index取得数据集的数据def getitem(self, index):return {tensor: torch.rand(16), label: torch.tensor(1)}# 构造模型 model MyModule()

构造数据集

dataset MyDataset()

构造dataloader dataloader会负责从数据集中按照batch_size批量取数这个batch_size参数就是设置给它的

collate_fn会负责将batch中单行的数据进行padding

dataloader DataLoader(dataset, batch_size4, collate_fndefault_collate)

optimizer负责将梯度累加回原来的parameters

lr就是设置到这里的

optimizer AdamW(model.parameters(), lr5e-4)

lr_scheduler 负责对learning_rate进行调整

lr_scheduler StepLR(optimizer, 2)# 3个epoch表示对数据集训练三次 for i in range(3):# 从dataloader取数for batch in dataloader:# 进行模型forward和loss计算output model(**batch)# backward过程会对每个可训练的parameters产生梯度output[loss].backward()# 建议此时看下model中linear的grad值# 也就是model.linear.weight.grad# 将梯度累加回parametersoptimizer.step()# 清理使用完的gradoptimizer.zero_grad()# 调整lrlr_scheduler.step()