积累
nn.Parameter 首先是函数,其次是用来包裹tensor用来作为可学习参数的,默认求导
nn.functional
是 PyTorch 中的一个功能模块,它包含了一系列用于定义神经网络操作的函数。这些函数通常用于执行各种非线性操作、损失函数、激活函数、卷积操作等。与 nn.Module
不同,nn.functional
中的函数是无状态的,即它们不会保持任何内部状态或参数。
nn.functional
的主要优势在于其计算效率和灵活性。它允许你以函数的方式直接调用这些操作,而不需要创建额外的层或模块。这使得在定义简单的网络结构或在复杂网络中进行某些特定的计算时非常方便。
例如,你可以使用 nn.functional.relu
函数来应用 ReLU 激活函数,或者使用 nn.functional.conv2d
函数来执行二维卷积操作。
然而,需要注意的是,虽然 nn.functional
中的函数与 nn.Module
子类中的方法具有相似的功能,但它们的用法和上下文有所不同。nn.Module
子类通常用于定义整个网络架构或模块,并包含可学习的参数,而 nn.functional
中的函数则更适合于在 forward
方法中调用,以执行特定的网络操作。
此外,nn.functional
中的函数和 nn.Module
子类中的方法之间的主要区别在于状态管理。nn.Module
子类可以管理其内部状态(如参数和缓冲区),而 nn.functional
中的函数则是无状态的,它们不会保持任何内部状态或参数。
总的来说,nn.functional
和 nn.Module
是 PyTorch 中用于构建神经网络模型的两个重要组件,它们各自具有不同的特点和用途。
2.nn.Module库: 对于需要学习参数的层,最好使用nn.Module,因为会默认注册parameters()里学习参数;对于无参数学习的层用nn.functional。
nn.Module
是 PyTorch 中神经网络模块的基类。当你想要定义一个新的神经网络层、模块或整个神经网络架构时,你需要从 nn.Module
继承。nn.Module
提供了用于定义网络结构、管理模型参数以及控制前向传播等操作的基础功能。
以下是 nn.Module
的一些主要特点和用途:
- 定义网络层和操作:使用
nn.Module
,你可以定义各种网络层,如全连接层(nn.Linear
)、卷积层(nn.Conv2d
)、池化层(nn.MaxPool2d
)等,以及各种激活函数(如nn.ReLU
)、归一化操作(如nn.BatchNorm2d
)等。 - 管理模型参数:
nn.Module
会自动跟踪和管理模型的参数,包括权重(weights)和偏差(biases)。这使得参数的初始化、梯度计算和优化变得非常简单。你可以通过model.parameters()
方法获取模型中的所有参数。 - 前向传播操作:通过实现
forward
方法,你可以定义模型的前向传播操作,即如何将输入数据传递给网络并生成预测结果。在forward
方法中,你可以使用在__init__
方法中定义的层和激活函数等操作。 - 递归嵌套:
nn.Module
具有递归嵌套的能力,这意味着你可以创建复杂的模型结构,将多个nn.Module
组合在一起,形成层次化的网络。
以下是一个简单的例子,展示如何使用 nn.Module
定义一个包含两个全连接层的简单神经网络:
import torch.nn as nn
class MyModel(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(MyModel, 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
在这个例子中,MyModel
类从 nn.Module
继承,并在 __init__
方法中定义了两个全连接层(fc1
和 fc2
)和一个 ReLU 激活函数。然后,在 forward
方法中,定义了模型的前向传播逻辑。
nn.functional
nn.functional
是 PyTorch 中的一个功能模块,它包含了一系列用于定义神经网络操作的函数。这些函数通常用于执行各种非线性操作、损失函数、激活函数、卷积操作等。与 nn.Module
不同,nn.functional
中的函数是无状态的,即它们不会保持任何内部状态或参数。
nn.functional
的主要优势在于其计算效率和灵活性。它允许你以函数的方式直接调用这些操作,而不需要创建额外的层或模块。这使得在定义简单的网络结构或在复杂网络中进行某些特定的计算时非常方便。
例如,你可以使用 nn.functional.relu
函数来应用 ReLU 激活函数,或者使用 nn.functional.conv2d
函数来执行二维卷积操作。
然而,需要注意的是,虽然 nn.functional
中的函数与 nn.Module
子类中的方法具有相似的功能,但它们的用法和上下文有所不同。nn.Module
子类通常用于定义整个网络架构或模块,并包含可学习的参数,而 nn.functional
中的函数则更适合于在 forward
方法中调用,以执行特定的网络操作。
此外,nn.functional
中的函数和 nn.Module
子类中的方法之间的主要区别在于状态管理。nn.Module
子类可以管理其内部状态(如参数和缓冲区),而 nn.functional
中的函数则是无状态的,它们不会保持任何内部状态或参数。
总的来说,nn.functional
和 nn.Module
是 PyTorch 中用于构建神经网络模型的两个重要组件,它们各自具有不同的特点和用途。
nn.Sequential()模块 用来快速构建模型,像是管道一样
nn.ModuleList: nn.ModuleList 是 PyTorch(一个流行的深度学习库)中的一个容器,用于包含多个 nn.Module 对象的列表。
nn.optim
在 PyTorch 中,nn.optim
模块提供了多种优化算法的实现,这些优化算法用于在训练神经网络时更新模型的参数。以下是 nn.optim
的基本用法:
首先,你需要定义你的模型(通常是一个 nn.Module
的子类实例),然后你需要定义一个损失函数(通常是一个 nn.functional
中的函数,如 nn.functional.cross_entropy
或 nn.functional.mse_loss
)。
然后,你可以选择一个优化器并实例化它,将模型的参数作为输入传递给优化器。在训练循环中,你需要进行前向传播以计算预测值和损失,然后执行反向传播以计算梯度,并使用优化器的 step()
方法来更新模型的参数。
以下是一个简单的示例,展示了如何使用 nn.optim.SGD
(随机梯度下降)优化器来训练一个简单的线性回归模型:
import torch
import torch.nn as nn
import torch.optim as optim
# 假设我们有一个简单的线性回归模型
class LinearRegressionModel(nn.Module):
def __init__(self, input_dim, output_dim):
super(LinearRegressionModel, self).__init__()
self.linear = nn.Linear(input_dim, output_dim)
def forward(self, x):
out = self.linear(x)
return out
# 实例化模型
model = LinearRegressionModel(input_dim=1, output_dim=1)
# 定义损失函数和优化器
criterion = nn.MSELoss() # 均方误差损失
optimizer = optim.SGD(model.parameters(), lr=0.01) # 使用SGD优化器,学习率设置为0.01
# 假设我们有一些训练数据
inputs = torch.randn(100, 1, requires_grad=False)
targets = 2 * inputs + 1 # 简单的线性关系,用于演示
# 训练循环
for epoch in range(100): # 假设我们训练100个epoch
# 前向传播
outputs = model(inputs)
loss = criterion(outputs, targets)
# 反向传播和优化
optimizer.zero_grad() # 清空之前的梯度
loss.backward() # 反向传播,计算当前梯度
optimizer.step() # 使用梯度更新权重
# 打印统计信息(可选)
if (epoch+1) % 10 == 0:
print(f'Epoch [{epoch+1}/{100}], Loss: {loss.item()}')
# 训练完成后,你可以使用模型进行预测等操作
在这个例子中,我们首先定义了一个简单的线性回归模型 LinearRegressionModel
,然后定义了均方误差损失函数 nn.MSELoss()
和一个 SGD 优化器 optim.SGD()
。在训练循环中,我们执行了前向传播以计算预测值和损失,然后执行了反向传播以计算梯度,并使用优化器的 step()
方法来更新模型的参数。在每个 epoch 结束时,我们还打印了当前的损失值以便监控训练过程。
Dataset类继承
在PyTorch中,torch.utils.data.Dataset
是一个抽象类,用于代表一个数据集。当你想要从自定义的数据源(如CSV文件、数据库、自定义格式的文件等)加载数据时,你可以通过继承 Dataset
类并实现其抽象方法来创建自定义的数据集。
以下是一个基本的步骤指南,说明如何通过继承 torch.utils.data.Dataset
来创建自定义数据集:
- 导入必要的库:首先,确保你已经导入了必要的PyTorch库。
- 定义数据集类:创建一个新的类,继承自
torch.utils.data.Dataset
。 - 初始化方法 (
__init__
):在初始化方法中,定义任何你需要的数据集相关的变量。这可能包括文件路径、数据预处理步骤的参数等。 - 实现
__len__
方法:这个方法应该返回数据集中的样本数量。 - 实现
__getitem__
方法:这个方法应该接收一个索引作为输入,并返回一个样本。样本通常是一个元组,包含输入数据和相应的标签(如果有的话)。这个方法应该能够处理任何索引,包括负索引和超出范围的索引(通过适当的错误处理或循环索引)。 - (可选)实现其他方法:你可以根据需要实现其他方法,如
__add__
、__mul__
等,以便支持数据集的组合或重复等操作。 - 使用数据集:一旦你定义了数据集类,你就可以创建其实例,并将其传递给数据加载器(
torch.utils.data.DataLoader
),以便在训练循环中迭代数据集。
下面是一个简单的示例,展示了如何继承 torch.utils.data.Dataset
来创建一个从CSV文件中加载数据的数据集:
import torch
from torch.utils.data import Dataset, DataLoader
import pandas as pd
class CustomDataset(Dataset):
def __init__(self, csv_file, transform=None):
self.data = pd.read_csv(csv_file)
self.transform = transform
def __len__(self):
return len(self.data)
def __getitem__(self, idx):
if torch.is_tensor(idx):
idx = idx.tolist()
sample = self.data.iloc[idx] # 使用pandas的iloc方法来选择行
# 假设CSV有两列:'feature' 和 'label'
features = sample['feature'].values.astype(float)
if self.transform:
features = self.transform(features)
label = sample['label'].values.astype(int)
return torch.tensor(features), torch.tensor(label)
# 使用示例
dataset = CustomDataset(csv_file='data.csv')
data_loader = DataLoader(dataset, batch_size=32, shuffle=True)
# 在训练循环中使用数据加载器
for inputs, labels in data_loader:
# 训练代码...
pass
请注意,这个示例假设CSV文件有两列(‘feature’ 和 ‘label’),并且你希望将特征列作为输入数据,将标签列作为标签。你可能需要根据你的具体数据集和需求来调整这个示例。
torchvision.transforms
torchvision.transforms
是 PyTorch 生态系统中的一部分,它为图像预处理提供了各种常用操作。这些变换(transforms)通常用于在将数据加载到 PyTorch 模型之前,对图像进行标准化、裁剪、缩放等处理。
下面是一些使用 torchvision.transforms
的基本示例:
首先,你需要导入 torchvision.transforms
:
from torchvision import transforms
你可以定义一个或多个变换,并将它们组合起来。例如,你可能想要对图像进行以下操作:
- 裁剪图像到指定大小。
- 转换为 Tensor。
- 归一化图像到 [0, 1] 范围,并可能减去均值和除以标准差(这通常是针对预训练的模型)。
# 假设我们想要裁剪图像到 224x224,然后归一化到 [0, 1]
transform = transforms.Compose([
transforms.Resize(256), # 首先,我们调整图像大小为 256x256
transforms.CenterCrop(224), # 然后,我们从中心裁剪出 224x224 的区域
transforms.ToTensor(), # 将 PIL Image 或 ndarray 转换为 torch.Tensor,范围在 [0, 1]
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), # 归一化到 [-1, 1]
])
Dataloader
DataLoader
是 PyTorch 中的一个重要类,它提供了一个可迭代的数据加载器,可以方便地批量加载数据,并自动进行多进程数据加载、批处理、打乱数据(shuffling)等操作。下面是如何使用 DataLoader
的基本步骤:
使用 DataLoader
来包装数据集,并设置批大小(batch size)、是否打乱数据等参数。
dataloader = DataLoader(dataset, batch_size=64, shuffle=True, num_workers=2)
在这个例子中,我们设置了批大小为 64,启用了数据打乱,并使用了 2 个子进程来加载数据。
在训练循环中,你可以通过迭代 DataLoader
来获取数据。
for images, labels in dataloader:
# 训练代码
# 例如: optimizer.zero_grad()
# outputs = model(images)
# loss = criterion(outputs, labels)
# loss.backward()
# optimizer.step()
pass
在每次迭代中,dataloader
会返回一个批次的图像和对应的标签。你可以将这些数据传递给模型进行训练。
注意事项
num_workers
参数用于指定数据加载时使用的子进程数。在 Unix 系统上,通常可以设置为 CPU 核心数或者更多(但要小心内存使用情况)。在 Windows 系统上,num_workers
可能需要设置为 0,因为 Windows 的多进程实现与 Unix 不同。- 如果你在 Jupyter Notebook 或其他交互式环境中使用
DataLoader
,并且设置了num_workers
大于 0,可能会遇到一些与多进程相关的问题。在这种情况下,你可以尝试将num_workers
设置为 0。 - 如果你的数据集非常大,无法一次性加载到内存中,
DataLoader
可以帮助你有效地管理内存使用,因为它会按需加载数据批次。