pytorch 完整的深度学习流程:数据加载、模型训练到模型测试(详细代码)

一、数据加载

1.使用PyTorch现有数据集

# 准备数据集
datasets_train = torchvision.datasets.CIFAR10(root="train", train=True, transform=torchvision.transforms.ToTensor(),
                                              download=True)
datasets_test = torchvision.datasets.CIFAR10(root="train", train=False, transform=torchvision.transforms.ToTensor(),
                                             download=True)

# 加载器
dataloader_train = DataLoader(dataset=datasets_train, batch_size=64)
dataloader_test = DataLoader(dataset=datasets_test, batch_size=64)

2.自定义数据集加载

自定义数据集需要继承DataSets类,并实现__getItem__ 和 __len__方法

class MyDataset(Dataset):#需要继承torch.utils.data.Dataset类
    def __init__(self):
        # 初始化文件路径或文件名列表。
        # 初始化该类的一些基本参数。
        pass
    def __getitem__(self, index):
        # 1、从文件中读取一个数据(例如,plt.imread)。
        # 2、预处理数据(例如torchvision.Transform)。
        # 3、返回数据对(例如图像和标签)。
        # 这里需要注意的是,第一步:read one data,是一个data
        pass
    def __len__(self):
        # 返回数据集的总大小。
# 具体实例如下
class AnimalDataSet(Dataset):
    def __init__(self, root_dir, transform=None):
        self.root_dir = root_dir   #文件目录
        self.transform = transform #变换
        self.images = os.listdir(self.root_dir)#目录里的所有文件
    
    def __len__(self):
        return len(self.images)
    
    def __getitem__(self,index):#根据索引index返回dataset[index]
        image_index = self.images[index]#根据索引index获取该图片
        img_path = os.path.join(self.root_dir, image_index)#获取索引为index的图片的路径名
        img = io.imread(img_path)# 读取该图片
        label = img_path.split('\\')[-1].split('.')[0]# 根据该图片的路径名获取该图片的label,具体根据路径名进行分割。我这里是"E:\\Python Project\\Pytorch\\dogs-vs-cats\\train\\cat.0.jpg",所以先用"\\"分割,选取最后一个为['cat.0.jpg'],然后使用"."分割,选取[cat]作为该图片的标签
        sample = {'image':img,'label':label}#根据图片和标签创建字典
        
        if self.transform:
            sample = self.transform(sample)#对样本进行变换
        return sample #返回该样本

二、模型搭建

网络继承nn.Module类,并实现__init__ 和 __forward__方法

# 实例如下:
class First(nn.Module):
    def __init__(self):
        super(First, self).__init__()
        self.model = nn.Sequential(
            nn.Conv2d(in_channels=3, out_channels=32, kernel_size=5, padding=2),
            nn.MaxPool2d(kernel_size=2),
            nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, padding=2),
            nn.MaxPool2d(kernel_size=2),
            nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, padding=2),
            nn.MaxPool2d(kernel_size=2),
            nn.Flatten(),
            nn.Linear(in_features=1024, out_features=64),
            nn.Linear(in_features=64, out_features=10)
        )

    def forward(self, x):
        x = self.model(x)
        return x

三、模型训练和测试

epoch = 10  # 定义epoch,表示模型训练的轮次数
for i in range(epoch):
    print("第{}轮训练:".format(i + 1))

	# 表示模型训练阶段,此时需要对模型中的权重梯度进行改变
    first.train()  
    for data in dataloader_train:
        img, target = data
        output = first(img)
        loss = loss_fn(output, target)
        # 放入优化器中优化:梯度清零,反向传播得到每个参数节点的梯度,优化参数
        optim.zero_grad()  # 将上一轮的梯度清零
        loss.backward()  # 反向传播计算梯度
        optim.step()  # 梯度更新
        total_train_step += 1 # 记录训练的次数
        if total_train_step % 100 == 0: # 每训练一百次输出loss
            writer.add_scalar("train_loss", loss.item(), global_step=total_train_step)
            print("训练次数为{}时,loss为:{}".format(total_train_step, loss.item()))

    # 测试步骤:此时不要对模型中的梯度进行改变
    first.eval()
    total_test_loss = 0
    total_accuracy = 0
    # 测试的时候不需要梯度进行调整
    with torch.no_grad():
        for data in dataloader_test:
            img, target = data
            output = first(img)
            loss = loss_fn(output, target)
             # 这里吧loss进行相加是为了后期比较不同的轮次上,整体数据集的loss,如第一个epoch上,整体数据集的loss为12,第二个epoch上,loss为9,固也可以得知模型训练的效果
            total_test_loss = total_test_loss + loss.item()
            accuracy = (output.argmax(1) == target).sum()
            total_accuracy = total_accuracy + accuracy

    print("整体测试集上的loss为:{}".format(total_test_loss))
    print("整体测试集上的准确率为:{}".format(total_accuracy / len(datasets_test)))
    writer.add_scalar("test_accuracy", total_accuracy / len(datasets_test), total_test_step)
    writer.add_scalar("test_loss", total_test_loss, global_step=total_test_step)
    total_test_loss += 1

    # 每一轮训练后,保存模型
    torch.save(first, "first_{}.pth".format(i))

上述模型的训练和测试步骤可以归纳为:

epoch = N  # 定义epoch,表示模型训练的轮次数
for i in range(epoch):
	# 表示模型训练阶段,此时需要对模型中的权重梯度进行改变
    first.train()  
    for data in dataloader_train:
        img, target = data
        output = first(img)
        loss = loss_fn(output, target)
        # 放入优化器中优化:梯度清零,反向传播得到每个参数节点的梯度,优化参数
        optim.zero_grad()  # 将上一轮的梯度清零
        loss.backward()  # 反向传播计算梯度
        optim.step()  # 梯度更新
        # 输出当前loss值

    # 测试步骤:此时不要对模型中的梯度进行改变
    first.eval()
    total_test_loss = 0
    total_accuracy = 0
    # 测试的时候不需要梯度进行调整
    with torch.no_grad():
        for data in dataloader_test:
            img, target = data
            output = first(img)
            loss = loss_fn(output, target)
            total_test_loss = total_test_loss + loss.item()
            accuracy = (output.argmax(1) == target).sum()
            total_accuracy = total_accuracy + accuracy

	# 输出loss和accuracy值
    # 每一轮训练后,保存模型
    torch.save(first, "first_{}.pth".format(i))
    # 上面的几行代码几乎是固定的,然后对模型训练中的指标进行输出
        “”“
        主要是对两个指标进行输出
        1.loss.item():模型训练中的loss值的变化,因为模型的训练主要目的就是为了对loss函数进行优化,使其达到尽可能小,故定时输出loss观察模型的训练效果是很有必要的。语句为print("训练次数为{}时,模型的损失函数值为{}".format(total_train, loss.item()))
        2.accuracy:accuracy等于训练一个批次(即一个内层循环中)中,output与target相等的数量与该批次的总数相比,表示模型训时的精确度
        语句为:
        accuracy = (output.argmax(1) == target).sum() # 一个批次中的一个数据的比较结果,如果output所得结果与target相同,就累加
        total_accuracy = total_accuracy + accuracy # 将一个批次的训练准确的次数都加起来
        print(total_accuracy / len(dataloader_train))
        # 这里的精确度,可以放在一个epoch迭代完成后输出,只输出一个轮次的精确度。    
        ”“”
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值