赞
踩
首先,先附链接,b站小土推pytorch讲解,PyTorch深度学习快速入门教程(绝对通俗易懂!)【小土堆】_哔哩哔哩_bilibili
这个视频对于小白来说很友好,学习时间也不长(快一点大概一个白天),结合pytorch官方文档。PyTorch documentation — PyTorch 1.12 documentation
本文章只是记录个人学习过程。有错误的地方欢迎指教,欢迎交流讨论。
如何下载pytorch,包括下载GPU版本(很麻烦的一个过程,各个版本号一定要对应好,本人踩坑已解决)这有一篇文章讲解的很详细:torch.cuda.is_available()返回false——解决办法_Nefu_lyh的博客-CSDN博客
当所有都准备好,我们开始搭建一个自己的特别简单的神经网络。神经网络有固定的模板,太多原理的内容就不叙述,网络上有很多课程包括吴恩达、李宏毅、李沐大神等等等。在这里创建一个CNN类,初始化,然后定义forward,这个简单的方法就是实现了一个加法运算。
- import torch
- from torch import nn
-
-
- class CNN(nn.Module):
- def __init__(self):
- super(CNN, self).__init__()
-
- def forward(self, input):
- output = input + 1
- return output
-
- cnn = CNN()
- x = torch.tensor(1.0)
- output = cnn(x)
- print(output)
程序运行结果为:tensor(2.)。一个简单的神经网络就这样搭建好了,下面我们来看如何搭建一个卷积神经网络也就是CNN。
我们知道卷积神经网络一般包含卷积层(Convolutional layer)、线形层(ReLU)、池化层(Pooling layer)、全连接层(Fully-Connected layer)
层与层之间的相应计算关系在文章开头链接内已经展示的十分清楚详细,包括各个层包括哪些参数,每个参数的作用会影响什么都有!
不爱看视频的,这里有一篇文章包含计算过程:CNN实现过程(卷积神经网络Convolutional Neural Networks)_国服最强貂蝉的博客-CSDN博客_cnn实现
总结来说,我觉得写一个完整的训练过程要把思路理清。首先,应该加载数据集,包括了训练集和测试集。其后构建我们自己想要的卷积神经网络模型,再后定义loss,包括优化器的参数,learning_rate这些。最后,保存我们训练的模型来进行验证。然后开始我们的整个训练过程。
上代码:
- import torch
- import torchvision.datasets
- from torch import nn
- from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
- from torch.utils.data import DataLoader
-
- dataset = torchvision.datasets.CIFAR10("../dataset", train=False, transform=torchvision.transforms.ToTensor(), download=True)
- dataloader = DataLoader(dataset, batch_size = 64)
-
- class CNN(nn.Module):
- def __init__(self):
- super(CNN, self).__init__()
- self.conv1 = Conv2d(3, 32, 5, padding=2)
- self.maxpool1 = MaxPool2d(2)
- self.conv2 = Conv2d(32, 32, 5, padding=2)
- self.maxpool2 = MaxPool2d(2)
- self.conv3 = Conv2d(32, 64, 5, padding=2)
- self.maxpool3 = MaxPool2d(2)
- self.flatten = Flatten()
- self.linear1 = Linear(1024, 64)
- self.linear2 = Linear(64, 10)
- def forward(self, x):
- x = self.conv1(x)
- x = self.maxpool1(x)
- x = self.conv2(x)
- x = self.maxpool2(x)
- x = self.conv3(x)
- x = self.maxpool3(x)
- x = self.flatten(x)
- x = self.linear1(x)
- x = self.linear2(x)
- return x
-
- loss = nn.CrossEntropyLoss()
- cnn = CNN()
-
- for data in dataloader:
- imgs, targets = data
- outputs = cnn(imgs)
- result_loss = loss(outputs, targets)
- result_loss.backward()
- print(result_loss)
我们会看到在我们定义这个卷积神经网络的时候,创建了很多层,代码看起来很繁琐,我们可以使用Sequential进行优化,同样上面这个程序还不包含优化器的一些设置,下面我们来进行优化。
- import torch
- import torchvision.datasets
- from torch import nn
- from torch.utils.data import DataLoader
- from torch.utils.tensorboard import SummaryWriter
- from model import *
- import time
-
-
- device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
-
- train_data = torchvision.datasets.CIFAR10("../dataset", train=True, transform=torchvision.transforms.ToTensor(),
- download=True)
- test_data = torchvision.datasets.CIFAR10("../dataset", train=False, transform=torchvision.transforms.ToTensor(),
- download=True)
- train_data_size = len(train_data)
- test_data_size = len(test_data)
-
- print("训练数据集的长度为:{}".format(train_data_size))
- print("测试数据集的长度为:{}".format(test_data_size))
-
- train_dataloader = DataLoader(train_data, batch_size=64)
- test_dataloader = DataLoader(test_data, batch_size=64)
-
-
- cnn = CNN()
- cnn = cnn.to(device)
-
- loss_fn = nn.CrossEntropyLoss()
- loss_fn = loss_fn.to(device)
-
- learning_rate=0.01 # 1e-1
- optimizer = torch.optim.SGD(cnn.parameters(), lr=learning_rate)
-
- total_train_step = 0
- total_test_step = 0
- epoch = 10
-
- writer = SummaryWriter("../train_logs")
-
- start_time = time.time()
- for i in range(epoch):
- print("---------------第{}轮训练开始:-------------------".format(i+1))
-
- cnn.train()
- for data in train_dataloader:
- imgs, targets = data
- imgs = imgs.to(device)
- targets = targets.to(device)
-
- outputs = cnn(imgs)
- loss = loss_fn(outputs, targets)
-
- # 优化
- optimizer.zero_grad()
- loss.backward()
- optimizer.step()
-
- total_train_step = total_train_step + 1
-
- if total_train_step % 100 == 0:
- end_time = time.time()
- print(end_time - start_time)
- print("训练次数:{}, Loss:{}".format(total_train_step, loss.item()))
- writer.add_scalar("train_loss", loss.item(), total_train_step)
-
-
- # 测试步骤开始
- cnn.eval()
- total_test_loss = 0
- total_accuracy = 0
-
- with torch.no_grad():
- for data in test_dataloader:
- imgs, targets = data
- imgs = imgs.to(device)
- targets = targets.to(device)
-
- outputs = cnn(imgs)
- loss = loss_fn(outputs, targets)
- total_test_loss = total_test_loss + loss
- accuracy = (outputs.argmax(1) == targets).sum()
- total_accuracy = total_accuracy + accuracy
-
- print("整体测试集上的Loss:{}".format(total_test_loss))
- print("整体测试集上的正确率:{}".format(total_accuracy/test_data_size))
- writer.add_scalar("test_loss", total_test_loss, total_test_step)
- writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)
- total_test_step = total_test_step + 1
-
- torch.save(cnn, "cnn_{}.pth".format(i+1))
- print("模型已保存")
-
- writer.close()
一个完整的训练过程就如上图所示,训练时使用了GPU进行训练,其中需要注意的是我们在测试时有 model.eval() 以及 with torch.no_grad()。
model.eval()是切换到测试程序,这时候不会更新模型的k,b参数,通知dropout层和batchnorm层在train和val中间进行切换。在train模式,dropout层会按照设定的参数p设置保留激活单元的概率(保留概率=p,比如keep_prob=0.8),batchnorm层会继续计算数据的mean和var并进行更新。在val模式下,dropout层会让所有的激活单元都通过,而batchnorm层会停止计算和更新mean和var,直接使用在训练阶段已经学出的mean和var值。
with torch.no_grad()在进行模型训练的过程中,因为要监控模型的性能,在跑完若干个epoch
训练之后,需要进行一次在验证集上的性能验证。一般来说,在验证或者是测试阶段,因为只是需要跑个前向传播(forward)就足够了,因此不需要保存变量的梯度。
下面我们来对训练的模型进行一个验证,这是我在网上找到的一张猫的图片,看看模型是否能够命中。首先,我们需要对找到的图片进行一些处理,然后加载我们之前训练过程中训练结果最好的那一次模型。
这是我们数据集的label,程序的输出如下:
我们的模型对这张图片分类正确!![3]就是cat。同样的,我又对其他两张照片进行判断,不过遗憾的是并没有猜对。这个训练模型的正确率才百分之60多一些,看起来正确率并不是那么高。一方面可能是数据集较小,而且图片是32x32,比较模糊。另一方面,训练的次数可能较少,后面我会探究一下如何优化模型能够提高正确率。
欢迎交流讨论!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。