使用PyTorch训练一个图像分类器实例
如下所示:
importtorch importtorchvision importtorchvision.transformsastransforms importmatplotlib.pyplotasplt importnumpyasnp print("torch:%s"%torch.__version__) print("tortorchvisionch:%s"%torchvision.__version__) print("numpy:%s"%np.__version__)
Out:
torch:1.0.0 tortorchvisionch:0.2.1 numpy:1.15.4
数据从哪儿来?
通常来说,你可以通过一些python包来把图像、文本、音频和视频数据加载为numpyarray。然后将其转换为torch.*Tensor。
图像。Pillow、OpenCV是用得比较多的
音频。scipy和librosa
文本。纯Python或者Cython就可以完成数据加载,可以在NLTK和SpaCy找到数据
对于计算机视觉而言,我们有torchvision包,它可以用来加载一下常用数据集如Imagenet、CIFAR10、MINIST等等,也有一些常用的为图像准备数据转换例如torchvision.datasets和torch.utils.data.DataLoader。
这次的教程中,我们使用CIFAR10数据集,他有‘airplane',‘automobile',‘bird',‘cat',‘deer',‘dog',‘frog',‘horse',‘ship',‘truck'这几个类别的图像。图像大小都是3x32x32的。也就是说,图像都是三通道的,每一张图的尺寸都是32x32。
训练一个图像分类器
步骤如下:
使用torchvision加载、归一化训练集和测试集
定义卷积神经网络
定义损失函数
使用训练集训练网络
使用测试集测试网络
1.加载、归一化CIFAR10
我们可以使用torchvision很轻松的完成
torchvision的数据集是基于PILImage的,数值是[0,1],我们需要将其转成范围为[-1,1]的Tensor
transform=transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5)) ]) trainset=torchvision.datasets.CIFAR10(root='./data',train=True, download=True,transform=transform) trainloader=torch.utils.data.DataLoader(trainset,batch_size=4, shuffle=True,num_workers=4) testset=torchvision.datasets.CIFAR10(root='./data',train=False, download=True,transform=transform) testloader=torch.utils.data.DataLoader(testset,batch_size=4, shuffle=True,num_workers=4) classes=('plane','car','bird','cat', 'deer','dog','frog','horse','ship','truck')
Out:
Downloadinghttps://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gzto./data/cifar-10-python.tar.gz Filesalreadydownloadedandverified
让我们来看看训练集的图片
#显示一张图片 defimshow(img): img=img/2+0.5#逆归一化 npimg=img.numpy() plt.imshow(np.transpose(npimg,(1,2,0))) plt.show() #任意地拿到一些图片 dataiter=iter(trainloader) images,labels=dataiter.next() #显示图片 imshow(torchvision.utils.make_grid(images)) #显示类标 print(''.join('%5s'%classes[labels[j]]forjinrange(4)))
Out:
truckdogshipdog
2.定义卷积神经网络
可以直接复制神经网络的代码,修改里面的几层即可。
importtorch.nnasnn importtorch.nn.functionalasF classNet(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) defforward(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) returnx net=Net()
3.定义损失函数和优化器
使用多分类交叉熵损失函数,和带有momentum的SGD作为优化器
importtorch.optimasoptim criterion=nn.CrossEntropyLoss() optimizer=optim.SGD(net.parameters(),lr=1e-3,momentum=0.9)
4.训练网络
我们直接使用循环语句遍历数据集即可完成训练
nums_epoch=2 forepochinrange(nums_epoch): _loss=0.0 fori,(inputs,labels)inenumerate(trainloader,0): inputs,labels=inputs.to(device),labels.to(device) optimizer.zero_grad() outputs=net(inputs) loss=criterion(outputs,labels) loss.backward() optimizer.step() _loss+=loss.item() ifi%2000==1999:#每2000步打印一次损失值 print('[%d,%5d]loss:%.3f'% (epoch+1,i+1,_loss/2000)) _loss=0.0 print('FinishedTraining')
Out:
[1,2000]loss:1.178 [1,4000]loss:1.200 [1,6000]loss:1.168 [1,8000]loss:1.175 [1,10000]loss:1.185 [1,12000]loss:1.165 [2,2000]loss:1.073 [2,4000]loss:1.066 [2,6000]loss:1.100 [2,8000]loss:1.107 [2,10000]loss:1.083 [2,12000]loss:1.103 FinishedTraining
5.测试网络
这个网络已经训练了两个epoch,我们现在来看看这个网络是不是学到了一些什么东西。
我们让这个神经网络预测几张图片,看看它的答案与真实答案的差别。
下面我们选取一些测试数据集中的数据,看看他们的真实标签。
#展示测试数据集 dataiter=iter(testloader) images,labels=dataiter.next() imshow(torchvision.utils.make_grid(images)) print('GraoundTruth:',''.join(['%5s'%classes[labels[j]]forjinrange(4)]))
Out:
GraoundTruth:shipshipdeership
接着我们让神经网络来给出预测标签
神经网络的输出是10个信号值,信号值最高的那个神经元表示整个网络的预测值,所以我们需要拿到信号最强的那个节点的索引值
#展示预测值 outputs=net(images) _,predicted=torch.max(outputs,1) print('Predicted:',''.join(['%5s'%classes[predicted[j]]forjinrange(4)]))
Out:
Predicted:carshiphorseship
下面我们对整个测试集做一次评估:
#评估测试数据集 correct,total=0,0 withtorch.no_grad(): forimages,labelsintestloader: outputs=net(images) _,predicted=torch.max(outputs,1) total+=labels.size(0) correct+=(labels==predicted).sum().item() print('Accuracyofthenetworkonthe10000testimages:%d%%'%( 100*correct/total))
Out:
Accuracyofthenetworkonthe10000testimages:58%
整个结果比随机猜要好得多(随机猜是10%的概率)。看来我们的神经网络还是学到了点东西。
下面我们来看看它在哪一个类别的分类上做得最好:
#按类标评估 n_classes=len(classes) class_correct,class_total=[0]*n_classes,[0]*n_classes withtorch.no_grad(): forimages,labelsintestloader: outputs=net(images) _,predicted=torch.max(outputs,1) is_correct=(labels==predicted).squeeze() foriinrange(len(labels)): label=labels[i] class_total[label]+=1 class_correct[label]+=is_correct[i].item() foriinrange(n_classes): print('Accuracyof%5s:%.2f%%'%( classes[i],100.0*class_correct[i]/class_total[i] ))
Out:
Accuracyofplane:67.00% Accuracyofcar:71.50% Accuracyofbird:55.20% Accuracyofcat:45.60% Accuracyofdeer:38.20% Accuracyofdog:47.00% Accuracyoffrog:78.80% Accuracyofhorse:55.90% Accuracyofship:72.70% Accuracyoftruck:57.50%
在GPU上训练
就像把Tensor从CPU转移到GPU一样,神经网络也可以转移到GPU上
首先需要检查是否有可用的GPU
device=torch.device("cuda:0"iftorch.cuda.is_available()else"cpu") #假设我们在支持CUDA的机器上,我们可以打印出CUDA设备: print(device)
Out:
cuda:0
我们假设device已经是CUDA设备了
下面命令将递归的将所有模块和参数、缓存转移到CUDA设备上去
net.to(device)
Out:
Net( (conv1):Conv2d(3,6,kernel_size=(5,5),stride=(1,1)) (pool):MaxPool2d(kernel_size=2,stride=2,padding=0,dilation=1,ceil_mode=False) (conv2):Conv2d(6,16,kernel_size=(5,5),stride=(1,1)) (fc1):Linear(in_features=400,out_features=120,bias=True) (fc2):Linear(in_features=120,out_features=84,bias=True) (fc3):Linear(in_features=84,out_features=10,bias=True) )
注意,在训练过程中的传入输入数据时,也需要转移到GPU上
并且,需要重新实例化优化器,否则会报错
inputs,labels=inputs.to(device),labels.to(device)
练习:尝试增加神经网络的宽度。第一个nn.Conv2d的第二个参数和第二个nn.Conv2d的第一个参数的值必须一样。看看会有什么样的效果。
以上这篇使用PyTorch训练一个图像分类器实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。