ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

PyTorch-->image classification(图像分类)

2020-10-23 09:01:50  阅读:150  来源: 互联网

标签:labels classification nn -- image torch net data self


使用深度学习框架的流程:

模型定义(包括损失函数的选择)-> 数据处理和加载 -> 训练(可能包含训练过程可视化)-> 测试

 

以下是根据官方教程的练手,其中卷积神经网络的部分会单独开一篇去写原理,目前俺还不太懂,哈哈哈哈!冲鸭!!!

 

  1 # 使用torchvision来加载并归一化CIFAR10数据集
  2 
  3 import torch
  4 import torchvision  # 保存了一些数据集
  5 import torchvision.transforms as transforms  # 进行数据预处理
  6 import torch.nn as nn
  7 import torch.nn.functional as F
  8 import torch.optim as optim
  9 
 10 from torch.autograd import Variable
 11 
 12 
 13 # 定义网络一般继承torch.nn.Module创建新子类
 14 class Net(nn.Module):
 15 
 16     def __init__(self):
 17         super(Net, self).__init__()
 18         # 1 input image channel, 6 output channels, 5*5 square conwolution
 19         # kernel
 20         # 添加卷积层
 21         self.conv1 = nn.Conv2d(3, 6, 5)  # 定义一个输入深度为3,输出为6,卷积核大小为 5*5 的 conv1 变量
 22         self.pool = nn.MaxPool2d(2, 2)  # 最大池化层
 23         self.conv2 = nn.Conv2d(6, 16, 5)  # 输入通道数为6 输出通道数为16
 24         # an affine operation: y = Wx + b
 25         # 3个全连接层
 26         self.fc1 = nn.Linear(16 * 5 * 5, 120)
 27         self.fc2 = nn.Linear(120, 84)
 28         self.fc3 = nn.Linear(84, 10)  # 最终属于10类中的一个
 29 
 30     # 定义前向传播的方法
 31     def forward(self, x):
 32         # 定义forward()函数:可以在此函数中使用任何Tensor操作
 33         # backward()函数被autograd自动定义
 34         # Max pooling over a (2,2) window
 35         # 输入x -> conv1 -> relu -> 2*2窗口的最大池化
 36         # x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
 37         # If the size is a square you can only specify a single number
 38         # x = F.max_pool2d(F.relu(self.conv2(x)), 2)
 39         # view 函数将张量x变形成一维向量形式,总特征数不变,为全连接层做准备
 40         # 为什么这里只关心列数不关心行数呢,因为马上就要进入全连接层了,而全连接层说白了就是矩阵乘法!
 41         #  第一个全连接层的首参数是16*5*5,所以要保证能够相乘,在矩阵乘法之前就要把x调到正确的size
 42         x = self.pool(F.relu(self.conv1(x)))
 43         x = self.pool(F.relu(self.conv2(x)))
 44         x = x.view(-1, 16 * 5 * 5)
 45         x = F.relu(self.fc1(x))
 46         x = F.relu(self.fc2(x))
 47         x = self.fc3(x)
 48         return x
 49 
 50 
 51 # torch.nn中大多数layer在torch.nn.funtional中都有一个与之对应的函数。
 52 # 二者的区别在于:
 53 # torch.nn.Module中实现layer的都是一个特殊的类,都是以class xx来定义的, 会自动提取可学习的参数
 54 # 而 nn.functional中的函数,更像是纯函数,由def function( )定义,只进行简单的数学运算。
 55 # 即二者的区别是functional中的函数是一个确定的不变的运算公式,输入数据产生输出就ok,
 56 # 而深度学习中会有很多权重是在不断更新的,不可能每进行一次forward就用新的权重重新来定义一遍函数来进行计算,所以说就会采用类的方式,以确保能在参数发生变化时仍能使用我们之前定好的运算步骤。
 57 # 从这个分析就可以看出什么时候改用nn.Module中的layer了:
 58 #   如果模型有可学习的参数,最好使用nn.Module对应的相关layer,否则二者都可以使用,没有什么区别。
 59 # 比如此例中的Relu其实没有可学习的参数,只是进行一个运算而已,所以使用的就是functional中的relu函数,
 60 # 而卷积层和全连接层都有可学习的参数,所以用的是nn.Module中的类。
 61 # 不具备可学习参数的层,将它们用函数代替,这样可以不用放在构造函数中进行初始化。
 62 
 63 
 64 # torchvision dataset 输出范围:[0,1]的PILImage,首先需要归一化为[-1,1]的Tensors
 65 # define a transform :可以将多个变换组合在一起,此处为组合了totensor & normalize
 66 transform = transforms.Compose(
 67     [transforms.ToTensor(),
 68      transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])  # first RGB三个通道上的均值 second RGB三个通道上的标准差 用于对RGB图像归一化
 69 # define a trainset,加载后使用上面定义的transform进行变换 (存放位置 为True代表创建的是训练集 为True代表需要从网上下载 使用的变换)
 70 trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
 71 # 后面会通过loader将数据传入网络
 72 # 组合数据集和采样器 在数据集上提供单进程或多进程的迭代器(数据的来源 每批次进入的数据数量 为True代表打乱数据顺序 默认为0代表在主进程中加载,此处为2代表选用用来加载数据的子进程个数)
 73 trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True, num_workers=2)
 74 # define a testset
 75 testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)
 76 
 77 testloader = torch.utils.data.DataLoader(testset, batch_size=4, shuffle=False, num_workers=2)
 78 # 类别需要给定
 79 classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
 80 
 81 # show some examples
 82 import matplotlib.pyplot as plt
 83 import numpy as np
 84 
 85 
 86 # functions to show an image
 87 
 88 def imshow(img):
 89     img = img / 2 + 0.5
 90     npimg = img.numpy()
 91     plt.imshow(np.transpose(npimg, (1, 2, 0)))
 92     plt.show()
 93 
 94 
 95 if __name__ == '__main__':
 96     # get some random training images
 97     dataiter = iter(trainloader)
 98     images, labels = dataiter.next()
 99 
