深度学习 PyTorch 代码全集
·
深度学习 PyTorch 代码全集
目录
- PyTorch 安装与验证
- 张量(Tensor)创建
- 张量转换
- 张量数值计算
- 张量统计运算
- 张量索引操作
- 张量形状操作
- 张量拼接
- 神经网络基础
- 损失函数
- 数据集与数据加载器
- 自动微分与反向传播
- 完整模型训练流程
- 优化器与学习率调度
- 参数初始化
1. PyTorch 安装与验证
# 导入PyTorch库
import torch
# 打印PyTorch版本号
print(torch.__version__)
# Windows系统:检查CUDA GPU是否可用
print(torch.cuda.is_available())
# Apple M系列芯片:检查MPS加速是否可用
print(torch.backends.mps.is_available())
2. 张量(Tensor)创建
2.1 基于内容创建张量
import torch
import numpy as np
# 1. 创建标量张量(0维)
scalar1 = torch.tensor(10) # 传入单个数字创建标量
scalar2 = torch.tensor(3.14)
print("标量张量1:", scalar1)
print("张量维度:", scalar1.dim()) # 输出0,表示0维
print("张量形状:", scalar1.shape) # 输出torch.Size([]),表示无维度
# 2. 创建一维张量(向量)
vec1 = torch.tensor([1, 2, 3, 4]) # 传入单层列表创建一维张量
vec2 = torch.tensor([0.1, 0.2, 0.3])
print("一维张量1:", vec1)
print("张量维度:", vec1.dim()) # 输出1,表示1维
print("张量形状:", vec1.shape) # 输出torch.Size([4]),表示4个元素
# 3. 创建二维张量(矩阵)
t1 = torch.tensor([[1, 2, 3], [10, 20, 30]]) # 传入二维嵌套列表创建二维张量
print(t1)
print(t1.shape) # 输出torch.Size([2, 3]),表示2行3列
# 4. 创建三维张量
t1 = torch.tensor([[[1,2,3], [4,5,6]], [[7,8,9], [10,11,12]]]) # 传入三层嵌套列表
print(t1)
print(t1.shape) # 输出torch.Size([2, 2, 3])
# 5. 基于NumPy数组创建张量
t1 = torch.tensor(np.array([10, 20, 30])) # 将NumPy数组转换为张量(创建副本)
t2 = torch.from_numpy(np.array([10, 20, 30])) # 共享内存,修改原数组会影响张量
print(t1)
print(t1.shape)
2.2 基于形状创建张量
# 基于形状创建张量(默认float32类型)
t1 = torch.Tensor(2, 3, 5) # 创建2×3×5的三维张量,元素未初始化
print(t1)
print(t1.shape) # 输出torch.Size([2, 3, 5])
2.3 创建指定类型的张量
# 方法1:通过dtype参数指定类型
t1 = torch.tensor([[1, 2, 3], [4, 5, 6]], dtype=torch.float64)
print(t1.dtype) # 输出torch.float64
# 方法2:使用特定类型的构造函数
t1 = torch.IntTensor(2, 3) # int32类型
t1 = torch.LongTensor(2, 3) # int64类型
t1 = torch.FloatTensor(2, 3) # float32类型
t1 = torch.DoubleTensor(2, 3) # float64类型
t1 = torch.BoolTensor(2, 3) # bool类型
t1 = torch.ByteTensor(2, 3) # uint8类型
t1 = torch.HalfTensor(2, 3) # float16类型
2.4 根据数据区间创建张量
# 1. 固定步长生成:torch.arange
t1 = torch.arange(10) # 生成[0,10)的整数,步长1
print(t1)
t1 = torch.arange(2, 10, 2) # 生成[2,10)的整数,步长2
print(t1)
# 2. 固定数量线性生成:torch.linspace
t1 = torch.linspace(2, 10, 6) # 在[2,10]之间生成6个均匀间隔的数
print(t1)
# 3. 对数间隔生成:torch.logspace
t1 = torch.logspace(1, 3, 3) # 生成10^1, 10^2, 10^3
print(t1)
t1 = torch.logspace(1, 3, 3, base=np.e) # 以e为底生成e^1, e^2, e^3
print(t1)
2.5 根据填充创建张量
# 1. 全1张量
t1 = torch.ones(3) # 创建长度为3的全1一维张量
t1 = torch.ones_like(t1) # 创建与t1形状相同的全1张量
print(t1)
# 2. 未初始化张量(速度最快,但值随机)
t1 = torch.empty(3)
print(t1)
# 3. 全常量张量
t1 = torch.full((2, 3), 10) # 创建2×3的张量,所有元素为10
print(t1)
# 4. 单位矩阵
t1 = torch.eye(3) # 创建3×3的单位矩阵
t1 = torch.eye(5, 6) # 创建5×6的矩阵,对角线为1
print(t1)
2.6 随机创建张量
# 1. [0,1)均匀分布
t2 = torch.rand(2, 3)
print(t2)
# 2. 整数均匀分布
t2 = torch.randint(1, 100, size=(2, 3)) # [1,100)之间的整数
print(t2)
# 3. 标准正态分布(均值0,方差1)
t2 = torch.randn(2, 3)
print(t2)
# 4. 自定义均值和标准差的正态分布
t2 = torch.normal(5, 2, size=(2, 3)) # 均值5,标准差2
print(t2)
# 5. 随机打乱(洗牌)
t2 = torch.randperm(10) # 生成[0,10)的随机排列
print(t2)
# 6. 设置随机种子(保证实验可复现)
torch.manual_seed(42)
seed = torch.random.initial_seed()
print(seed)
3. 张量转换
3.1 元素类型转换
# 初始化一个int64类型的张量
t1 = torch.tensor([1, 2, 3])
print("初始类型:", t1.dtype)
# 方式1:type()方法
t1 = t1.type(torch.float32)
print(t1.dtype)
# 方式2:to()方法(推荐,功能更全面)
t1 = t1.to(torch.int32)
print(t1.dtype)
# 方式3:直接调用类型方法
t1 = t1.float() # 转换为float32
print(t1.dtype)
3.2 Tensor 与 NumPy ndarray 转换
# 1. Tensor → NumPy
t1 = torch.tensor([1, 2, 3])
a1 = t1.numpy() # 默认共享内存,修改t1会影响a1
print(type(a1))
# 避免内存共享:深拷贝
a2 = t1.numpy().copy()
t1[0] = 100
print(t1)
print(a2) # a2不受影响
# 2. NumPy → Tensor
a1 = np.array([1, 2, 3])
t1 = torch.from_numpy(a1) # 默认共享内存
print(type(t1))
# 避免内存共享:clone()
t1 = torch.from_numpy(a1).clone()
3.3 Tensor → 标量(Scalar)
t1 = torch.tensor(10)
t2 = torch.tensor([10])
t3 = torch.tensor([[10]])
# 只有当张量只有一个元素时才能调用item()
print(t1.item()) # 输出10(Python原生int类型)
print(t2.item())
print(t3.item())
4. 张量数值计算
4.1 基本运算(张量与标量)
import torch
# 初始化2×3张量
t1 = torch.tensor([[1, 2, 3], [4, 5, 6]])
# 1. 运算符重载(非原地操作,不修改原张量)
print(t1 + 10) # 每个元素加10
print(t1 - 10) # 每个元素减10
print(t1 * 10) # 每个元素乘10
print(t1 / 10) # 每个元素除10
print(t1 ** 2) # 每个元素平方
print(-t1) # 每个元素取反
# 2. 非原地方法(与运算符等价)
print(t1.add(10))
print(t1.sub(10))
print(t1.mul(10))
print(t1.div(10))
print(t1.pow(2))
print(t1.neg())
# 3. 原地方法(修改原张量,以下划线结尾)
t1.add_(10) # 直接修改t1,每个元素加10
print(t1)
4.2 元素级运算(张量与张量)
# 初始化两个形状相同的2×3张量
t1 = torch.tensor([[1, 2, 3], [4, 5, 6]])
t2 = torch.tensor([[10, 20, 30], [40, 50, 60]])
# 逐元素相加
print(t1 + t2)
# 逐元素相乘(哈达玛积,不是矩阵乘法)
print(t1 * t2)
# 逐元素相除
print(t1 / t2)
4.3 矩阵相乘
# 初始化二维矩阵
t1 = torch.tensor([[1, 2, 3], [4, 5, 6]]) # 形状(2,3)
t2 = torch.tensor([[10, 20, 30, 40], [40, 50, 60, 70], [40, 50, 60, 70]]) # 形状(3,4)
# 方式1:运算符@(推荐,简洁)
print(t1 @ t2) # 输出形状(2,4)
# 方式2:mm()方法(仅支持二维矩阵)
print(t1.mm(t2))
# 方式3:matmul()方法(支持任意维度,批量矩阵乘法)
print(t1.matmul(t2))
5. 张量统计运算
import torch
# 生成形状为(2,3,4)的随机整数张量
t1 = torch.randint(1, 10, (2, 3, 4))
print("原始张量:\n", t1)
# 1. 求和运算
print("全局求和:", t1.sum()) # 所有元素相加,返回标量
print("按dim=0求和:\n", t1.sum(dim=0)) # 压缩第0维,输出形状(3,4)
print("按dim=1求和:\n", t1.sum(dim=1)) # 压缩第1维,输出形状(2,4)
print("按dim=2求和:\n", t1.sum(dim=2)) # 压缩第2维,输出形状(2,3)
# 2. 均值运算(仅支持浮点型)
print("按dim=0求均值:\n", t1.float().mean(dim=0))
# 3. 最值运算(返回值和索引)
max_val, max_idx = t1.float().max(dim=1)
print("最大值:\n", max_val)
print("最大值索引:\n", max_idx)
# 4. 方差与标准差
print("按dim=1求方差:\n", t1.float().var(dim=1))
print("按dim=1求标准差:\n", t1.float().std(dim=1))
# 5. 去重运算
print("元素去重:\n", t1.float().unique())
# 6. 排序运算
sorted_val, sorted_idx = t1.float().sort(dim=2)
print("排序后的值:\n", sorted_val)
print("排序索引:\n", sorted_idx)
6. 张量索引操作
import torch
# 生成形状为(2,5,4)的随机整数张量
t = torch.randint(0, 10, (2, 5, 4))
print("原始张量:\n", t)
# 1. 简单索引
print(t[0][0][0]) # 链式索引
print(t[0, 0, 0]) # 逗号分隔索引(推荐)
print(t[1]) # 取第1个矩阵,输出形状(5,4)
print(t[1, 2]) # 取第1个矩阵第2行,输出形状(4)
# 2. 范围索引(切片)
print(t[1, 1:]) # 取第1个矩阵从第1行到末尾
print(t[-1:, 1:4, 0:3:2]) # 复杂切片
# 3. 列表索引(提取非连续元素)
list1 = [0, 1, 1]
list2 = [1, 3, 2]
print(t[list1, list2]) # 提取(0,1),(1,3),(1,2)位置的行
# 4. 布尔索引
print(t[t > 5]) # 取出所有大于5的值
mask = t[:, :, 0] > 5 # 每行首元素大于5的行
print(t[mask])
7. 张量形状操作
import torch
# 创建形状为(3,2,6)的三维张量
t1 = torch.randint(1, 10, (3, 2, 6))
print("原始形状:", t1.shape)
# 1. 维度交换
print("转置所有维度:", t1.T.shape) # 反转所有维度
print("只转置最后两个维度:", t1.mT.shape) # 矩阵转置
print("交换0和1维:", t1.transpose(0, 1).shape)
print("重新排列所有维度:", t1.permute(1, 0, 2).shape)
# 2. 调整形状
print("展平为一维:", t1.reshape(36).shape)
print("调整为(3,1,-1):", t1.reshape(3, 1, -1).shape) # -1自动推导维度
# 3. 增删维度
t2 = torch.randint(1, 10, (2, 4))
print("原始形状:", t2.shape)
print("增加维度dim=2:", t2.unsqueeze(dim=2).shape) # 增加维度
t3 = t2.unsqueeze(dim=0)
print("删除维度:", t3.squeeze().shape) # 删除所有大小为1的维度
8. 张量拼接
import torch
# 1. torch.cat():按指定维度拼接(维度不变)
t1 = torch.randint(1, 10, (2, 1, 3))
t2 = torch.randint(1, 10, (2, 3, 3))
print("cat拼接结果形状:", torch.cat([t1, t2], dim=1).shape) # 输出(2,4,3)
# 2. torch.stack():堆叠操作(新增维度)
t1 = torch.randint(1, 10, (3, 4, 5))
t2 = torch.randint(1, 10, (3, 4, 5))
print("stack堆叠结果形状:", torch.stack([t1, t2], dim=0).shape) # 输出(2,3,4,5)
9. 神经网络基础
9.1 全连接层
import torch
import torch.nn as nn
# 定义全连接层:2个输入神经元,3个输出神经元
linear = nn.Linear(in_features=2, out_features=3, bias=True)
# 查看权重和偏置形状
print("权重形状:", linear.weight.shape) # 输出torch.Size([3, 2])
print("偏置形状:", linear.bias.shape) # 输出torch.Size([3])
# 构造输入数据:2个样本,每个样本2个特征
x = torch.tensor([[1.0, 2.0], [3.0, 4.0]])
# 前向传播(自动调用forward方法)
y = linear(x)
print("输出形状:", y.shape) # 输出torch.Size([2, 3])
9.2 激活函数
import torch
import torch.nn as nn
x = torch.tensor([0.7, -1.2, 2.5, 0, -3.1])
# 1. Sigmoid函数(二分类输出层)
print(torch.sigmoid(x))
# 2. Tanh函数
print(torch.tanh(x))
# 3. ReLU函数(隐藏层首选)
print(torch.relu(x))
# 4. Softmax函数(多分类输出层)
print(torch.softmax(x, dim=0))
# 5. 其他激活函数
print(nn.LeakyReLU(0.01)(x)) # LeakyReLU
print(nn.GELU()(x)) # GELU(Transformer默认)
9.3 自定义模型
import torch
import torch.nn as nn
# 自定义模型必须继承nn.Module
class MyModule(nn.Module):
def __init__(self):
super().__init__() # 必须调用父类初始化方法
# 定义网络层
self.linear1 = nn.Linear(3, 4) # 输入层→第1隐藏层
self.linear2 = nn.Linear(4, 4) # 第1隐藏层→第2隐藏层
self.out = nn.Linear(4, 2) # 第2隐藏层→输出层
# 必须实现forward方法,定义前向传播逻辑
def forward(self, x):
x = self.linear1(x)
x = torch.tanh(x)
x = self.linear2(x)
x = torch.relu(x)
x = self.out(x)
y = torch.softmax(x, dim=-1)
return y
# 测试模型
if __name__ == '__main__':
x = torch.randn(10, 3) # 10个样本,每个3个特征
model = MyModule()
y = model(x)
print("输出形状:", y.shape) # 输出torch.Size([10, 2])
9.4 使用 Sequential 定义模型
import torch
import torch.nn as nn
# 对于纯顺序结构的网络,使用Sequential更简洁
model = nn.Sequential(
nn.Linear(3, 4),
nn.Tanh(),
nn.Linear(4, 4),
nn.ReLU(),
nn.Linear(4, 2),
nn.Softmax(dim=-1)
)
# 测试
x = torch.randn(10, 3)
y = model(x)
print("输出形状:", y.shape)
9.5 模型保存与加载
import torch
import torch.nn as nn
# 定义模型
model = nn.Sequential(
nn.Linear(3, 4),
nn.Tanh(),
nn.Linear(4, 4),
nn.ReLU(),
nn.Linear(4, 2),
nn.Softmax(dim=-1)
)
# 保存模型(只保存参数,推荐)
torch.save(model.state_dict(), 'model.pth')
# 加载模型
loaded_model = nn.Sequential(
nn.Linear(3, 4),
nn.Tanh(),
nn.Linear(4, 4),
nn.ReLU(),
nn.Linear(4, 2),
nn.Softmax(dim=-1)
)
state_dict = torch.load('model.pth')
loaded_model.load_state_dict(state_dict)
# 验证
x = torch.randn(10, 3)
print(torch.allclose(model(x), loaded_model(x))) # 输出True
10. 损失函数
import torch
import torch.nn as nn
# 1. MAE损失(L1损失)
output = torch.randn(5)
target = torch.randn(5)
loss_l1 = nn.L1Loss()
loss = loss_l1(output, target)
print("MAE损失:", loss)
# 2. MSE损失(L2损失)
loss_l2 = nn.MSELoss()
loss = loss_l2(output, target)
print("MSE损失:", loss)
# 3. Smooth L1损失
loss_smooth_l1 = nn.SmoothL1Loss()
loss = loss_smooth_l1(output, target)
print("Smooth L1损失:", loss)
# 4. 二元交叉熵损失
output = torch.randn(5)
proba = torch.sigmoid(output)
target = torch.tensor([0, 0, 1, 1, 0]).float()
loss_bce = nn.BCELoss()
loss = loss_bce(proba, target)
print("BCELoss:", loss)
# 5. 带Logits的二元交叉熵(更稳定)
loss_bce_logits = nn.BCEWithLogitsLoss()
loss = loss_bce_logits(output, target)
print("BCEWithLogitsLoss:", loss)
# 6. 交叉熵损失(多分类)
output = torch.randn(8, 6) # 8个样本,6个类别
target = torch.tensor([1, 0, 5, 4, 2, 3, 0, 5]) # 标签编码
loss_ce = nn.CrossEntropyLoss()
loss = loss_ce(output, target)
print("CrossEntropyLoss:", loss)
11. 数据集与数据加载器
11.1 自定义 Dataset
from torch.utils.data import Dataset
# 自定义Dataset必须继承Dataset
class MyDataset(Dataset):
def __init__(self, data):
self.data = data # 初始化数据
def __len__(self):
return len(self.data) # 返回数据集大小
def __getitem__(self, idx):
return self.data[idx] # 按索引返回单条数据
# 使用示例
data = [1, 2, 3, 4]
dataset = MyDataset(data)
print(dataset[0]) # 输出1
print(len(dataset)) # 输出4
11.2 TensorDataset
import torch
from torch.utils.data import TensorDataset, DataLoader
# 创建特征和标签张量
x = torch.randn(10, 3)
y = torch.randn(10)
# 构建TensorDataset
dataset = TensorDataset(x, y)
print(dataset[0]) # 输出第一个样本的特征和标签
11.3 DataLoader
# 创建数据加载器
loader = DataLoader(
dataset,
batch_size=3, # 每个批次大小
shuffle=True, # 每个epoch打乱数据
drop_last=False # 是否丢弃最后一个不完整的批次
)
# 遍历数据
for x_batch, y_batch in loader:
print(x_batch, y_batch)
print("-------")
12. 自动微分与反向传播
import torch
import torch.nn as nn
# 定义数据
x = torch.tensor([10.0])
y = torch.tensor([3.0])
# 定义需要求导的参数(requires_grad=True)
w = torch.randn(1, requires_grad=True)
b = torch.randn(1, requires_grad=True)
# 前向传播
z = w * x + b
z.retain_grad() # 保留非叶子节点的梯度
print("前向传播结果:", z)
# 计算损失
loss_fn = nn.MSELoss()
loss = loss_fn(z, y)
loss.retain_grad()
print("损失值:", loss)
# 反向传播:计算所有参数的梯度
loss.backward()
# 查看梯度
print("损失的梯度:", loss.grad)
print("z的梯度:", z.grad)
print("w的梯度:", w.grad)
print("b的梯度:", b.grad)
# 查看是否为叶子节点
print("w是叶子节点:", w.is_leaf)
print("z是叶子节点:", z.is_leaf)
13. 完整模型训练流程
13.1 线性回归示例
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import TensorDataset, DataLoader
import matplotlib.pyplot as plt
# 1. 准备数据
x = torch.randn(100, 1) # 100个样本,1个特征
y = x * 2.5 + 5.0 + torch.randn(100, 1) * 0.2 # 真实关系:y=2.5x+5+噪声
# 超参数
batch_size = 6
lr = 0.01
epochs = 200
# 2. 构建数据集和数据加载器
dataset = TensorDataset(x, y)
dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True)
# 3. 定义模型:单层线性层
model = nn.Linear(1, 1)
# 4. 定义损失函数和优化器
loss_fn = nn.MSELoss()
optimizer = optim.SGD(model.parameters(), lr=lr)
# 5. 训练模型
loss_list = []
for epoch in range(epochs):
total_loss = 0
iter_num = 0
for x_batch, y_batch in dataloader:
# 前向传播
y_pred = model(x_batch)
# 计算损失
loss = loss_fn(y_pred, y_batch)
# 反向传播
loss.backward()
# 更新参数
optimizer.step()
# 梯度清零(必须,否则梯度会累加)
optimizer.zero_grad()
total_loss += loss.item()
iter_num += 1
# 记录每轮平均损失
avg_loss = total_loss / iter_num
loss_list.append(avg_loss)
if (epoch+1) % 20 == 0:
print(f"Epoch {epoch+1}/{epochs}, Loss: {avg_loss:.4f}")
# 打印训练后的参数
print("训练后的斜率:", model.weight.item()) # 接近2.5
print("训练后的偏置:", model.bias.item()) # 接近5.0
# 画图
fig, axs = plt.subplots(1, 2, figsize=(12, 4))
axs[0].plot(loss_list)
axs[0].set_title('Loss Curve')
axs[1].scatter(x, y)
axs[1].plot(x, model(x).detach().numpy(), c='r')
axs[1].set_title('Fitting Result')
plt.show()
13.2 手写数字识别完整训练
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import TensorDataset, DataLoader
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
# 0. 定义超参数
lr = 0.1
epochs = 20
batch_size = 256
# 1. 加载和预处理数据
def get_digit_data():
dataset = pd.read_csv("./data/train.csv")
x = dataset.drop("label", axis=1)
y = dataset["label"]
# 划分训练集和测试集
x_train, x_test, y_train, y_test = train_test_split(
x, y, test_size=0.2, random_state=42
)
# 归一化到[0,1]
scaler = MinMaxScaler()
x_train = scaler.fit_transform(x_train)
x_test = scaler.transform(x_test)
# 转换为张量
x_train = torch.tensor(x_train).float()
x_test = torch.tensor(x_test).float()
y_train = torch.tensor(y_train.to_numpy()).long()
y_test = torch.tensor(y_test.to_numpy()).long()
return x_train, x_test, y_train, y_test
x_train, x_test, y_train, y_test = get_digit_data()
# 2. 构建数据集和数据加载器
train_dataset = TensorDataset(x_train, y_train)
train_dataloader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
valid_dataset = TensorDataset(x_test, y_test)
valid_dataloader = DataLoader(valid_dataset, batch_size=batch_size)
# 3. 定义模型
model = nn.Sequential(
nn.Linear(784, 50),
nn.ReLU(),
nn.Linear(50, 100),
nn.ReLU(),
nn.Linear(100, 10)
)
# 定义设备(自动选择GPU/CPU)
device = torch.device(
"cuda" if torch.cuda.is_available()
else "mps" if torch.backends.mps.is_available()
else "cpu"
)
model.to(device)
print(f"使用设备: {device}")
# 4. 定义损失函数和优化器
loss_fn = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=lr)
# 5. 训练模型
for epoch in range(epochs):
# 训练模式
model.train()
train_loss = 0
train_acc_num = 0
for inputs, targets in train_dataloader:
inputs = inputs.to(device)
targets = targets.to(device)
# 前向传播
y_pred = model(inputs)
# 计算损失
loss = loss_fn(y_pred, targets)
# 反向传播
loss.backward()
# 更新参数
optimizer.step()
# 梯度清零
optimizer.zero_grad()
train_loss += loss.item() * inputs.shape[0]
y_pred_class = torch.argmax(y_pred, dim=1)
train_acc_num += torch.sum(y_pred_class == targets).item()
# 计算训练指标
train_loss_avg = train_loss / len(train_dataset)
train_acc = train_acc_num / len(train_dataset)
# 验证模式
model.eval()
val_loss = 0
val_acc_num = 0
with torch.no_grad(): # 验证时不需要计算梯度
for inputs, targets in valid_dataloader:
inputs = inputs.to(device)
targets = targets.to(device)
y_pred = model(inputs)
loss = loss_fn(y_pred, targets)
val_loss += loss.item() * inputs.shape[0]
y_pred_class = torch.argmax(y_pred, dim=1)
val_acc_num += torch.sum(y_pred_class == targets).item()
val_loss_avg = val_loss / len(valid_dataset)
val_acc = val_acc_num / len(valid_dataset)
# 打印结果
print(f'第{epoch+1}轮, 训练损失: {train_loss_avg:.4f}, 训练准确率: {train_acc:.4f}, '
f'验证损失: {val_loss_avg:.4f}, 验证准确率: {val_acc:.4f}')
14. 优化器与学习率调度
14.1 动量法
import torch
import torch.optim as optim
# 定义参数
w = torch.tensor([-7.0, 2.0], requires_grad=True)
# 普通SGD
optimizer_sgd = optim.SGD([w], lr=0.01)
# 带动量的SGD(momentum=0.9)
optimizer_momentum = optim.SGD([w], lr=0.01, momentum=0.9)
14.2 学习率调度
import torch
import torch.optim as optim
from torch.optim.lr_scheduler import StepLR, MultiStepLR, ExponentialLR
# 定义参数和优化器
w = torch.tensor([-7.0, 2.0], requires_grad=True)
optimizer = optim.SGD([w], lr=0.9)
# 1. 等间隔衰减:每10个epoch衰减为原来的0.7
scheduler_step = StepLR(optimizer, step_size=10, gamma=0.7)
# 2. 指定间隔衰减:在[10,20,70]epoch时衰减
scheduler_multi = MultiStepLR(optimizer, milestones=[10, 20, 70], gamma=0.7)
# 3. 指数衰减:每个epoch乘以0.99
scheduler_exp = ExponentialLR(optimizer, gamma=0.99)
# 训练循环中更新学习率
for epoch in range(100):
# ... 训练步骤 ...
optimizer.step()
optimizer.zero_grad()
scheduler_step.step() # 更新学习率
14.3 其他优化器
import torch
import torch.optim as optim
w = torch.tensor([-7.0, 2.0], requires_grad=True)
# AdaGrad
optimizer_adagrad = optim.Adagrad([w], lr=0.9)
# RMSProp
optimizer_rmsprop = optim.RMSprop([w], lr=0.1, alpha=0.99)
# Adam(最常用)
optimizer_adam = optim.Adam([w], lr=0.1, betas=(0.9, 0.999))
15. 参数初始化
import torch
import torch.nn as nn
linear = nn.Linear(5, 2)
# 1. 常数初始化
nn.init.zeros_(linear.weight) # 全部初始化为0
nn.init.ones_(linear.weight) # 全部初始化为1
nn.init.constant_(linear.weight, 10) # 全部初始化为10
# 2. 单位矩阵初始化
nn.init.eye_(linear.weight)
# 3. 正态分布初始化
nn.init.normal_(linear.weight, mean=0.0, std=1.0)
# 4. 均匀分布初始化
nn.init.uniform_(linear.weight, a=0, b=10)
# 5. Xavier初始化(适用于Sigmoid/Tanh)
nn.init.xavier_normal_(linear.weight) # 正态分布
nn.init.xavier_uniform_(linear.weight) # 均匀分布
# 6. He初始化(适用于ReLU及其变体)
nn.init.kaiming_normal_(linear.weight) # 正态分布
nn.init.kaiming_uniform_(linear.weight) # 均匀分布
更多推荐


所有评论(0)