构建神经网络Build the Neural Network神经网络由对数据执行操作的层/模块组成。torch.nn命名空间提供了构建自己的神经网络所需的所有构建块。PyTorch 中的每个模块都是nn.Module的子类。神经网络本身就是一个模块由其他模块层组成。这种嵌套结构使得构建和管理复杂架构变得容易。在以下部分中我们将构建一个神经网络来对 FashionMNIST 数据集中的图像进行分类。importos# 导入操作系统模块importtorch# 导入 PyTorch 核心库fromtorchimportnn# 导入神经网络模块fromtorch.utils.dataimportDataLoader# 导入数据加载器fromtorchvisionimportdatasets,transforms# 导入视觉数据集和变换模块获取训练设备Get Device for Training我们希望能够在加速器上训练模型如 CUDA、MPS、MTIA 或 XPU。如果当前加速器可用我们将使用它。否则我们使用 CPU。devicetorch.accelerator.current_accelerator().typeiftorch.accelerator.is_available()elsecpu# 检查加速器可用性print(fUsing{device}device)# 打印当前使用的设备类型输出Using cuda device定义类Define the Class我们通过子类化nn.Module来定义我们的神经网络并在__init__中初始化神经网络的层。每个nn.Module子类在forward方法中实现对输入数据的操作。classNeuralNetwork(nn.Module):# 定义神经网络类继承自 nn.Moduledef__init__(self):# 初始化方法super().__init__()# 调用父类的初始化方法self.flattennn.Flatten()# 创建展平层self.linear_relu_stacknn.Sequential(# 创建顺序容器nn.Linear(28*28,512),# 全连接层784 → 512nn.ReLU(),# ReLU 激活函数nn.Linear(512,512),# 全连接层512 → 512nn.ReLU(),# ReLU 激活函数nn.Linear(512,10),# 全连接层512 → 10)defforward(self,x):# 前向传播方法xself.flatten(x)# 展平输入logitsself.linear_relu_stack(x)# 通过全连接层序列returnlogits# 返回 logits我们创建一个NeuralNetwork的实例将其移动到device并打印其结构。modelNeuralNetwork().to(device)# 创建模型实例并移动到设备print(model)# 打印模型结构输出NeuralNetwork( (flatten): Flatten(start_dim1, end_dim-1) (linear_relu_stack): Sequential( (0): Linear(in_features784, out_features512, biasTrue) (1): ReLU() (2): Linear(in_features512, out_features512, biasTrue) (3): ReLU() (4): Linear(in_features512, out_features10, biasTrue) ) )要使用模型我们传入输入数据。这会执行模型的forward以及一些后台操作。不要直接调用model.forward()在输入上调用模型返回一个 2 维张量dim0 对应每个类别的 10 个原始预测值dim1 对应每个输出的各个值。我们通过将输出传入nn.Softmax模块的实例来获取预测概率。Xtorch.rand(1,28,28,devicedevice)# 创建随机输入张量1张28x28图像logitsmodel(X)# 前向传播得到 logitspred_probabnn.Softmax(dim1)(logits)# 将 logits 转换为概率y_predpred_probab.argmax(1)# 获取概率最大的类别索引print(fPredicted class:{y_pred})# 打印预测类别输出Predicted class: tensor([7], devicecuda:0)模型层Model Layers让我们分解 FashionMNIST 模型中的层。为了说明我们将取一个包含 3 张 28x28 大小图像的样本小批量看看它在通过网络时会发生什么。input_imagetorch.rand(3,28,28)# 创建 3 张 28x28 的随机图像print(input_image.size())# 打印输入图像的尺寸输出torch.Size([3, 28, 28])nn.Flatten我们初始化nn.Flatten层将每个 2D 28x28 图像转换为 784 个像素值的连续数组小批量维度dim0保持不变。flattennn.Flatten()# 创建展平层flat_imageflatten(input_image)# 将输入图像展平print(flat_image.size())# 打印展平后的尺寸输出torch.Size([3, 784])nn.Linear线性层是一个使用其存储的权重和偏置对输入应用线性变换的模块。layer1nn.Linear(in_features28*28,out_features20)# 创建线性层784 → 20hidden1layer1(flat_image)# 通过线性层print(hidden1.size())# 打印输出尺寸输出torch.Size([3, 20])nn.ReLU非线性激活是在模型的输入和输出之间创建复杂映射的关键。它们在线性变换之后应用以引入_非线性_帮助神经网络学习各种各样的现象。在这个模型中我们在线性层之间使用nn.ReLU但还有其他激活函数可以为你的模型引入非线性。print(fBefore ReLU:{hidden1}\n\n)# 打印 ReLU 之前的值hidden1nn.ReLU()(hidden1)# 应用 ReLU 激活函数print(fAfter ReLU:{hidden1})# 打印 ReLU 之后的值输出Before ReLU: tensor([[ 1.3094e-01, 4.3160e-01, 5.2315e-01, -1.3872e-01, -6.9563e-01, -6.2513e-03, -2.0715e-01, 1.2438e-01, -1.8729e-01, -8.3639e-02, -5.4417e-01, 1.8546e-02, -2.3980e-01, -9.3009e-02, 6.0112e-01, -8.1109e-04, 5.3917e-01, -4.2795e-01, -9.4901e-01, -1.0455e00], [ 3.0679e-01, 2.8433e-01, 1.8939e-02, 1.2754e-01, -6.2956e-01, -4.1956e-01, -1.6514e-02, -1.4316e-01, -5.5423e-02, -3.1190e-01, -1.1989e-01, 1.8634e-01, -2.4850e-02, -6.0525e-02, 6.3658e-01, -1.3055e-01, 3.4517e-01, -1.1803e-02, -3.8263e-01, -1.2716e00], [ 1.7327e-01, 3.4879e-01, 3.1220e-01, -3.1442e-01, -7.1223e-01, -4.2157e-01, -8.4068e-02, -1.0126e-01, -2.7832e-01, -2.8407e-01, -1.6673e-01, -2.6544e-02, -1.0147e-01, -1.0637e-01, 5.8027e-01, 3.9544e-02, 4.6786e-01, 1.4311e-01, -3.0729e-01, -1.4228e00]], grad_fnAddmmBackward0) After ReLU: tensor([[0.1309, 0.4316, 0.5231, 0.0000, 0.0000, 0.0000, 0.0000, 0.1244, 0.0000, 0.0000, 0.0000, 0.0185, 0.0000, 0.0000, 0.6011, 0.0000, 0.5392, 0.0000, 0.0000, 0.0000], [0.3068, 0.2843, 0.0189, 0.1275, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.1863, 0.0000, 0.0000, 0.6366, 0.0000, 0.3452, 0.0000, 0.0000, 0.0000], [0.1733, 0.3488, 0.3122, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.5803, 0.0395, 0.4679, 0.1431, 0.0000, 0.0000]], grad_fnReluBackward0)nn.Sequentialnn.Sequential是一个有序的模块容器。数据按照定义的顺序通过所有模块。你可以使用顺序容器来快速组合一个网络。seq_modulesnn.Sequential(# 创建顺序模块容器flatten,# 展平层layer1,# 线性层nn.ReLU(),# ReLU 激活nn.Linear(20,10)# 线性层20 → 10)input_imagetorch.rand(3,28,28)# 创建随机输入logitsseq_modules(input_image)# 通过顺序模块前向传播nn.Softmax神经网络的最后一个线性层返回 logits——[-∞, ∞] 范围内的原始值——这些值被传入nn.Softmax模块。logits 被缩放到 [0, 1] 范围内的值表示模型对每个类别的预测概率。dim参数指示值必须沿哪个维度求和为 1。softmaxnn.Softmax(dim1)# 创建 Softmax 层沿第1维归一化pred_probabsoftmax(logits)# 将 logits 转换为概率模型参数Model Parameters神经网络内的许多层是_参数化_的即具有在训练期间优化的相关权重和偏置。子类化nn.Module会自动跟踪模型对象中定义的所有字段并使用模型的parameters()或named_parameters()方法使所有参数可访问。在这个例子中我们遍历每个参数并打印其大小和值的预览。print(fModel structure:{model}\n\n)# 打印模型结构forname,paraminmodel.named_parameters():# 遍历模型的所有命名参数print(fLayer:{name}| Size:{param.size()}| Values :{param[:2]}\n)# 打印参数名称、大小和前两个值输出Model structure: NeuralNetwork( (flatten): Flatten(start_dim1, end_dim-1) (linear_relu_stack): Sequential( (0): Linear(in_features784, out_features512, biasTrue) (1): ReLU() (2): Linear(in_features512, out_features512, biasTrue) (3): ReLU() (4): Linear(in_features512, out_features10, biasTrue) ) ) Layer: linear_relu_stack.0.weight | Size: torch.Size([512, 784]) | Values : tensor([[-0.0182, -0.0114, 0.0199, ..., 0.0226, -0.0306, -0.0323], [-0.0161, -0.0127, 0.0001, ..., 0.0170, 0.0015, -0.0062]], devicecuda:0, grad_fnSliceBackward0) Layer: linear_relu_stack.0.bias | Size: torch.Size([512]) | Values : tensor([0.0181, 0.0233], devicecuda:0, grad_fnSliceBackward0) Layer: linear_relu_stack.2.weight | Size: torch.Size([512, 512]) | Values : tensor([[ 0.0250, -0.0056, 0.0227, ..., -0.0145, 0.0324, 0.0357], [-0.0109, -0.0318, -0.0081, ..., 0.0370, -0.0279, -0.0379]], devicecuda:0, grad_fnSliceBackward0) Layer: linear_relu_stack.2.bias | Size: torch.Size([512]) | Values : tensor([ 0.0024, -0.0108], devicecuda:0, grad_fnSliceBackward0) Layer: linear_relu_stack.4.weight | Size: torch.Size([10, 512]) | Values : tensor([[ 0.0058, -0.0245, -0.0232, ..., -0.0389, -0.0154, 0.0236], [-0.0152, 0.0186, -0.0065, ..., 0.0427, -0.0192, -0.0225]], devicecuda:0, grad_fnSliceBackward0) Layer: linear_relu_stack.4.bias | Size: torch.Size([10]) | Values : tensor([-0.0058, 0.0047], devicecuda:0, grad_fnSliceBackward0)