100     # # show
101     # imshow(torchvision.utils.make_grid(images))
102     # # print labes
103     # print(' '.join('%5s' % classes[labels[j]] for j in range(4)))
104 
105     net = Net()
106 
107     # use a Classification Cross-Entropy 分类交叉熵 loss(损失函数) and SGD 动量 with momentum(优化器)
108     # 想把模型搬到GPU上跑,要在定义优化器之前完成.cuda()这一步
109     criterion = nn.CrossEntropyLoss()
110     optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
111 
112     # loop over the dataset multiple times 将数据集循环传给net & momentum
113     # 下面进行两次训练
114     for epoch in range(2):
115 
116         running_loss = 0.0  # 方便对损失函数的值进行输出
117         # enumerate() 既获得索引也获得数据
118         for i, data in enumerate(trainloader, 0):
119             # get the inputs
120             inputs, labels = data  # 从enumerate返回的data 包含数据和标签信息
121             # inputs, labels = Variable(inputs),Variable(labels) 将数据转换成Variable
122             # don't forget!!!
123             optimizer.zero_grad()
124 
125             # forward + backward + optimize
126             outputs = net(inputs)
127             loss = criterion(outputs, labels)
128             loss.backward()
129             # 在定义网络时定义了前向传播函数,但是并没有定义反向传播函数,深度学习是需要反向传播求导的,
130             # Pytorch其实利用的是Autograd模块来进行自动求导,反向传播。
131             # Autograd中最核心的类就是Variable了,它封装了Tensor,并几乎支持所有Tensor的操作,这里可以参考官方给的详细解释:
132             # http: // pytorch.org / tutorials / beginner / blitz / autograd_tutorial.html  # sphx-glr-beginner-blitz-autograd-tutorial-py
133             # 以上链接详细讲述了variable究竟是怎么能够实现自动求导的,怎么用它来实现反向传播的。
134             # 这里涉及到计算图的相关概念
135             # 总结:要计算各个variable的梯度,只需调用根节点的backward方法,Autograd就会自动沿着整个计算图进行反向计算
136             # 而在此例子中,根节点就是loss,所以程序中的loss.backward()
137             # 代码就是在实现反向传播,自动计算所有的梯度。
138             optimizer.step()  # 执行完反向传播之后,更新优化器参数,以便进行下一轮训练
139 
140             # print statistics
141             running_loss += loss.item()
142             # print every 2000 mini-batches
143             if i % 2000 == 1999:
144                 print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 2000))
145                 running_loss = 0.0
146 
147     print('Finished!!!')
148 
149     # save the model
150     PATH = './cifar_net.pth'
151     torch.save(net.state_dict(), PATH)
152 
153     # test the network on the test data
154 
155     dataiter = iter(testloader)
156     images, labels = dataiter.next()  # 根据设置应该是四张图片
157 
158     # print images
159     imshow(torchvision.utils.make_grid(images))
160     print('Ground_Truth: ', ' '.join('%5s' % classes[labels[j]] for j in range(4)))
161 
162     net_1 = Net()
163 
164     net_1.load_state_dict(torch.load(PATH))
165     outputs = net_1(images)
166     _, predited = torch.max(outputs, 1)  # 会返回两个值,但是对第一个不感兴趣
167     # .max() 返回输入Tensor中每行的最大值,并转换成指定的dim(维度)
168     # 指的 the dimension to reduce!并不是在the dimension上去返回最大值。
169     # 理解为:返回最大的索引,即预测出的类别
170     print('Predicted: ', ' '.join('%5s' % classes[predited[j]] for j in range(4)))
171 
172     # performs on the whole dataset
173 
174     correct = 0
175     total = 0
176 
177     with torch.no_grad():
178         for data in testloader:
179             images, labels = data
180             outputs = net_1(images)
181             _, predited = torch.max(outputs.data, 1)
182             total += labels.size(0)
183             correct += (predited == labels).sum().item()
184 
185     print('Accuracy of the network on the 10000 test images: %d %%' % (
186             100 * (correct / total)))
187 
188     # performs on different classes
189     class_correct = list(0. for i in range(10))
190     class_total = list(0. for i in range(10))
191     with torch.no_grad():
192         for data in testloader:
193             images, labels = data
194             outputs = net_1(images)
195             _, predited = torch.max(outputs, 1)
196             c = (predited == labels).squeeze()
197             for i in range(4):  # 每个batch有4个图片!
198                 label = labels[i]
199                 class_correct[label] += c[i].item()
200                 class_total[label] += 1
201 
202     for i in range(10):
203         print('Accuracy of %5s : %2d %%' % (classes[i],
204                                             100 * (class_correct[i] / class_total[i])))
205 
206     # run the neural network on the GPU
207     device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
208     print(device)
209 
210     net.to(device)
211     inputs, labels = data[0].to(device), data[0].to(device)

 

标签:labels,classification,nn,--,image,torch,net,data,self
来源: https://www.cnblogs.com/aluomengmengda/p/13856114.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有