【Pytorch】小土堆笔记(未完成)
transforms
在训练的过程中,神经网络模型接收的数据类型是 Tensor,而不是 PIL 对象,因此我们还需要对数据进行预处理操作,比如图像格式的转换。
同时我们可以对图片进行一系列图像变换与增强操作,例如裁切边框、调整图像比例和大小、标准化等,以便模型能够更好地学习到数据的特征。
这些操作都可以通过torchvision.transforms来完成,所以transforms可以理解为图像预处理工具包。
transforms具体用法可以参照:3.2 PyTorch_Torchvision-02:transforms - 知乎 (zhihu.com)
dataset_transform = torchvision.transforms.Compose([ torchvision.transforms.ToTensor()]) train_set = torchvision.datasets.CIFAR10(root="./dataset", train=True, transform=dataset_transform, download=True) test_set = torchvision.datasets.CIFAR10(root="./dataset", train=False, transform=dataset_transform, download=True)
Compose可以将各种操作组合在一起,在数据里量足够的情况下我们一般使用ToTensor足够,不需要进行图片增强操作,所以我们可以简写:
test_data = torchvision.datasets.CIFAR10("../dataset", train=False, transform=torchvision.transforms.ToTensor())
dataloader
① Dataset只是去告诉我们程序,我们的数据集在什么位置,数据集第一个数据给它一个索引0,它对应的是哪一个数据。
② Dataloader就是把数据加载到神经网络当中,Dataloader所做的事就是每次从Dataset中取数据,至于怎么取,是由Dataloader中的参数决定的。
test_data = torchvision.datasets.CIFAR10("../dataset", train=False, transform=torchvision.transforms.ToTensor()) test_loader = DataLoader(test_data, batch_size=64, shuffle=True, num_workers=0, drop_last=True)
这里的四个参数,分别解释一下:
batch_size 就是每批次大小
shuffle 是否打乱数据,推荐设置为True
num_workers 这个参数决定了有几个进程来处理data loading。0意味着所有的数据都会被load进主进程。(默认为0)
drop_last 如果设置为True:这个是对最后的未完成的batch来说的,比如你的batch_size设置为64,而一个epoch只有100个样本,那么训练的时候后面的36个就被扔掉了…
如果为False(默认),那么会继续正常执行,只是最后的batch_size会小一点(也有可能会报错)
在加载数据集后,我们可以使用以下结构来访问每一批数据的内容。
writer = SummaryWriter("logs/11_dataloader") # 测试数据集使用dataLoder后的结果 step = 0 for data in test_loader: imgs, targets = data # print(imgs.shape) # print(targets) writer.add_images("Epoch:{}".format(), imgs, step) step = step+1 writer.close()
加载、修改、保存模型
import torchvision from torch import nn vgg16 = torchvision.models.vgg16(weights= torchvision.models.VGG16_Weights.DEFAULT) train_data = torchvision.datasets.CIFAR10("../dataset", train=True, transform=torchvision.transforms.ToTensor(), download=True) # x下面的几种常见的修改方式,效果都一样 # vgg16.add_module('add_linear', nn.Linear(1000, 10)) # print(vgg16) # # vgg16.classifier.add_module('add_linear', nn.Linear(1000, 10)) # print(vgg16) vgg16.classifier[6] = nn.Linear(4096, 10)
import torch import torchvision vgg16 = torchvision.models.vgg16() # 保存方式 1 模型结构+模型参数 torch.save(vgg16, "vgg16_method1.pth") # 读取方式 model1 = torch.load("vgg16_method1.pth") #print(model1) # 保存方式 2 模型参数(官方推荐) torch.save(vgg16.state_dict(), "vgg16_method2.pth") # 读取方式 vgg16_new = torchvision.models.vgg16() vgg16_new.load_state_dict(torch.load("vgg16_method2.pth")) # vgg16_new = torch.load("vgg16_method2.pth") print(vgg16_new)
模型的训练(cpu)
import torch.optim.optimizer import torchvision from torch import nn from torch.utils.data import DataLoader from torch.utils.tensorboard import SummaryWriter from model import MyModel # 准备数据集 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(f"测试数据集的长度为:{test_data_size}") # 利用 DataLoader 来加载数据集 train_dataloader = DataLoader(train_data, batch_size=64) test_dataloader = DataLoader(test_data, batch_size=64) # 创建网络 myModel = MyModel() # 损失函数 loss_fn = nn.CrossEntropyLoss() # 优化器 # learning_rate = 0.01 # 1e-2 = 1 * 10^-2 = 1/100 = 0.01 learning_rate = 1e-2 # 0.01 optimizer = torch.optim.SGD(myModel.parameters(), lr=learning_rate) # 设置训练网络的一些参数 # 训练训练的次数 total_train_step = 0 # 记录训练的次数 total_test_step = 0 # 训练的轮数 epoch = 10 # 添加tensorboard writer = SummaryWriter("./logs/27_model_train") for i in range(epoch): print("------------------第{}轮训练------------------".format(i+1)) myModel.train() # 训练步骤开始 for data in train_dataloader: imgs, targets = data outputs = myModel(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: print("训练次数:{}, Loss:{}".format(total_train_step, loss.item())) writer.add_scalar("train_loss", loss.item(), total_train_step) # 测试步骤开始 myModel.eval() total_test_loss = 0 total_accuracy = 0 with torch.no_grad(): for data in test_dataloader: imgs, targets = data outputs = myModel(imgs) loss = loss_fn(outputs, targets) total_test_loss = total_test_loss + loss.item() 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 + 1 torch.save(myModel, "MyModel_{}.pth".format(i)) print("模型已保存") writer.close()
模型训练(GPU)
import torch.optim.optimizer import torchvision from torch import nn from torch.utils.data import DataLoader from torch.utils.tensorboard import SummaryWriter from model import MyModel import time # 准备数据集 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(f"测试数据集的长度为:{test_data_size}") # 利用 DataLoader 来加载数据集 train_dataloader = DataLoader(train_data, batch_size=64, drop_last=True) test_dataloader = DataLoader(test_data, batch_size=64, drop_last=True) # 创建网络 myModel = MyModel() myModel = myModel.cuda() # 使用GPU训练 # 损失函数 loss_fn = nn.CrossEntropyLoss() loss_fn = loss_fn.cuda() # 使用GPU训练 # 优化器 # learning_rate = 0.01 # 1e-2 = 1 * 10^-2 = 1/100 = 0.01 learning_rate = 1e-2 # 0.01 optimizer = torch.optim.SGD(myModel.parameters(), lr=learning_rate) # 设置训练网络的一些参数 # 训练训练的次数 total_train_step = 0 # 记录训练的次数 total_test_step = 0 # 训练的轮数 epoch = 10 # 添加tensorboard writer = SummaryWriter("./logs/27_model_train") start_time = time.time() for i in range(epoch): print("------------------第{}轮训练------------------".format(i + 1)) myModel.train() # 训练步骤开始 for data in train_dataloader: imgs, targets = data imgs = imgs.cuda() # GPU加速 targets = targets.cuda() outputs = myModel(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("用时:{}".format(end_time - start_time)) print("训练次数:{}, Loss:{}".format(total_train_step, loss.item())) writer.add_scalar("train_loss", loss.item(), total_train_step) # 测试步骤开始 myModel.eval() total_test_loss = 0 total_accuracy = 0 with torch.no_grad(): for data in test_dataloader: imgs, targets = data imgs = imgs.cuda() # GPU加速 targets = targets.cuda() outputs = myModel(imgs) loss = loss_fn(outputs, targets) total_test_loss = total_test_loss + loss.item() 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 + 1 torch.save(myModel, "MyModel_{}.pth".format(i)) print("模型已保存") writer.close()