本文主要参考沐神的视频教程 https://www.bilibili.com/video/BV1PX4y1g7KC/?p=4&spm_id_from=pageDriver&vd_source=c7bfc6ce0ea0cbe43aa288ba2713e56d
文档教程 https://zh-v2.d2l.ai/
本文的主要内容对沐神提供的代码中个人不太理解的内容进行笔记记录,内容不会特别严谨仅供参考。
1.函数目录
python | 位置 |
---|---|
* 和 ** | 2.2 |
iter 和 next | 2.2 |
torch.utils.data 是 PyTorch 中专门用于数据加载和处理的模块。它提供了一系列工具和类,用于处理和加载数据集,包括自定义数据集的创建、数据集的变换以及数据的批量加载等功能。
主要组成部分
- Dataset: 抽象类,用于表示数据集。
- TensorDataset: 简单的封装数据集类,用于将特征和标签打包成数据集。
- DataLoader: 数据加载器,用于将数据集分批次加载,并提供多线程数据加载等功能。
- Sampler: 用于定义数据集的采样策略。
torch.utils.data | 位置 |
---|---|
Tensordataset | 2.2 |
DataLoader | 2.2 |
torch.nn 是 PyTorch 中的一个核心模块,专门用于构建神经网络。它提供了许多构建神经网络的基本组件,如层(layers)、损失函数(loss functions)、激活函数(activation functions)、容器(containers)等。
主要组成部分
- Modules(模块):包括各种神经网络层。
- Containers(容器):用于将多个层组合在一起。
- Functional API:一些不带参数的函数,比如激活函数、池化操作等。
- Loss Functions:用于定义不同的损失函数。
- Initialization:用于参数初始化的函数。
torch.nn | 位置 |
---|---|
nn.Linear | 2.3 |
nn.Sequential | 2.3 |
nn.MSEloss | 2.5 |
Tensor | 位置 |
---|---|
Tensor.normal_ | 2.4 |
Tensor.fill_ | 2.4 |
torch.optim 模块提供了多种优化算法,通过实例化优化器并传入模型参数和学习率等超参数,能够方便地进行模型训练。使用优化器进行训练时,需要在每个训练步骤中计算损失、反向传播、更新参数并清零梯度。常用的优化器包括 SGD、Adam、RMSprop 等。
torch.optim | 位置 |
---|---|
SGD | 2.6 |
2. 线性回归的简介实现
2.1 生成数据集
import numpy as np
import torch
from torch.utils import data
from d2l import torch as d2l
# 1.生成数据
true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = d2l.synthetic_data(true_w, true_b, 1000)
2.2 读取数据集
2.2.1 TensorDataset
- 作用:TensorDataset 的主要作用是将多个张量封装在一起,使它们可以作为一个数据集来进行迭代。它将每个张量的第一个维度视为数据样本数,并假设所有张量的第一个维度长度相同。
- 用法
import torch
from torch.utils.data import TensorDataset, DataLoader
# 1. 创建数据张量
features = torch.tensor([[1, 2], [3, 4], [5, 6], [7, 8]], dtype=torch.float32)
labels = torch.tensor([1, 2, 3, 4], dtype=torch.float32)
# 2. 创建 TensorDataset 实例
dataset = TensorDataset(features, labels)
# 3. 使用 DataLoader 来迭代数据集
batch_size = 2
dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True)
# 4. 迭代数据集
for batch_features, batch_labels in dataloader:
print('Features:', batch_features)
print('Labels:', batch_labels)
Features: tensor([[5., 6.],
[1., 2.]])
Labels: tensor([3., 1.])
Features: tensor([[7., 8.],
[3., 4.]])
Labels: tensor([4., 2.])
2.2.2 * 和 **的作用
在 Python 中,* 和 * * 号用于函数传递参数时有不同的作用,分别用于解包(unpacking)和关键字参数(keyword arguments)。
- *args
- 作用:将可变数量的位置参数传递给函数。
- 使用场景:当你不确定函数需要多少个位置参数时,可以使用 *args 来接受任意数量的位置参数。
# *args 接受了任意数量的位置参数,并将它们作为一个元组传递给函数。
def example_func(*args):
for arg in args:
print(arg)
example_func(1, 2, 3)
- **kwargs
- 作用:将可变数量的关键字参数传递给函数。
- 使用场景:当你不确定函数需要多少个关键字参数时,可以使用 **kwargs 来接受任意数量的关键字参数。
# **kwargs 接受了任意数量的关键字参数,并将它们作为一个字典传递给函数。
def example_func(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
example_func(a=1, b=2, c=3)
3 * 和 ** 用于参数解包
使用 * 解包列表或元组
def example_func(a, b, c):
print(a, b, c)
data = (1, 2, 3)
# *data 将元组 data 解包为位置参数 a=1, b=2, c=3 并传递给函数。
example_func(*data)
使用 ** 解包字典
def example_func(a, b, c):
print(a, b, c)
data = {'a': 1, 'b': 2, 'c': 3}
# **data 将字典 data 解包为关键字参数 a=1, b=2, c=3 并传递给函数。
example_func(**data)
2.2.3 iter和next
iter():将一个可迭代对象(如列表、元组、字典等)转换为迭代器对象。。
next():获取迭代器的下一个元素
# python
my_list = [1, 2, 3, 4]
my_iter = iter(my_list)
print(my_iter) # 输出:<list_iterator object at 0x...>
# 获取迭代器的下一个项目
print(next(my_iter)) # 输出:1
print(next(my_iter)) # 输出:2
print(next(my_iter)) # 输出:3
通过结合使用 iter 和 next,你可以手动控制迭代过程,而不仅仅依赖于 for 循环。
2.2.4 DataLoader
torch.utils.data.DataLoader 是 PyTorch 中用于加载数据的工具,它在处理大型数据集时非常有用。它能够方便地对数据进行批处理、打乱顺序、并行加速读取等操作。
DataLoader(dataset, batch_size=1, shuffle=False, sampler=None,
batch_sampler=None, num_workers=0, collate_fn=None,
pin_memory=False, drop_last=False, timeout=0,
worker_init_fn=None, *, prefetch_factor=2,
persistent_workers=False)
- dataset:你想要加载的数据集,通常是 TensorDataset 或自定义数据集。
- batch_size:每个批次的大小。
- shuffle:是否在每个epoch开始时打乱数据。
- num_workers:使用多少个子进程来加载数据。默认为0(不使用多进程),设置为大于0的整数可以加速数据加载。
- drop_last:如果数据集大小不能被 batch_size 整除,是否丢弃最后一个不完整的批次。
- pin_memory:是否将数据加载到固定内存区,有助于加快数据传输到GPU。
# 2.读取数据
def loadarray(data_arrays, batch_size, is_train=True):
# *data_arrays进行解包操作
dataset = data.TensorDataset(*data_arrays)
# 每次批次大小为batch_size; 每次epoch开始的时候把数据打乱
return data.DataLoader(dataset, batch_size=batch_size, shuffle=is_train)
batch_size = 10
data_iter = loadarray((features, labels), batch_size)
print(next(iter(data_iter)))
2.3 定义模型
2.3.1 nn.Linear
CLASS torch.nn.Linear(in_features, out_features, bias=True)
对传入数据应用线性变换: y = x A T + b y = xA^T + b y=xAT+b
- 参数
- in_features:每个输入样本的大小
- out_features:每个输出样本的大小
- bias:如果设置为False,层将不会学习偏差。默认值:真正的
- 形状
𝐻𝑖𝑛 = in_features 表示输入张量的最后一维必须等于 nn.Linear 层的 in_features 参数。
𝐻out = out_features 表示输出张量的最后一维必须等于 nn.Linear 层的 out_features 参数。 - 变量
- ~Linear.weight:线性学习模块可学习权重形状为:(out_features,in_features)
- ~Linear.bias:线性学习模块可学习偏移形状为:out_features
import torch
import torch.nn as nn
linear = nn.Linear(in_features=4, out_features=2)
print(linear.weight.shape)
print(linear.bias.shape)
torch.Size([2, 4]) #weight参数的形状
torch.Size([2]) #bias参数的形状
#线性层只作用与输出数据的最后一个维度
x = torch.randn(3, 5, 4) # 3 是批次大小,5 是序列长度,4 是特征维度
output = linear(x)
print(output.shape) # 输出形状为 (3, 5, 2)
2.3.2 nn.Sequential
nn.Sequential 是 PyTorch 提供的一个容器模块,用于将多个神经网络层组合在一起。它按照传入的顺序逐层执行前向传播。在 nn.Sequential 中,所有子模块将依次按顺序被添加,并且在调用该容器的 forward 方法时,它们将按照相同的顺序被调用。
- 用法
创建 nn.Sequential, 你可以通过将各个层以有序的方式传入 nn.Sequential 来构建一个模型。例如:
import torch
import torch.nn as nn
# 使用 nn.Sequential 定义一个简单的神经网络
model = nn.Sequential(
nn.Linear(10, 5),
nn.ReLU(),
nn.Linear(5, 2)
)
print(model)
# 3.定义模型
net = nn.Sequential(nn.Linear(2,1))
2.4 初始化模型参数
2.4.1 Tensor.normal_()
normal_ 是 PyTorch 中张量的一个方法,用于就地填充正态(高斯)分布的随机数。其语法如下:
normal_(mean=0, std=1, *, generator=None) → Tensor
mean:均值
std:方差
Tensor.normal_ 和 torch.normal() 都是 PyTorch 中生成正态分布随机数的方法,但它们的用法和行为有所不同。以下是它们的关系和区别。
Tensor.normal_与torch.normal()
- Tensor.normal_ 是一个就地操作(in-place operation),它直接修改调用它的张量的内容。
- torch.normal() 是一个函数,用于生成新的张量,其中包含从指定的正态分布中抽取的随机数。
2.4.2 Tensor.fill_
用指定的值填充张量
# 4.初始化模型参数
net[0].weight.normal_(0, 0.01)
net[0].bias.fill_(0)
2.5 定义损失函数
2.5.1 nn.MSELoss()
nn.MSELoss 是 PyTorch 中用于计算均方误差损失的类,常用于回归任务。它可以通过创建实例并调用实例的 forward 方法(即直接调用实例本身)来计算模型输出与真实标签之间的损失。
使用方法
- nn.MSELoss 可以通过以下步骤进行使用:
- 定义损失函数: 创建 nn.MSELoss 的实例。
- 计算损失: 使用损失函数实例计算模型输出与真实标签之间的损失。
import torch
import torch.nn as nn
# 定义模型输出和真实标签
predicted = torch.tensor([2.5, 0.0, 2.1, 1.4])
target = torch.tensor([3.0, -0.5, 2.0, 1.0])
# 创建 MSELoss 实例
criterion = nn.MSELoss()
# 计算损失
loss = criterion(predicted, target)
print('Loss:', loss.item())
# 5. 定义损失函数
loss = nn.MSELoss()
2.6 定义优化算法
2.6.1 torch.optim.SGD()
torch.optim.SGD 是 PyTorch 提供的用于实现随机梯度下降(Stochastic Gradient Descent, SGD)优化算法的类。随机梯度下降是一种简单而有效的优化算法,广泛应用于训练神经网络模型。
class torch.optim.SGD(params, lr=<required parameter>, momentum=0, dampening=0, weight_decay=0, nesterov=False)
参数详解
- params: 待优化的参数或参数组。通常使用 model.parameters() 来传递模型的参数。
- lr: 学习率,是一个必须要设置的参数。学习率决定了每次更新时参数移动的步长。
- momentum: 动量因子,用于加速 SGD 在相关方向上的收敛,并抑制震荡。默认为 0,表示没有动量。
- dampening: 动量衰减因子。默认为 0。
- weight_decay: 权重衰减(L2 正则化),默认值为 0。通过向损失函数添加参数的平方和来防止过拟合。
- nesterov: 布尔值,表示是否使用 Nesterov 动量。默认为 False。
# 6. 定义优化算法
trainer = torch.optim.SGD(net.parameters(), lr=0.03)
2.7 训练
zero_grad() 用于清除梯度,step() 用于根据计算的梯度更新模型参数。这两个方法是 PyTorch 中优化器类的标准方法,用于管理和更新模型参数。
# 7. 训练
num_eopch = 3
for i in range(num_eopch):
for X, y in data_iter:
l = loss(net(X), y)
trainer.zero_grad()
l.backward()
trainer.step()
l = loss(net(features), labels)
print(f'eopch:{i+1}, loss{l:f}')
print(net[0].weight.data)
print(net[0].bias.data)
2.8 完整代码
import numpy as np
import torch
from torch.utils import data
from d2l import torch as d2l
import torch.nn as nn
# 1.生成数据
true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = d2l.synthetic_data(true_w, true_b, 1000)
# 2.读取数据
def loadarray(data_arrays, batch_size, is_train=True):
dataset = data.TensorDataset(*data_arrays)
return data.DataLoader(dataset, batch_size=batch_size, shuffle=is_train)
batch_size = 10
data_iter = loadarray((features, labels), batch_size)
print(next(iter(data_iter)))
# 3.定义模型
net = nn.Sequential(nn.Linear(2,1))
# 4.初始化模型参数
net[0].weight.data.normal_(0, 0.01)
net[0].bias.data.fill_(0)
# 5. 定义损失函数
loss = nn.MSELoss()
# 6. 定义优化算法
trainer = torch.optim.SGD(net.parameters(), lr=0.03)
# 7. 训练
num_eopch = 3
for i in range(num_eopch):
for X, y in data_iter:
l = loss(net(X), y)
trainer.zero_grad()
l.backward()
trainer.step()
l = loss(net(features), labels)
print(f'eopch:{i+1}, loss{l:f}')
print(net[0].weight.data)
print(net[0].bias.data)