目录
介绍
设置训练硬件
定义类
模型层
全连接层(nn.Flatten )
nn.Linear(线性层)
nn.ReLU
nn.Sequential
nn.Softmax
Model Parameters
神经网络由对数据执行操作的层/模块组成。 torch.nn 命名空间提供了构建神经网络所需的所有模块。 PyTorch 中的每个模块都是 nn.Module 的子类。 神经网络本身是一个模块,它由其他模块(层)组成。 这种嵌套结构允许轻松构建和管理复杂的架构。
在接下来的部分中,我们将构建一个神经网络来对 FashionMNIST 数据集中的图像进行分类。
import os
import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
我们希望能够在 GPU 等硬件加速器(如果可用)上训练我们的模型。 让我们检查一下torch.cuda是否可用,否则我们继续使用CPU。
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using {device} device")
out:
Using cuda device
我们通过子类 nn.Module 来定义我们的神经网络,并在 __init__ 中初始化神经网络层。 每个 nn.Module 子类都在 forward 方法中实现对输入数据的操作。
class NeuralNetwork(nn.Module):
def __init__(self):
super(NeuralNetwork, self).__init__()
self.flatten = nn.Flatten()
self.linear_relu_stack = nn.Sequential(
nn.Linear(28*28, 512),
nn.ReLU(),
nn.Linear(512, 512),
nn.ReLU(),
nn.Linear(512, 10),
)
def forward(self, x):
x = self.flatten(x)
logits = self.linear_relu_stack(x)
return logits
我们创建一个 NeuralNetwork 实例,并将其移动到设备上,并打印其结构。
model = NeuralNetwork().to(device)
print(model)
out;
NeuralNetwork(
(flatten): Flatten(start_dim=1, end_dim=-1)
(linear_relu_stack): Sequential(
(0): Linear(in_features=784, out_features=512, bias=True)
(1): ReLU()
(2): Linear(in_features=512, out_features=512, bias=True)
(3): ReLU()
(4): Linear(in_features=512, out_features=10, bias=True)
)
)
要使用模型,我们将输入数据传递给它。 这将执行模型的forward(),以及一些后台操作。 不要直接调用 model.forward() !
在输入上调用模型会返回一个 10 维张量,其中包含每个类的原始预测值。 我们通过一个 nn.Softmax 模块的实例来获得预测概率。
X = torch.rand(1, 28, 28, device=device)
logits = model(X)
pred_probab = nn.Softmax(dim=1)(logits)
y_pred = pred_probab.argmax(1)
print(f"Predicted class: {y_pred}")
out:
Predicted class: tensor([9], device='cuda:0')
让我们分解 FashionMNIST 模型中的层。 为了说明这一点,我们将抽取 3 张大小为 28x28 的图像的小批量样本,看看当我们通过网络传递它时会发生什么。
input_image = torch.rand(3,28,28)
print(input_image.size())
out:
torch.Size([3, 28, 28])
注:torch.rand — PyTorch 1.11.0 documentation
我们初始化 nn.Flatten 层以将每个 2D 28x28 图像转换为 784 个像素值的连续数组(保持小批量维度(dim=0))。
flatten = nn.Flatten()
flat_image = flatten(input_image)
print(flat_image.size())
out:
torch.Size([3, 784])
nn.flatten(): Flatten — PyTorch 1.11.0 documentation
(12条消息) CNN的Flatten操作 | Pytorch系列(七)_flyfor2013的博客-CSDN博客nn.flatten():(12条消息) CNN的Flatten操作 | Pytorch系列(七)_flyfor2013的博客-CSDN博客
线性层是一个模块,它使用其存储的权重和偏差对输入应用线性变换。
layer1 = nn.Linear(in_features=28*28, out_features=20)
hidden1 = layer1(flat_image)
print(hidden1.size())
out:
torch.Size([3, 20])
官方文档:nn.Linear: Linear — PyTorch 1.11.0 documentation
非线性激活是在模型的输入和输出之间创建复杂映射的原因。 它们在线性变换后应用以引入非线性,帮助神经网络学习各种现象。
在这个模型中,我们在线性层之间使用了 nn.ReLU,但是还有其他激活可以在模型中引入非线性。
print(f"Before ReLU: {hidden1}\n\n")
hidden1 = nn.ReLU()(hidden1)
print(f"After ReLU: {hidden1}")
out:
Before ReLU: tensor([[-0.2237, -0.2367, 0.2977, -0.3347, -0.4724, 0.3709, 0.0294, -0.0807,
-0.5721, -0.1723, -0.8035, 0.4663, -0.0803, -0.2520, 0.8864, 0.4762,
0.2638, -0.1566, 0.0790, -0.0876],
[-0.2885, -0.3101, 0.2298, -0.4918, -0.3310, 0.4374, 0.1665, 0.1405,
-0.5300, -0.3482, -0.4831, -0.0948, 0.1129, -0.3147, 0.8067, 0.3847,
0.2725, -0.0671, 0.4173, -0.3192],
[-0.2258, -0.1209, 0.6989, -0.4547, -0.3201, -0.1266, -0.1083, -0.0766,
-0.2590, -0.3851, -0.7130, 0.4853, 0.2001, -0.3398, 0.9755, 0.3800,
-0.0782, 0.2659, 0.2886, -0.5325]], grad_fn=)
After ReLU: tensor([[0.0000, 0.0000, 0.2977, 0.0000, 0.0000, 0.3709, 0.0294, 0.0000, 0.0000,
0.0000, 0.0000, 0.4663, 0.0000, 0.0000, 0.8864, 0.4762, 0.2638, 0.0000,
0.0790, 0.0000],
[0.0000, 0.0000, 0.2298, 0.0000, 0.0000, 0.4374, 0.1665, 0.1405, 0.0000,
0.0000, 0.0000, 0.0000, 0.1129, 0.0000, 0.8067, 0.3847, 0.2725, 0.0000,
0.4173, 0.0000],
[0.0000, 0.0000, 0.6989, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,
0.0000, 0.0000, 0.4853, 0.2001, 0.0000, 0.9755, 0.3800, 0.0000, 0.2659,
0.2886, 0.0000]], grad_fn=)
nn.Sequential 是一个有序的模块容器。 数据按照定义的顺序通过所有模块。 您可以使用顺序容器来组合一个快速网络,例如 seq_modules。
seq_modules = nn.Sequential(
flatten,
layer1,
nn.ReLU(),
nn.Linear(20, 10)
)
input_image = torch.rand(3,28,28)
logits = seq_modules(input_image)
神经网络的最后一个线性层返回 logits - [-infty, infty] 中的原始值 被传递给 nn.Softmax 模块。 logits 被缩放为 [0, 1],表示模型对每个类别的预测概率。 dim 参数指示值必须总和为 1 的维度。
softmax = nn.Softmax(dim=1)
pred_probab = softmax(logits)
神经网络中的许多层都是参数化的,即具有在训练期间优化的相关权重和偏差。 子类化 nn.Module 会自动跟踪模型对象中定义的所有字段,并使用模型的 parameters() 或 named_parameters() 方法使所有参数都可以访问。
print(f"Model structure: {model}\n\n")
for name, param in model.named_parameters():
print(f"Layer: {name} | Size: {param.size()} | Values : {param[:2]} \n")
out:
Model structure: NeuralNetwork(
(flatten): Flatten(start_dim=1, end_dim=-1)
(linear_relu_stack): Sequential(
(0): Linear(in_features=784, out_features=512, bias=True)
(1): ReLU()
(2): Linear(in_features=512, out_features=512, bias=True)
(3): ReLU()
(4): Linear(in_features=512, out_features=10, bias=True)
)
)
Layer: linear_relu_stack.0.weight | Size: torch.Size([512, 784]) | Values : tensor([[ 0.0033, -0.0081, -0.0354, ..., -0.0335, 0.0070, 0.0030],
[ 0.0106, -0.0064, 0.0300, ..., 0.0071, -0.0062, 0.0169]],
device='cuda:0', grad_fn=)
Layer: linear_relu_stack.0.bias | Size: torch.Size([512]) | Values : tensor([-0.0193, -0.0153], device='cuda:0', grad_fn=)
Layer: linear_relu_stack.2.weight | Size: torch.Size([512, 512]) | Values : tensor([[ 0.0408, 0.0078, 0.0300, ..., 0.0058, -0.0142, -0.0226],
[ 0.0319, -0.0063, -0.0093, ..., -0.0096, 0.0352, 0.0178]],
device='cuda:0', grad_fn=)
Layer: linear_relu_stack.2.bias | Size: torch.Size([512]) | Values : tensor([0.0219, 0.0020], device='cuda:0', grad_fn=)
Layer: linear_relu_stack.4.weight | Size: torch.Size([10, 512]) | Values : tensor([[ 0.0076, 0.0076, 0.0433, ..., 0.0178, 0.0230, 0.0227],
[-0.0396, -0.0042, 0.0342, ..., -0.0364, -0.0184, -0.0329]],
device='cuda:0', grad_fn=)
Layer: linear_relu_stack.4.bias | Size: torch.Size([10]) | Values : tensor([-0.0380, -0.0044], device='cuda:0', grad_fn=)
官方文档:
Build the Neural Network — PyTorch Tutorials 1.11.0+cu102 documentation