侧边栏壁纸
  • 累计撰写 5 篇文章
  • 累计创建 0 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

Pytorch学习-训练分类器

Administrator
2022-07-16 / 0 评论 / 1 点赞 / 62 阅读 / 12077 字 / 正在检测是否收录...

训练分类器

一、训练一个分类器

至此,已经完成了对Pyroch构建神经网络的介绍,之后就可以用这些知识来构建一个分类器了。

二、数据处理

一般地,当我们处理图片、文本、音频或者视频数据的时候,我们可以使用python代码来把它转换成numpy数组。然后再把numpy数组转换成torch.xxxTensor。

  • 对于处理图像,常见的lib包括Pillow和OpenCV
  • 对于音频,常见的lib包括scipy和librosa
  • 对于文本,可以使用标准的Python库,另外比较流行的lib包括NLTK和SpaCy

对于视觉问题,PyTorch提供了一个torchvision包(需要单独安装),它对于常见数据集比如Imagenet, CIFAR10, MNIST等提供了加载的方法。并且它也提供很多数据变化的工具,包括torchvision.datasets和torch.utils.data.DataLoader。这会极大的简化我们的工作,避免重复的代码。
这里我们使用CIFAR10数据集。它包括十个类别:”airplane”, “automobile”, “bird”, “cat”, “deer”, “dog”, “frog”, “horse”, “ship”,”truck”。图像的对象是3x32x32,也就是3通道(RGB)的32x32的图片。

三、训练步骤

  • 使用torchvision加载和预处理CIFAR10训练和测试数据集。
  • 定义卷积网络
  • 定义损失函数
  • 用训练数据训练模型
  • 用测试数据测试模型

四、导入数据

通过使用torchvision,我们可以轻松的加载CIFAR10数据集。torchvision读取的datasets是PILImage对象,它的取值范围是[0, 1],我们把它转换到范围[-1, 1]。


transform = transforms.Compose(
 [transforms.ToTensor(),
 transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

trainset = torchvision.datasets.CIFAR10(root='/path/to/data', train=True,
 download=True, transform=transform)
 trainloader = torch.utils.data.DataLoader(trainset, batch_size=4,
 shuffle=True, num_workers=2)

testset = torchvision.datasets.CIFAR10(root='/path/to/data', train=False,
 download=True, transform=transform)
 testloader = torch.utils.data.DataLoader(testset, batch_size=4,
 shuffle=False, num_workers=2)

classes = ('plane', 'car', 'bird', 'cat',
 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')

我们来看几张图片,如下图所示,显示图片的代码如下:

import matplotlib.pyplot as plt
import numpy as np

# 显示图片的函数


def imshow(img):
img = img / 2 + 0.5     #  [-1,1] -> [0,1]
npimg = img.numpy()
plt.imshow(np.transpose(npimg, (1, 2, 0))) # (channel, width, height) -> (width, height, channel)


# 随机选择一些图片
dataiter = iter(trainloader)
images, labels = dataiter.next()

# 显示图片
imshow(torchvision.utils.make_grid(images))
# 打印label
print(' '.join('%5s' % classes[labels[j]] for j in range(4)))

五、定义神经网络

import torch.nn as nn
import torch.nn.functional as F


class Net(nn.Module):
 def __init__(self):
  super(Net, self).__init__()
  self.conv1 = nn.Conv2d(3, 6, 5)
  self.pool = nn.MaxPool2d(2, 2)
  self.conv2 = nn.Conv2d(6, 16, 5)
  self.fc1 = nn.Linear(16 * 5 * 5, 120)
  self.fc2 = nn.Linear(120, 84)
  self.fc3 = nn.Linear(84, 10)
 
 def forward(self, x):
  x = self.pool(F.relu(self.conv1(x)))
  x = self.pool(F.relu(self.conv2(x)))
  x = x.view(-1, 16 * 5 * 5)
  x = F.relu(self.fc1(x))
  x = F.relu(self.fc2(x))
  x = self.fc3(x)
  return x

net = Net()

我们这里使用交叉熵损失函数,Optimizer使用带冲量的SGD。

import torch.optim as optim

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

我们遍历DataLoader进行训练。

    for epoch in range(2):  # 这里只迭代2个epoch,实际应该进行更多次训练

        running_loss = 0.0
        for i, data in enumerate(trainloader, 0):
            # 得到输入
            inputs, labels = data

            # 梯度清零
            optimizer.zero_grad()

            # forward + backward + optimize
            outputs = net(inputs)
            loss = criterion(outputs, labels)
            loss.backward()
            optimizer.step()

            # 定义统计信息
            running_loss += loss.item()
            if i % 2000 == 1999:
                print('[%d, %5d] loss: %.3f' %
                      (epoch + 1, i + 1, running_loss / 2000))
            running_loss = 0.0

    print('Finished Training')

六、在测试数据集上进行测试

我们进行了2轮迭代,可以使用测试数据集上的数据来进行测试。首先我们随机抽取几个样本来进行测试。


dataiter = iter(testloader)
images, labels = dataiter.next()


imshow(torchvision.utils.make_grid(images))
print('GroundTruth: ', ' '.join('%5s' % classes[labels[j]] for j in range(4)))

我们用模型来预测一下,看看是否正确预测:

outputs = net(images)

outputs是10个分类的logits。我们在训练的时候需要用softmax把它变成概率(CrossEntropyLoss帮我们做了),但是预测的时候没有必要,因为我们只需要知道哪个分类的概率大就行。

_, predicted = torch.max(outputs, 1)

print('Predicted: ', ' '.join('%5s' % classes[predicted[j]]
  for j in range(4)))


接下来我们看看在整个测试集合上的效果:

correct = 0
total = 0
with torch.no_grad():
for data in testloader:
 images, labels = data
 outputs = net(images)
 _, predicted = torch.max(outputs.data, 1)
 total += labels.size(0)
 correct += (predicted == labels).sum().item()

print('Accuracy of the network on the 10000 test images: %d %%' % (
 100 * correct / total))

#Accuracy of the network on the 10000 test images: 54 %

看起来比随机的瞎猜要好,因为随机猜的准确率大概是10%的准确率,所以模型确实学到了一些东西。我们也可以看每个分类的准确率:


class_correct = list(0. for i in range(10))
class_total = list(0. for i in range(10))
with torch.no_grad():
    for data in testloader:
        images, labels = data
        outputs = net(images)
        _, predicted = torch.max(outputs, 1)
        c = (predicted == labels).squeeze()
        for i in range(4):
            label = labels[i]
            class_correct[label] += c[i].item()
            class_total[label] += 1

for i in range(10):
    print('Accuracy of %5s : %2d %%' % (
        classes[i], 100 * class_correct[i] / class_total[i]))

结果为:

Accuracy of plane : 57 %
Accuracy of   car : 72 %
Accuracy of  bird : 30 %
Accuracy of   cat : 28 %
Accuracy of  deer : 55 %
Accuracy of   dog : 46 %
Accuracy of  frog : 70 %
Accuracy of horse : 60 %
Accuracy of  ship : 45 %
Accuracy of truck : 74 %
1

评论区