在初学PyToch和神经网络时面对众多的概念和函数我们可能会很迷惑如雾里看花。这时最好的方法便是做一个简单的小项目理解这个项目的构成虽然博主也是新手但我们不妨一起通过PyTorch来编写一个可以区分蜜蜂和蚂蚁的net。这是蜜蜂和蚂蚁训练集测试集的下载地址来源于B站视频评论区。首先是我们需要的包import torch import torch.nn as nn import torch.nn.function as F import torchvision #读取图片 from torchvision import transforms然后第一步是录入我们训练和测试用的照片。先设定好照片的统一格式transformtransforms.Compose([ transforms.Resize((32,32)), #像素统一转换为32*32 #如果想让照片变得清晰点记得多加几个卷积层 transforms.Tensor #统一转化为张量 ])然后导入训练照片和测试照片trainsettorchvision.datasets.Imagefloder( rootr训练照片储存地址,#Python中地址的\会和\n混淆所以一般在前面加个r或者用\\ trainsformtransform ) trainloadertorch.utils.data.DataLoader( trainset, #定义如何给net图片 batch_size4, #每次会给四张图片 shuffleTrue, #每次完整的训练伦次会打乱照片顺序 num_wokers0 #单进程运行 ) #同理定义测试集 testsettorchvision.datasets.Imagefloder( rootr训练照片储存地址 trainsformtransform ) testloadertorch.utils.data.DataLoader( trainset, #定义如何给net图片 batch_size4, #每次会给四张图片 shuffleTrue, #每次完整的训练伦次会打乱照片顺序 num_wokers0 #单进程运行 ) #定义种类 classes(ants,bees)接下来开始定义netclass Net(nn.Module): def __init__(self): super(Net,self).__init__ #标准格式 self.conv1nn.Conv2d(3,6,5) #定义第一个卷积层3代表彩色照片6代表6个卷积核 #5代表每个卷积核尺寸为5*5 self.poolnn.MaxPool2d(2,2) #定义池化矩阵 self.conv2nn.Conv2d(6,16,5) #定义第二个卷积层 self.fc1nn.Linear(16*5*5,120)#16和最后一个卷积层输出对应5*5由公式计算得到 self.fc2nn.Linear(120,84) #这里先转换为120再到84最后到2ants和bees是 self.fc3nn.Linear(84,2) #公式写法当然也可以直接由120到2 def forward(self,x): xself.pool(F.relu(self.conv1(x))) #按顺序池化 xself.pool(F.relu(self.conv2(x))) xtorch.flatten(x,1) #展平fc只接收一维变量 xF.relu(self.fc1(x)) xF.relu(self.fc2(x)) xself.fc3(x) return x #输出结果 netNet()在fc1中的5*5原自公式其中W指照片原尺寸K代表卷积核大小或池化大小P代表填充默认为零S代表步长经过卷积核一般为1经过池化矩阵我们这里为2。也就是说如果我们统一的图片尺寸是256*256那么经过两组卷积池化后会尺寸变成61*61即fc1的括号变成16*61*61120这会相当麻烦所以如果大家想取大像素还请适当增加卷积层个数。接下来我们开始梯度下降criterionnn.CrossEntropyLoss() optimizertorch.optim.SGD(net.parameters(),lr0.01,momentum0.9)#优化器选择带动量的SGD print(开始训练) for epoch in range(训练轮数) for i , data in enumerate(trainloader,0): inputs,labels data outputsnet(inputs) optimitzer.zero_grad() #每次梯度记得归零 losscriter(outputs,labels) loss.backward optimizer.step() print(训练完成) #储存训练结束后的参数 PATHr\-.pth #储存的地址记得提前建好.pth文件 torch.save(net.state_dict(),PATH)最后我们对训练完成后的net进行测试snet.load_state_dict(torch.load(PATH)) #读取上面储存的参数 net.eval() #结束学习即下面运行测试集时不进行迭代 total0 correct0 with torch.no_grad(): #不计算梯度节约算力 for data in testloader: images , labels data outputsnet(images) _, predicted torch.max(outputs,1)# _,指把返回的images值舍弃 #毕竟我们只在意labels对不对 #最后的1指的是一维 #不直接使用totallen(testset)的原因是电脑会舍弃总数对每组照片的余数 total labels.size(0) correct (predicted labels).sum().itrm() print(f正确率为{100*correct//total}%。)至此我们的分辨蜜蜂和蚂蚁的神经网络就此写完了接下来我们可以随便测试一张照片同时想要直接读取存好的地址不重新训练浪费时间可以这样写import os PATHr-\.pth #训练后参数储存的地址 if os.path.exists(PATH): net.load_state_dict(torch.load(PATH)) else: #训练过程 #…………然后from PIL import Image image_pathr你想测试的照片地址 imgImage.open(image_path).convert(RGB) img_tensortransfrom(img) #将我们选择的照片变为3*32*32的张量 img_tensorimg_tensor.unsqueeze(0) #在这个三维张量前再插入一个维度批次1 #因为Conv2d只支持四维变量 with torch.no_grad: outputsnet(img) -, predicted torch.max(outputs,1) resultpredicted.item() print(classes[result]) #输出具体类别最后是如何运用显卡GPU加速我们的训练devicetorch.device(cuda:0) #首先把net转移进GPU netNet() net.to(device) #最后记得把数据也转移进GPUnet和数据必须同时在CPU或者同时在GPU #……训练过程…… inputs inputs.to(device) labels labels.to(device) #……正常后续流程……最后说说题外话我感觉用PyCharm编写Python中的会方便很多它会直接提醒你括号里的数字代表什么
从零开始运用PyTorch构建神经网络实现分辨蚂蚁和蜜蜂
在初学PyToch和神经网络时面对众多的概念和函数我们可能会很迷惑如雾里看花。这时最好的方法便是做一个简单的小项目理解这个项目的构成虽然博主也是新手但我们不妨一起通过PyTorch来编写一个可以区分蜜蜂和蚂蚁的net。这是蜜蜂和蚂蚁训练集测试集的下载地址来源于B站视频评论区。首先是我们需要的包import torch import torch.nn as nn import torch.nn.function as F import torchvision #读取图片 from torchvision import transforms然后第一步是录入我们训练和测试用的照片。先设定好照片的统一格式transformtransforms.Compose([ transforms.Resize((32,32)), #像素统一转换为32*32 #如果想让照片变得清晰点记得多加几个卷积层 transforms.Tensor #统一转化为张量 ])然后导入训练照片和测试照片trainsettorchvision.datasets.Imagefloder( rootr训练照片储存地址,#Python中地址的\会和\n混淆所以一般在前面加个r或者用\\ trainsformtransform ) trainloadertorch.utils.data.DataLoader( trainset, #定义如何给net图片 batch_size4, #每次会给四张图片 shuffleTrue, #每次完整的训练伦次会打乱照片顺序 num_wokers0 #单进程运行 ) #同理定义测试集 testsettorchvision.datasets.Imagefloder( rootr训练照片储存地址 trainsformtransform ) testloadertorch.utils.data.DataLoader( trainset, #定义如何给net图片 batch_size4, #每次会给四张图片 shuffleTrue, #每次完整的训练伦次会打乱照片顺序 num_wokers0 #单进程运行 ) #定义种类 classes(ants,bees)接下来开始定义netclass Net(nn.Module): def __init__(self): super(Net,self).__init__ #标准格式 self.conv1nn.Conv2d(3,6,5) #定义第一个卷积层3代表彩色照片6代表6个卷积核 #5代表每个卷积核尺寸为5*5 self.poolnn.MaxPool2d(2,2) #定义池化矩阵 self.conv2nn.Conv2d(6,16,5) #定义第二个卷积层 self.fc1nn.Linear(16*5*5,120)#16和最后一个卷积层输出对应5*5由公式计算得到 self.fc2nn.Linear(120,84) #这里先转换为120再到84最后到2ants和bees是 self.fc3nn.Linear(84,2) #公式写法当然也可以直接由120到2 def forward(self,x): xself.pool(F.relu(self.conv1(x))) #按顺序池化 xself.pool(F.relu(self.conv2(x))) xtorch.flatten(x,1) #展平fc只接收一维变量 xF.relu(self.fc1(x)) xF.relu(self.fc2(x)) xself.fc3(x) return x #输出结果 netNet()在fc1中的5*5原自公式其中W指照片原尺寸K代表卷积核大小或池化大小P代表填充默认为零S代表步长经过卷积核一般为1经过池化矩阵我们这里为2。也就是说如果我们统一的图片尺寸是256*256那么经过两组卷积池化后会尺寸变成61*61即fc1的括号变成16*61*61120这会相当麻烦所以如果大家想取大像素还请适当增加卷积层个数。接下来我们开始梯度下降criterionnn.CrossEntropyLoss() optimizertorch.optim.SGD(net.parameters(),lr0.01,momentum0.9)#优化器选择带动量的SGD print(开始训练) for epoch in range(训练轮数) for i , data in enumerate(trainloader,0): inputs,labels data outputsnet(inputs) optimitzer.zero_grad() #每次梯度记得归零 losscriter(outputs,labels) loss.backward optimizer.step() print(训练完成) #储存训练结束后的参数 PATHr\-.pth #储存的地址记得提前建好.pth文件 torch.save(net.state_dict(),PATH)最后我们对训练完成后的net进行测试snet.load_state_dict(torch.load(PATH)) #读取上面储存的参数 net.eval() #结束学习即下面运行测试集时不进行迭代 total0 correct0 with torch.no_grad(): #不计算梯度节约算力 for data in testloader: images , labels data outputsnet(images) _, predicted torch.max(outputs,1)# _,指把返回的images值舍弃 #毕竟我们只在意labels对不对 #最后的1指的是一维 #不直接使用totallen(testset)的原因是电脑会舍弃总数对每组照片的余数 total labels.size(0) correct (predicted labels).sum().itrm() print(f正确率为{100*correct//total}%。)至此我们的分辨蜜蜂和蚂蚁的神经网络就此写完了接下来我们可以随便测试一张照片同时想要直接读取存好的地址不重新训练浪费时间可以这样写import os PATHr-\.pth #训练后参数储存的地址 if os.path.exists(PATH): net.load_state_dict(torch.load(PATH)) else: #训练过程 #…………然后from PIL import Image image_pathr你想测试的照片地址 imgImage.open(image_path).convert(RGB) img_tensortransfrom(img) #将我们选择的照片变为3*32*32的张量 img_tensorimg_tensor.unsqueeze(0) #在这个三维张量前再插入一个维度批次1 #因为Conv2d只支持四维变量 with torch.no_grad: outputsnet(img) -, predicted torch.max(outputs,1) resultpredicted.item() print(classes[result]) #输出具体类别最后是如何运用显卡GPU加速我们的训练devicetorch.device(cuda:0) #首先把net转移进GPU netNet() net.to(device) #最后记得把数据也转移进GPUnet和数据必须同时在CPU或者同时在GPU #……训练过程…… inputs inputs.to(device) labels labels.to(device) #……正常后续流程……最后说说题外话我感觉用PyCharm编写Python中的会方便很多它会直接提醒你括号里的数字代表什么