【LLM学习】1-NLP回顾+Pytorch复习
目录
0.引言
1. NLP基础学习
1.1文本预处理(分词、tokenization)。
1.1.1 分词(Tokenization)
1.2词嵌入(word embeddings,如Word2Vec)
1.2.1 Word2Vec(基于上下文训练)
1.2.2 预训练词向量(GloVe、FastText)
1.2.4 Transformer 词嵌入(BERT, GPT)
1.3序列建模(RNN、LSTM初步了解即可,重点转到transformer)
1) 自注意力机制
2.Pytorch快速入门/复习
2.1基础组件
2.2模型构建与训练
2.3数据处理
2.4调试与优化
0.引言
随着大模型爆火,准备好好深入学习下,根据招聘岗位,总结了下大模型人才需要具备以下能力:
- 深度学习与大模型开发:熟练掌握 PyTorch,了解 TensorFlow,熟悉 Transformer、BERT、GPT 等模型及其微调算法(如 LoRA)。
- 大模型微调与优化:掌握微调方法(Supervised/PEFT)、指令微调、模型对齐、推理性能加速(vLLM、LmDeploy、Ollama 等)。
- RAG(检索增强生成):熟悉 LangChain、Haystack、LlamaIndex,能结合向量数据库(Milvus、Chroma)进行知识库构建。
- 大模型训练与部署:具备训练数据构建、训练策略优化、分布式计算(DeepSpeed)、GPU架构与推理优化经验。
之前有NLP的文档,但是也忘得差不多了且废话有点多,针对LLM需要的知识恶补一下:
关于Transformer架构见:NLP实战8:图解 Transformer笔记_nlp和transformer架构-CSDN博客
1. NLP基础学习
- 目标: 掌握NLP核心概念,为理解LLM打基础。
1.1文本预处理(分词、tokenization)。
文本数据需要转换为模型可处理的格式,主要步骤包括:
1.1.1 分词(Tokenization)
分词是 NLP 处理的第一步,将句子拆分为独立的单词或子词。
1) 基于空格分词(英文)
text = "Natural Language Processing is fascinating!"
tokens = text.split() # 直接按空格分词
print(tokens) # ['Natural', 'Language', 'Processing', 'is', 'fascinating!']
2) 中文分词(jieba 库)
import jieba
text = "自然语言处理是人工智能的一个重要方向。"
tokens = jieba.lcut(text)
print(tokens) # ['自然语言处理', '是', '人工智能', '的', '一个', '重要', '方向', '。']
1.2词嵌入(word embeddings,如Word2Vec)
词嵌入是将单词转换为向量,使得语义相近的词在向量空间中距离更近。
1.2.1 Word2Vec(基于上下文训练)
Word2Vec 通过 CBOW
或 Skip-gram
训练单词向量:
from gensim.models import Word2Vec
sentences = [["I", "love", "NLP"], ["NLP", "is", "awesome"]]
model = Word2Vec(sentences, vector_size=50, min_count=1)
print(model.wv["NLP"]) # 获取 NLP 的词向量
1.2.2 预训练词向量(GloVe、FastText)
可使用 预训练的嵌入模型(如 GloVe、FastText):
from gensim.models import KeyedVectors
model = KeyedVectors.load_word2vec_format("glove.6B.50d.txt", binary=False)
print(model["king"] - model["man"] + model["woman"]) # 词向量计算
1.2.4 Transformer 词嵌入(BERT, GPT)
现代 NLP 使用 Transformer(BERT、GPT)编码语义:
from transformers import BertTokenizer, BertModel
import torch
tokenizer = BertTokenizer.from_pretrained("bert-base-uncased")
model = BertModel.from_pretrained("bert-base-uncased")
tokens = tokenizer("Hello world", return_tensors="pt")
output = model(**tokens)
print(output.last_hidden_state.shape) # (1, token数, 隐藏层维度)
1.3序列建模(RNN、LSTM初步了解即可,重点转到transformer)
RNN(循环神经网络)-RNN 适用于处理文本序列,但存在梯度消失问题。
LSTM(长短时记忆网络)LSTM 通过 门控机制 解决梯度消失。
Transformer 解决 RNN 的长期依赖问题,引入自注意力机制(Self-Attention)。
1) 自注意力机制
自注意力计算输入序列中每个词对其他词的影响:
Q
(查询)K
(键)V
(值)Attention(Q, K, V) = softmax(QK^T / sqrt(d_k)) V
2.Pytorch快速入门/复习
在此之前,可以先了解两个概能,有助于下面的学习:
前向传播(Forward Propagation)
定义:前向传播是指从输入数据开始,通过神经网络的每一层,逐步计算输出值的过程。
反向传播(Backpropagation)
定义:反向传播是指从输出层开始,通过链式法则计算损失函数对每个参数的梯度,并将梯度传递回网络的每一层,用于更新参数的过程。
类比一下就是
前向传播:就像你做数学题时,从已知条件一步步推导出答案。
反向传播:就像你检查答案时,从结果一步步回溯,找出哪里出错了,并修正错误。
-
2.1基础组件
- 张量(Tensor)操作:创建、运算、形状变换等
定义:张量(Tensor)是 PyTorch 的核心数据结构,可以看作矩阵。类似于 NumPy 的数组,但支持 GPU 加速和自动求导。
创建
import torch
# 直接从数据创建
tensor1 = torch.tensor([[1, 2], [3, 4]], dtype=torch.float32)
# 创建全 0 或全 1 张量
zeros_tensor = torch.zeros((3, 3))
ones_tensor = torch.ones((2, 4))
# 创建随机张量
rand_tensor = torch.rand((2, 3)) # 0-1 之间均匀分布
randn_tensor = torch.randn((2, 3)) # 标准正态分布
# 指定范围创建张量
range_tensor = torch.arange(0, 10, 2) # [0, 2, 4, 6, 8]
# 指定范围创建张量
range_tensor = torch.arange(0, 10, 2) # [0, 2, 4, 6, 8]
张量运算
PyTorch 的张量支持各种数学运算,包括加减乘除、矩阵乘法、广播机制等:
import torch
a = torch.tensor([[1, 2], [3, 4]], dtype=torch.float32)
b = torch.tensor([[5, 6], [7, 8]], dtype=torch.float32)
# 加法
sum_tensor = a + b #或者torch.add
# 乘法(逐元素)
mul_tensor = a * b #或者torch.mul
# 矩阵乘法
matmul_tensor = torch.matmul(a, b) # 或 a @ b
# 求均值、最大值、最小值
mean_val = torch.mean(a)
max_val = torch.max(a)
min_val = torch.min(a)
形状变换
张量的形状可以通过 .view()
或 .reshape()
进行变换:
import torch
tensor = torch.arange(0, 12)
print(tensor)
reshaped_tensor = tensor.view(3, 4) # 变为 3x4 矩阵
print(reshaped_tensor)
reshaped_tensor_alt = tensor.reshape(4, 3) #变成4x3 矩阵
tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
# 转置
tensor_t = reshaped_tensor.t() # 仅适用于 2D 矩阵
print(tensor_t)
tensor_transposed = reshaped_tensor.permute(1, 0) # 适用于高维张量
print(tensor_transposed)
tensor([[ 0, 4, 8],
[ 1, 5, 9],
[ 2, 6, 10],
[ 3, 7, 11]])
tensor([[ 0, 4, 8],
[ 1, 5, 9],
[ 2, 6, 10],
[ 3, 7, 11]])
# 维度扩展和缩减
unsqueeze_tensor = tensor.unsqueeze(0) # 在第 0 维增加维度
#tensor([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]])
squeeze_tensor = unsqueeze_tensor.squeeze(0) # 移除 0 维
#tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
-
- 自动求导机制:
autograd
的使用及其原理
- 自动求导机制:
PyTorch 的 autograd
模块提供自动求导功能,允许构建计算图并自动计算梯度。
计算图与自动求导
import torch
x = torch.tensor(3.0, requires_grad=True)# 创建张量,requires_grad=True 表示需要计算梯度
y = x ** 2 # 计算 y = x^2 tensor(4., grad_fn=<PowBackward0>)
# 反向传播计算梯度
y.backward() # 计算 dy/dx
print(x.grad) # 输出:6.0
y.backward()就是计算y对x的梯度(求导),结果存在x.gard中。同理可以处理多变量梯度
x = torch.tensor(3.0, requires_grad=True)
y = torch.tensor(4.0, requires_grad=True)
z = x ** 2 + y ** 3 # 计算 z = x^2 + y^3
z.backward() # 计算偏导
print(x.grad) # dz/dx = 2x = 6
print(y.grad) # dz/dy = 3y^2 = 48
在模型推理时,可以使用 torch.no_grad()
来避免计算梯度,提高计算效率:
detach()
截断梯度传播
如果某个张量的梯度不希望影响原始计算图,可以使用 detach()
:
x = torch.tensor(3.0, requires_grad=True)
y = x ** 2
z = y.detach() # z 变为普通张量,不再追踪梯度
print(y.requires_grad) # True
print(z.requires_grad) # False
-
2.2模型构建与训练
- 模型定义(
nn.Module
的编写与使用)
- 模型定义(
在 PyTorch 中,所有神经网络模型都需要继承 nn.Module
,并定义 forward()
方法来指定前向传播的计算逻辑。
import torch
import torch.nn as nn
import torch.optim as optim
# 定义一个简单的前馈神经网络
class SimpleNN(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(SimpleNN, self).__init__()
self.fc1 = nn.Linear(input_size, hidden_size) # 输入层到隐藏层
self.relu = nn.ReLU() # 激活函数
self.fc2 = nn.Linear(hidden_size, output_size) # 隐藏层到输出层
def forward(self, x):
x = self.fc1(x)
x = self.relu(x)
x = self.fc2(x)
return x
# 创建模型实例
model = SimpleNN(input_size=3, hidden_size=5, output_size=2)
print(model)
-
- 前向传播与反向传播流程
前向传播:正如先前提到的,就算数据输入通过网络层逐层计算到输出的过程。
x = torch.tensor([[1.0, 2.0, 3.0]]) # 形状 (1,3)
output = model(x) # 前向传播
print(output) # 输出层结果
反向传播: 反向传播计算梯度,并通过 backward()
自动更新参数。
# 计算损失
criterion = nn.MSELoss() # 均方误差损失
target = torch.tensor([[0.5, 1.5]]) # 真实值
loss = criterion(output, target)
# 反向传播
loss.backward() # 计算梯度
# 查看某个参数的梯度
print(model.fc1.weight.grad)
-
- 模型训练流程:前向、损失计算、反向传播、优化更新
训练模型的完整流程包括:(以下四步算一次迭代epoch)
-
前向传播:计算模型的预测值,是训练的基础。
-
计算损失:评估模型的性能,为优化提供目标。
-
反向传播:计算梯度,指明参数更新的方向。
-
优化器更新参数:实际执行参数更新,使模型逐步优化。
# 训练参数
learning_rate = 0.01
optimizer = optim.SGD(model.parameters(), lr=learning_rate) # 随机梯度下降
# 模拟训练 100 轮
for epoch in range(100):
optimizer.zero_grad() # 清空梯度
output = model(x) # 前向传播
loss = criterion(output, target) # 计算损失
loss.backward() # 反向传播
optimizer.step() # 更新参数
if epoch % 10 == 0:
print(f"Epoch {epoch}, Loss: {loss.item()}")
-
2.3数据处理
- 数据集与数据加载器(
Dataset
与DataLoader
)
- 数据集与数据加载器(
深度学习中,数据处理是模型训练的重要环节。在 PyTorch 中,Dataset
负责数据的定义和读取,DataLoader
负责批量加载数据并支持多线程加速。
定义Dataset
import torch
from torch.utils.data import Dataset, DataLoader
# 自定义数据集
class MyDataset(Dataset):
def __init__(self):
self.data = torch.randn(100, 3) # 100 个样本,每个 3 维
self.labels = torch.randint(0, 2, (100,)) # 100 个二分类标签
def __len__(self):
return len(self.data)
def __getitem__(self, index):
return self.data[index], self.labels[index]
# 创建数据集实例
dataset = MyDataset()
print(f"数据集大小: {len(dataset)}")
print(f"样本数据: {dataset[0]}")
DataLoader
用于批量加载数据,并支持多线程(num_workers
)和打乱顺序(shuffle
)。
# 创建 DataLoader
dataloader = DataLoader(dataset, batch_size=8, shuffle=True, num_workers=2)
# 迭代 DataLoader
for batch_idx, (data, labels) in enumerate(dataloader):
print(f"批次 {batch_idx} - 数据形状: {data.shape}, 标签形状: {labels.shape}")
break # 仅展示第一批次
-
- 数据预处理与增强
PyTorch 提供 torchvision.transforms
进行数据预处理,如归一化、随机裁剪等。不过这个多针对于图片,之前的文章可以参考。不再赘述。
-
2.4调试与优化
- 学习率调度器与超参数调优
学习率是干啥的?控制参数更新的步长,影响模型的训练速度、收敛性和稳定性。
一般使用学习率调度器,常用的比如Adam、SGD等
import torch.optim.lr_scheduler as lr_scheduler
# 定义优化器
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
# 定义学习率调度器(StepLR:每 5 轮学习率衰减为原来的 0.1 倍)
scheduler = lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.1)
# 训练过程中更新学习率
for epoch in range(15):
optimizer.step() # 训练步骤
scheduler.step() # 更新学习率
print(f"Epoch {epoch}: Learning Rate = {scheduler.get_last_lr()[0]}")
常见学习率调度策略
调度器 | 作用 |
StepLR | 每 step_size 轮后,学习率乘以 gamma |
ExponentialLR | 学习率按 gamma^epoch 指数衰减 |
ReduceLROnPlateau | 当损失不下降时降低学习率 |
CosineAnnealingLR | 余弦退火策略 |
-
- 模型保存、加载与断点恢复
PyTorch 通过 torch.save()
保存模型权重,torch.load()
加载模型,实现训练中断后恢复。
保存的模型一般是.pth文件,可以再加载。
2.3 断点恢复
如果训练过程中意外中断,可以保存优化器状态、当前 epoch 等信息,便于下次继续训练。