pytorch训练分类器
数据
通常,当您必须处理图像,文本,音频或视频数据时,可以使用将数据加载到 NumPy 数组中的标准 Python 包。 然后,您可以将该数组转换为torch.*Tensor
。
- 对于图像,Pillow,OpenCV 等包很有用
- 对于音频,请使用 SciPy 和 librosa 等包
- 对于文本,基于 Python 或 Cython 的原始加载,或者 NLTK 和 SpaCy 很有用
专门针对视觉,我们创建了一个名为torchvision
的包,其中包含用于常见数据集(例如 Imagenet,CIFAR10,MNIST 等)的数据加载器,以及用于图像(即torchvision.datasets
和torch.utils.data.DataLoader
)的数据转换器。
这提供了极大的便利,并且避免了编写样板代码。
在本教程中,我们将使用 CIFAR10 数据集。 它具有以下类别:“飞机”,“汽车”,“鸟”,“猫”,“鹿”,“狗”,“青蛙”,“马”,“船”,“卡车”。 CIFAR-10 中的图像尺寸为3x32x32
,即尺寸为32x32
像素的 3 通道彩色图像。
训练图像分类器
我们将按顺序执行以下步骤:
- 使用
torchvision
加载并标准化 CIFAR10 训练和测试数据集 - 定义卷积神经网络
- 定义损失函数
- 根据训练数据训练网络
- 在测试数据上测试网络
1.加载并标准化 CIFAR10
使用torchvision
,加载 CIFAR10 非常容易。
1 import torch 2 import torchvision 3 import torchvision.transforms as transforms
TorchVision 数据集的输出是[0, 1]
范围的PILImage
图像。 我们将它们转换为归一化范围[-1, 1]
的张量。 .. 注意:
1 If running on Windows and you get a BrokenPipeError, try setting 2 the num_worker of torch.utils.data.DataLoader() to 0.
1 transform = transforms.Compose( 2 [transforms.ToTensor(), 3 transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) 4 5 trainset = torchvision.datasets.CIFAR10(root='./data', train=True, 6 download=True, transform=transform) 7 trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, 8 shuffle=True, num_workers=2) 9 10 testset = torchvision.datasets.CIFAR10(root='./data', train=False, 11 download=True, transform=transform) 12 testloader = torch.utils.data.DataLoader(testset, batch_size=4, 13 shuffle=False, num_workers=2) 14 15 classes = ('plane', 'car', 'bird', 'cat', 16 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
出:
1 Downloading https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz to ./data/cifar-10-python.tar.gz 2 Extracting ./data/cifar-10-python.tar.gz to ./data 3 Files already downloaded and verified
让我们展示一些训练图像,很有趣。
1 import matplotlib.pyplot as plt 2 import numpy as np 3 4 # functions to show an image 5 6 def imshow(img): 7 img = img / 2 + 0.5 # unnormalize 8 npimg = img.numpy() 9 plt.imshow(np.transpose(npimg, (1, 2, 0))) 10 plt.show() 11 12 # get some random training images 13 dataiter = iter(trainloader) 14 images, labels = dataiter.next() 15 16 # show images 17 imshow(torchvision.utils.make_grid(images)) 18 # print labels 19 print(' '.join('%5s' % classes[labels[j]] for j in range(4)))
出:
1 dog truck frog horse
2.定义卷积神经网络
之前从“神经网络”部分复制神经网络,然后对其进行修改以获取 3 通道图像(而不是定义的 1 通道图像)。
1 import torch.nn as nn 2 import torch.nn.functional as F 3 4 class Net(nn.Module): 5 def __init__(self): 6 super(Net, self).__init__() 7 self.conv1 = nn.Conv2d(3, 6, 5) 8 self.pool = nn.MaxPool2d(2, 2) 9 self.conv2 = nn.Conv2d(6, 16, 5) 10 self.fc1 = nn.Linear(16 * 5 * 5, 120) 11 self.fc2 = nn.Linear(120, 84) 12 self.fc3 = nn.Linear(84, 10) 13 14 def forward(self, x): 15 x = self.pool(F.relu(self.conv1(x))) 16 x = self.pool(F.relu(self.conv2(x))) 17 x = x.view(-1, 16 * 5 * 5) 18 x = F.relu(self.fc1(x)) 19 x = F.relu(self.fc2(x)) 20 x = self.fc3(x) 21 return x 22 23 net = Net()
3.定义损失函数和优化器
让我们使用分类交叉熵损失和带有动量的 SGD。
1 import torch.optim as optim 2 3 criterion = nn.CrossEntropyLoss() 4 optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
4.训练网络
这是事情开始变得有趣的时候。 我们只需要遍历数据迭代器,然后将输入馈送到网络并进行优化即可。
1 for epoch in range(2): # loop over the dataset multiple times 2 3 running_loss = 0.0 4 for i, data in enumerate(trainloader, 0): 5 # get the inputs; data is a list of [inputs, labels] 6 inputs, labels = data 7 8 # zero the parameter gradients 9 optimizer.zero_grad() 10 11 # forward + backward + optimize 12 outputs = net(inputs) 13 loss = criterion(outputs, labels) 14 loss.backward() 15 optimizer.step() 16 17 # print statistics 18 running_loss += loss.item() 19 if i % 2000 == 1999: # print every 2000 mini-batches 20 print('[%d, %5d] loss: %.3f' % 21 (epoch + 1, i + 1, running_loss / 2000)) 22 running_loss = 0.0 23 24 print('Finished Training')
出:
1 [1, 2000] loss: 2.196 2 [1, 4000] loss: 1.849 3 [1, 6000] loss: 1.671 4 [1, 8000] loss: 1.589 5 [1, 10000] loss: 1.547 6 [1, 12000] loss: 1.462 7 [2, 2000] loss: 1.382 8 [2, 4000] loss: 1.389 9 [2, 6000] loss: 1.369 10 [2, 8000] loss: 1.332 11 [2, 10000] loss: 1.304 12 [2, 12000] loss: 1.288 13 Finished Training
让我们快速保存我们训练过的模型:
1 PATH = './cifar_net.pth' 2 torch.save(net.state_dict(), PATH)
5.根据测试数据测试网络
我们已经在训练数据集中对网络进行了 2 次训练。 但是我们需要检查网络是否学到了什么。
我们将通过预测神经网络输出的类别标签并根据实际情况进行检查来进行检查。 如果预测正确,则将样本添加到正确预测列表中。
好的,第一步。 让我们显示测试集中的图像以使其熟悉。
1 dataiter = iter(testloader) 2 images, labels = dataiter.next() 3 4 # print images 5 imshow(torchvision.utils.make_grid(images)) 6 print('GroundTruth: ', ' '.join('%5s' % classes[labels[j]] for j in range(4)))
出:
1 GroundTruth: cat ship ship plane
接下来,让我们重新加载保存的模型(注意:这里不需要保存和重新加载模型,我们只是为了说明如何这样做):
1 net = Net() 2 net.load_state_dict(torch.load(PATH))
好的,现在让我们看看神经网络对以上这些示例的看法:
1 outputs = net(images)
输出是 10 类的能量。 一个类别的能量越高,网络就认为该图像属于特定类别。 因此,让我们获取最高能量的指数:
1 _, predicted = torch.max(outputs, 1) 2 3 print('Predicted: ', ' '.join('%5s' % classes[predicted[j]] 4 for j in range(4)))
出:
1 Predicted: cat ship ship plane
结果似乎还不错。
让我们看一下网络在整个数据集上的表现。
1 correct = 0 2 total = 0 3 with torch.no_grad(): 4 for data in testloader: 5 images, labels = data 6 outputs = net(images) 7 _, predicted = torch.max(outputs.data, 1) 8 total += labels.size(0) 9 correct += (predicted == labels).sum().item() 10 11 print('Accuracy of the network on the 10000 test images: %d %%' % ( 12 100 * correct / total))
出:
1 Accuracy of the network on the 10000 test images: 53 %
看起来比偶然更好,准确率是 10%(从 10 个类中随机选择一个类)。 好像网络学到了一些东西。
嗯,哪些类的表现良好,哪些类的表现不佳:
1 class_correct = list(0. for i in range(10)) 2 class_total = list(0. for i in range(10)) 3 with torch.no_grad(): 4 for data in testloader: 5 images, labels = data 6 outputs = net(images) 7 _, predicted = torch.max(outputs, 1) 8 c = (predicted == labels).squeeze() 9 for i in range(4): 10 label = labels[i] 11 class_correct[label] += c[i].item() 12 class_total[label] += 1 13 14 for i in range(10): 15 print('Accuracy of %5s : %2d %%' % ( 16 classes[i], 100 * class_correct[i] / class_total[i]))
出:
1 Accuracy of plane : 50 % 2 Accuracy of car : 62 % 3 Accuracy of bird : 51 % 4 Accuracy of cat : 32 % 5 Accuracy of deer : 31 % 6 Accuracy of dog : 35 % 7 Accuracy of frog : 77 % 8 Accuracy of horse : 70 % 9 Accuracy of ship : 71 % 10 Accuracy of truck : 52 %
好的,那下一步呢?
我们如何在 GPU 上运行这些神经网络?
在 GPU 上进行训练
就像将张量转移到 GPU 上一样,您也将神经网络转移到 GPU 上。
如果可以使用 CUDA,首先将我们的设备定义为第一个可见的 cuda 设备:
1 device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 2 3 # Assuming that we are on a CUDA machine, this should print a CUDA device: 4 5 print(device)
出:
1 cuda:0
本节的其余部分假定device
是 CUDA 设备。
然后,这些方法将递归遍历所有模块,并将其参数和缓冲区转换为 CUDA 张量:
1 net.to(device)
请记住,您还必须将每一步的输入和目标也发送到 GPU:
1 inputs, labels = data[0].to(device), data[1].to(device)
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~