目录
前言
我后面可能会出一个详解版的,这只是一个浅显版的,旨在广度与理解
为了大家好理解我会加入很多的个人理解,希望读者能理性辨别
因为我采用引导式教学,请大家在有耐心的时候看 (不然看爆炸了别怪我 :d)
核心基础 张量
这是pytorch的核心基础,网上有很多,我在这里就不在赘述了
详细看我这篇文章
前情提要
我个人认为,训练ai遵循着 3 步走:定义模型,训练模型,调用模型,我会按这个步骤教大家
关于语言模型
这个很难,所以我会出文章专门讲这个:
[文章](先放着)
定义模型
首先看代码(这里看不看都没关系):
import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.fc1 = nn.Linear(784, 128)
self.fc2 = nn.Linear(128, 10)
def forward(self, x):
x = F.relu(self.fc1(x))
x = self.fc2(x)
return x
这是一个很简单的模型,我们来逐步逐步分析
Linear函数(泛指模型结构函数)
这个就是市面上常看见的神经网络
的表现结构
看上面的数字784
,128
,10
感觉很可怕
我再说一个例子:
就比如预测房价:你有3
个信息:面积
,房龄
,位置
实际情况下,即使确实是3个信息,也不仅有3层
那么你输入就是3
个东西,现在你只需要1
个数字
那么你就可以得到:
nn.Linear(3,1)
ReLU函数(泛指模型连接函数)
这个函数的具体用法我会在下面的forward讲到
这个函数的用处是过滤没用的信息。。。还是得举个例子:
-
假设你要分类一张图片是否是猫:
输入层:原始像素(比如 [0.2, 0.5, 0.1, …])。 -
提取特征(比如是否有胡须、尖耳朵)。
-
ReLU 会过滤掉不重要的特征,保留重要特征。
-
最终答案:组合这些特征,判断是否是猫。
forward(这个是自己写的函数)
这里就是把linear
连接起来的
记住:层数越多不一定代表越好
一层就用一个relu套一层
就像上面代码那样:
x = F.relu(self.fc1(x))
x = self.fc2(x)
nn.Sequential函数
假如你很懒,不想搞那么多变量、不想一个一个用relu连接起来,你可以使用nn.Sequential,最上面的代码可以改进成:
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
# 用 Sequential 包装层
self.layers = nn.Sequential(
nn.Linear(784, 128), # 第1层:全连接层
nn.ReLU(), # 第2层:激活函数
nn.Linear(128, 10) # 第3层:输出层
)
def forward(self, x):
return self.layers(x)
很显然,他的参数类型是:linear模型
、连接方式
。。。
更多的模型结构函数
1. 模型定义函数(核心层)
模块 | 用途 | 关键参数 | 示例代码 | 适用场景 |
---|---|---|---|---|
nn.Linear | 全连接层(加权求和) | in_features , out_features | nn.Linear(10, 5) | 表格数据、分类/回归 |
nn.Conv2d | 图像卷积(提取局部特征) | in_channels , out_channels , kernel_size | nn.Conv2d(3, 16, 3) | 图像处理(分类、检测) |
nn.LSTM | 处理序列数据(记忆长期依赖) | input_size , hidden_size | nn.LSTM(100, 128) | 文本、时间序列预测 |
nn.Embedding | 将离散符号映射为稠密向量 | num_embeddings , embedding_dim | nn.Embedding(1000, 128) | NLP(词向量表示) |
nn.MaxPool2d | 最大池化(缩小特征图尺寸) | kernel_size | nn.MaxPool2d(2) | 图像分类(降维) |
2. 连接函数(激活与归一化)
模块 | 用途 | 参数 | 示例代码 | 适用场景 |
---|---|---|---|---|
nn.ReLU | 激活函数(过滤负值,保留正值) | 无 | nn.Sequential(nn.Linear(10,5), nn.ReLU()) | 隐藏层默认激活 |
nn.Sigmoid | 压缩输出到 [0,1] (概率) | 无 | 输出层(二分类) | 二分类任务 |
nn.Softmax | 输出概率分布(和为1) | dim (指定维度) | nn.Softmax(dim=1) | 多分类任务(需指定维度) |
nn.Tanh | 压缩输出到 [-1,1] | 无 | 生成任务(如图像像素归一化) | GAN生成器输出层 |
nn.Dropout | 随机丢弃神经元(防过拟合) | p (丢弃概率) | nn.Dropout(0.5) | 隐藏层(正则化) |
到后面,我会再出一期,专门谈谈这个
连接:python pytorch 模型构造函数、连接函数 通俗版
因为最近压力大,所以这些都不会写很细
训练模型
还是先上代码(这里只写了最重点的模型循环训练)仅模版:
train_data = ... # 你的训练数据
dataset = Dataset(train_data) # 转换(这个需手写)
train_loader = DataLoader(dataset, batch_size=2, shuffle=True)
model = SomeModel() # SomeModel => 替换成你写的模型
criterion = torch.nn.MSELoss() # 回归任务用均方误差
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
# 核心:循环训练
num_epochs = 100
for epoch in range(num_epochs):
total_loss = 0
for inputs, labels in train_loader:
# 前向传播:模型尝试计算和
preds = model(inputs)
# 计算误差
loss = criterion(preds, labels)
# 反向传播与优化
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_loss += loss.item()
# 打印平均损失
avg_loss = total_loss / len(train_loader)
print(f"Epoch {epoch+1}, Loss: {avg_loss:.4f}")
训练循环
训练循环分为 3 大步与 1 小步
下面以“学生做题并订正”为例
学前测
先让你看看,你对这一部分了解得怎么样,后续再为你的错误,进行改进
代码:
preds = model(inputs)
老师批改
接下来,老师就要批改卷子,看看那里没有掌握
这里主要的工作是:检查那里没有掌握,为后面制定个性化培优
这里的 检查函数 用的是 损失函数
,后面会讲
代码:
loss = criterion(preds, labels)
# 这里 criterion 的定义在这里
# criterion = torch.nn.MSELoss() # 没错!MSELoss就是损失函数
分析、学习
这部分先给代码,我们一步一步讲:
# 定义: optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
# 他就是 优化器
optimizer.zero_grad()
loss.backward()
optimizer.step()
optimizer.zero_grad()
老师批改好试卷后,你得要在错的基础上优化
从而得到正确答案
loss.backward()
学完以后,分析错在哪里,重新整理思路
optimizer.step()
运用在现实中(吸收正确答案),做出行动
记录成绩、查看进步空间
你得要给我看出你的进步,所以记录下来,并输出
太简单,就不必说了
收集数据
我们从头开始讲起
例如:我们要做一个模型,功能是:输入两个数输出一个数,表示它们的和
我们的训练列表是这样的:
train_data = [((a,b),它们的和),...]
我们的Dataset
就可以这么写:
class Dataset(Dataset):
def __init__(self, data):
# 提取输入部分:将 (in1, in2) 转为张量
self.inputs = torch.tensor(
[[in1, in2] for ((in1, in2), _) in data],
dtype=torch.float32
)
# 提取输出部分:将 (out,) 转为张量(支持多输出)
self.outputs = torch.tensor(
[out_tuple for (_, out_tuple) in data],
dtype=torch.float32
)
def __len__(self):
return len(self.inputs)
def __getitem__(self, idx):
# 返回格式:(输入张量, 输出张量)
return self.inputs[idx], self.outputs[idx]
__init__函数
- 数组
- 这里面的都要是
torch.tensor
类型的
- 这里面的都要是
- inputs列表
- 这里就是要修改的地方了,这里是输入数据集,把你的
data
提取出输入信息
- 这里就是要修改的地方了,这里是输入数据集,把你的
- outputs列表
- 这里就是输出的列表(就是我们上面举例的“学生写的正确答案”),也是把
data
里的输出结果提取出来
- 这里就是输出的列表(就是我们上面举例的“学生写的正确答案”),也是把
剩下两个函数
这些就是这样的了,一个是调用len()
一个是调用[]
(取搜引),基本不用动
损失器与优化器
先给一个表,后面我会出文章,专门讲这个
优化器 | 关键参数 | 调整建议 | 适用场景 | 注意事项 |
---|---|---|---|---|
SGD | lr (学习率) | 从 0.1 开始尝试,逐步缩小(如0.01→0.001) | 简单任务、精细调参 | 太大→震荡;太小→收敛慢 |
momentum (动量) | 通常设为 0.9 ,模拟物理惯性 | 配合大学习率使用 | 避免与Adam同时用 | |
Adam | lr | 默认 0.001 通常有效,复杂任务可尝试 0.0001 | 绝大多数任务默认选择 | 资源消耗略高 |
weight_decay | 正则化强度,常用 1e-4 | 防止过拟合 | 太大导致欠拟合 | |
RMSprop | lr | 类似Adam,从 0.001 开始 | RNN/LSTM等循环网络 | 对学习率敏感 |
alpha | 衰减率,默认 0.99 ,调整范围 0.9~0.999 | 处理非平稳目标 | 值越大历史影响越久 | |
Adagrad | lr | 初始值需较大(如 0.1 ),因会自动衰减 | 稀疏数据(如推荐系统) | 后期学习率趋近于0 |
AdamW | lr | 类似Adam,但更稳定(推荐 0.001 ) | 搭配权重衰减正则化 | 比Adam更现代 |
betas | 动量参数,默认 (0.9, 0.999) 通常不需改 | 需要稳定训练时 | 调整需谨慎 |
使用模型
保存&加载
终于做好了,我想要直接保存这个模型怎么办呢?
可以直接用torch.save(model, [保存目录])
要用的时候就可以直接使用loaded_model = torch.load([保存目录])
来加载模型了
调用(推理模型)
我们可以先加载模型model
就可以这样:
with torch.no_grad(): # 关闭梯度计算加速推理
input_tensor = torch.tensor([[5.0, 3.0]]) # 输入必须是张量
prediction = model(input_tensor) # 输出也是张量
print(f"5+3预测值:{prediction.tolist()}") # 输出
这里的输出prediction
也是一个张量
后语
这篇文章看下来你已经完全入门 pytorch 了
这篇文章写了差不多有 3 个月,坚持做免费栏目很难,希望大家可以多多支持
接下来我会出两篇文章,都是实战篇:
- a+b模型:[暂时没做]()
- 图片识别模型(这个工程量很大,所以我会考虑付费):[暂时没做]()