01-快速入门 快速入门Quickstart本节将介绍机器学习中常见任务的 API。处理数据Working with DataPyTorch 提供了两个处理数据的原语torch.utils.data.DataLoader和torch.utils.data.Dataset。Dataset存储样本及其对应的标签DataLoader在Dataset外包装了一个可迭代对象。importtorch# 导入 PyTorch 核心库fromtorchimportnn# 导入神经网络模块fromtorch.utils.dataimportDataLoader# 导入数据加载器fromtorchvisionimportdatasets# 导入视觉数据集模块fromtorchvision.transformsimportv2# 导入数据变换模块 v2 版本PyTorch 提供了领域特定的库如 TorchText、TorchVision 和 TorchAudio这些库都包含数据集。在本教程中我们将使用 TorchVision 数据集。torchvision.datasets模块包含了许多真实世界视觉数据的Dataset对象如 CIFAR、COCO。在本教程中我们使用 FashionMNIST 数据集。每个 TorchVisionDataset都包含两个参数transform和target_transform分别用于修改样本和标签。# 从开放数据集下载训练数据training_datadatasets.FashionMNIST(# 创建 FashionMNIST 训练数据集对象rootdata,# 数据存储路径trainTrue,# 指定为训练集downloadTrue,# 如果数据不存在则从网络下载transformv2.Compose([# 对图像进行变换组合v2.ToImage(),# 将数据转为 torchvision 的 Image 张量格式v2.ToDtype(torch.float32,scaleTrue)# 转为 float32 类型并将像素值缩放到 [0,1]]),)# 从开放数据集下载测试数据test_datadatasets.FashionMNIST(# 创建 FashionMNIST 测试数据集对象rootdata,# 数据存储路径trainFalse,# 指定为测试集downloadTrue,# 如果数据不存在则从网络下载transformv2.Compose([# 对图像进行变换组合与训练集相同v2.ToImage(),# 将数据转为 torchvision 的 Image 张量格式v2.ToDtype(torch.float32,scaleTrue)# 转为 float32 类型并将像素值缩放到 [0,1]]),)我们将Dataset作为参数传递给DataLoader。这将在数据集外包装一个可迭代对象并支持自动批处理、采样、打乱和多进程数据加载。这里我们定义批大小为 64即 dataloader 可迭代对象中的每个元素将返回一个包含 64 个特征和标签的批次。batch_size64# 定义批大小为 64# 创建数据加载器train_dataloaderDataLoader(training_data,batch_sizebatch_size)# 用训练数据集创建数据加载器test_dataloaderDataLoader(test_data,batch_sizebatch_size)# 用测试数据集创建数据加载器forX,yintest_dataloader:# 遍历测试数据加载器print(fShape of X [N, C, H, W]:{X.shape})# 打印输入特征的形状批次大小、通道数、高度、宽度print(fShape of y:{y.shape}{y.dtype})# 打印标签的形状和数据类型break# 只查看第一个批次后跳出循环输出Shape of X [N, C, H, W]: torch.Size([64, 1, 28, 28]) Shape of y: torch.Size([64]) torch.int64创建模型Creating Models要在 PyTorch 中定义神经网络我们创建一个继承自nn.Module的类。我们在__init__函数中定义网络的层并在forward函数中指定数据如何通过网络。为了加速神经网络中的运算我们将其移动到加速器上如 CUDA、MPS、MTIA 或 XPU。如果当前加速器可用我们将使用它否则使用 CPU。# 检查加速器是否可用如果可用则使用加速器否则使用 CPUdevicetorch.accelerator.current_accelerator().typeiftorch.accelerator.is_available()elsecpuprint(fUsing{device}device)# 打印当前使用的设备类型# 定义模型classNeuralNetwork(nn.Module):# 定义神经网络类继承自 nn.Moduledef__init__(self):# 初始化方法super().__init__()# 调用父类的初始化方法self.flattennn.Flatten()# 创建展平层将 2D 图像展平为 1D 向量self.linear_relu_stacknn.Sequential(# 创建顺序容器按顺序包含各层nn.Linear(28*28,512),# 第一个全连接层输入 784 维输出 512 维nn.ReLU(),# ReLU 激活函数引入非线性nn.Linear(512,512),# 第二个全连接层输入 512 维输出 512 维nn.ReLU(),# ReLU 激活函数nn.Linear(512,10)# 第三个全连接层输入 512 维输出 10 维对应 10 个类别)defforward(self,x):# 前向传播方法定义数据如何通过网络xself.flatten(x)# 将输入图像展平logitsself.linear_relu_stack(x)# 通过全连接层序列得到原始预测值logitsreturnlogits# 返回预测值modelNeuralNetwork().to(device)# 创建模型实例并移动到指定设备print(model)# 打印模型结构输出Using cuda device 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) ) )优化模型参数Optimizing the Model Parameters要训练模型我们需要一个损失函数和一个优化器。loss_fnnn.CrossEntropyLoss()# 定义交叉熵损失函数适用于多分类任务optimizertorch.optim.SGD(model.parameters(),lr1e-3)# 定义 SGD 随机梯度下降优化器学习率为 0.001在单个训练循环中模型对训练数据集进行预测以批次形式输入并通过反向传播预测误差来调整模型的参数。deftrain(dataloader,model,loss_fn,optimizer):# 定义训练函数sizelen(dataloader.dataset)# 获取数据集的样本总数model.train()# 将模型设置为训练模式forbatch,(X,y)inenumerate(dataloader):# 遍历数据加载器中的每个批次X,yX.to(device),y.to(device)# 将数据和标签移动到指定设备# 计算预测误差predmodel(X)# 前向传播得到模型预测lossloss_fn(pred,y)# 计算预测值与真实标签之间的损失# 反向传播loss.backward()# 反向传播计算梯度optimizer.step()# 根据梯度更新模型参数optimizer.zero_grad()# 清零梯度防止梯度累积ifbatch%1000:# 每 100 个批次打印一次loss,currentloss.item(),(batch1)*len(X)# 获取当前损失值和已处理的样本数print(floss:{loss:7f}[{current:5d}/{size:5d}])# 打印损失和进度我们还在测试数据集上检查模型的性能以确保它正在学习。deftest(dataloader,model,loss_fn):# 定义测试函数sizelen(dataloader.dataset)# 获取数据集的样本总数num_batcheslen(dataloader)# 获取批次总数model.eval()# 将模型设置为评估模式test_loss,correct0,0# 初始化测试损失和正确预测计数withtorch.no_grad():# 禁用梯度计算节省内存和计算forX,yindataloader:# 遍历测试数据加载器X,yX.to(device),y.to(device)# 将数据和标签移动到指定设备predmodel(X)# 前向传播得到模型预测test_lossloss_fn(pred,y).item()# 累加批次损失correct(pred.argmax(1)y).type(torch.float).sum().item()# 统计正确预测数test_loss/num_batches# 计算平均测试损失correct/size# 计算准确率print(fTest Error: \n Accuracy:{(100*correct):0.1f}%, Avg loss:{test_loss:8f}\n)# 打印测试结果训练过程在若干次迭代epoch中进行。在每个 epoch 中模型学习参数以做出更好的预测。我们在每个 epoch 打印模型的准确率和损失我们希望看到准确率随着每个 epoch 增加而损失减少。epochs5# 训练 5 个 epochfortinrange(epochs):# 遍历每个 epochprint(fEpoch{t1}\n-------------------------------)# 打印当前 epoch 编号train(train_dataloader,model,loss_fn,optimizer)# 执行训练循环test(test_dataloader,model,loss_fn)# 执行测试循环print(Done!)# 训练完成输出Epoch 1 ------------------------------- loss: 2.302590 [ 64/60000] loss: 2.291843 [ 6464/60000] loss: 2.274084 [12864/60000] loss: 2.267996 [19264/60000] loss: 2.248032 [25664/60000] loss: 2.235034 [32064/60000] loss: 2.235448 [38464/60000] loss: 2.206563 [44864/60000] loss: 2.203167 [51264/60000] loss: 2.173855 [57664/60000] Test Error: Accuracy: 48.5%, Avg loss: 2.165248 Epoch 2 ------------------------------- loss: 2.171659 [ 64/60000] loss: 2.168588 [ 6464/60000] loss: 2.110749 [12864/60000] loss: 2.124941 [19264/60000] loss: 2.070731 [25664/60000] loss: 2.026289 [32064/60000] loss: 2.046067 [38464/60000] loss: 1.972416 [44864/60000] loss: 1.973158 [51264/60000] loss: 1.901610 [57664/60000] Test Error: Accuracy: 59.3%, Avg loss: 1.900692 Epoch 3 ------------------------------- loss: 1.927220 [ 64/60000] loss: 1.909643 [ 6464/60000] loss: 1.786996 [12864/60000] loss: 1.823585 [19264/60000] loss: 1.710886 [25664/60000] loss: 1.668456 [32064/60000] loss: 1.684839 [38464/60000] loss: 1.584657 [44864/60000] loss: 1.603412 [51264/60000] loss: 1.505005 [57664/60000] Test Error: Accuracy: 60.7%, Avg loss: 1.522182 Epoch 4 ------------------------------- loss: 1.580342 [ 64/60000] loss: 1.556963 [ 6464/60000] loss: 1.401661 [12864/60000] loss: 1.472037 [19264/60000] loss: 1.356207 [25664/60000] loss: 1.352045 [32064/60000] loss: 1.366575 [38464/60000] loss: 1.284744 [44864/60000] loss: 1.322070 [51264/60000] loss: 1.234389 [57664/60000] Test Error: Accuracy: 62.9%, Avg loss: 1.253126 Epoch 5 ------------------------------- loss: 1.323655 [ 64/60000] loss: 1.310964 [ 6464/60000] loss: 1.143728 [12864/60000] loss: 1.248905 [19264/60000] loss: 1.131093 [25664/60000] loss: 1.151796 [32064/60000] loss: 1.175902 [38464/60000] loss: 1.103851 [44864/60000] loss: 1.148382 [51264/60000] loss: 1.078236 [57664/60000] Test Error: Accuracy: 64.5%, Avg loss: 1.088746 Done!保存模型Saving Models保存模型的常用方法是序列化内部状态字典包含模型参数。torch.save(model.state_dict(),model.pth)# 将模型参数状态字典保存到文件 model.pthprint(Saved PyTorch Model State to model.pth)# 打印保存成功提示输出Saved PyTorch Model State to model.pth加载模型Loading Models加载模型的过程包括重新创建模型结构并将状态字典加载到其中。modelNeuralNetwork().to(device)# 重新创建模型实例并移动到设备model.load_state_dict(torch.load(model.pth,weights_onlyTrue))# 从文件加载模型参数weights_onlyTrue 是安全最佳实践输出All keys matched successfully此模型现在可用于进行预测。classes[# 定义类别名称列表T-shirt/top,# 0: T恤Trouser,# 1: 裤子Pullover,# 2: 套衫Dress,# 3: 连衣裙Coat,# 4: 外套Sandal,# 5: 凉鞋Shirt,# 6: 衬衫Sneaker,# 7: 运动鞋Bag,# 8: 包Ankle boot,# 9: 踝靴]model.eval()# 将模型设置为评估模式x,ytest_data[0][0],test_data[0][1]# 获取测试数据集的第一张图像和标签withtorch.no_grad():# 禁用梯度计算xx.to(device)# 将图像移动到设备predmodel(x)# 模型预测predicted,actualclasses[pred[0].argmax(0)],classes[y]# 获取预测类别和真实类别print(fPredicted: {predicted}, Actual: {actual})# 打印预测结果和真实标签输出Predicted: Ankle boot, Actual: Ankle boot