其他分享
首页 > 其他分享> > Pytorch ----- 数据集 (dataset) 数据加载器 (dataloader) num_workeres工作原理 及调整方法 ~~学习笔记

Pytorch ----- 数据集 (dataset) 数据加载器 (dataloader) num_workeres工作原理 及调整方法 ~~学习笔记

作者:互联网

数据集 (dataset): 应该支持索引取数据
数据加载器 (dataloader):主要用于拿出mini_batch

前几节使用数据直接将数据用文件加载,然后将所有数据都放进去。像这样。。。。。。
在这里插入图片描述

Mini-batch 循环使用:
嵌套循环,外层循环次数控制,内层每一次执行一个Mini_batch。每一次循环跑一边所有的Mini_batch.
在这里插入图片描述

几个名词。。

打乱->分组 分成若干个batch。之后可以通过迭代拿出来每一个Batch,然后遍历Batch拿出其中数据。

在这里插入图片描述

dataset和dataloader类的使用:
Dataset是抽象类,不能实例化,只能被子类继承使用。
Dataloader 可以实例化
在这里插入图片描述
魔法方法 getitem 为了 实现下标索引功能。
魔法方法 len 显然是实现求长度或者数据条数的功能。

DataLoader 中的参数:
dataset=dataset 传递数据集对象。
batch_size = 32 指定batch_size大小。
shuffle = True 打乱样本顺序 。
num_workers = 2 读数据构成Mini_batch时,使用几个进程进行多线程处理。

Pytorch 0.4版本在window中可能遇到多线程系统内核调用报错问题。 解决:将两层循环放到 main函数里。

数据集的整体实现:
在这里插入图片描述
filepath 文件路径
在这里插入图片描述
xy是一个矩阵,shape方法返回xy有几行几列(元组)。取其[0],则self.len 得到 xy中的行数,即有多少个数据样本。

在这里插入图片描述
构造数据对象,传路径过去。
最后 加上数据加载器。

后面训练循环的变化:
在这里插入图片描述
epoch 所有数据都跑100遍。
内层循环对前面数据加载器对象做迭代,用enumerate仅仅是想看到现在是第几次迭代了。
从train_loader里拿出x[i] y[i]数据放到了 inputs和labels里。loader自动将xy变成Tensor类型。所以 inputs和labels都是张量。
后面不变,损失和函数,梯度清零,反向传播,更新权重。

数据依旧使用上次糖尿病人的数据,
完整代码:



import torch
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
import numpy as np
import time
# 数据准备
filepath = './diabetes.csv'

class DiabetesDataset(Dataset):
    def __init__(self,filepath):
        xy = np.loadtxt(filepath,delimiter = ',',dtype=np.float32)
        self.len = xy.shape[0]
        self.x_data = torch.from_numpy(xy[:,:-1])
        self.y_data = torch.from_numpy(xy[:,[-1]])

    def __getitem__(self, index):
        return self.x_data[index] , self.y_data[index]

    def __len__(self):
        return self.len

dataset = DiabetesDataset(filepath)
train_loader = DataLoader(dataset=dataset,
                          batch_size=32,
                          shuffle=True,
                          num_workers=0)

# 训练模型
class Model(torch.nn.Module):
    def __init__(self):
        super(Model,self).__init__()
        # 维度变化
        self.linear1 = torch.nn.Linear(8,6)
        self.linear2 = torch.nn.Linear(6,4)
        self.linear3 = torch.nn.Linear(4,1)
        # 加入激活因子
        self.sigmoid = torch.nn.Sigmoid()
    def forward(self,x):
        # 多层神经网络传递
        x = self.sigmoid(self.linear1(x))
        x = self.sigmoid(self.linear2(x))
        x = self.sigmoid(self.linear3(x))
        return x


time_ll = []
loss_ll = []
model = Model()

# 损失函数
criterion = torch.nn.BCELoss(reduction='mean')

# 优化器
optimizer = torch.optim.SGD(model.parameters(),lr=0.01)

if __name__ == '__main__':
    start_time = time.time()
    for epoch in range(10):
        for i,data in enumerate(train_loader):
            x, y = data
            # 前馈
            y_pre = model.forward(x)
            # 损失
            loss = criterion(y_pre,y)
            loss_ll.append(loss.item())
            # 梯度清零
            optimizer.zero_grad()
            # 反向传播
            loss.backward()
            # 更新
            optimizer.step()
            # print("当前正在训练第"+ str(i) +"块batch")
    end_time = time.time()
    print("程序运行时间为:",end_time-start_time)
    print("损失值",loss_ll[-1])

在使用了mini_batch分块 操作之后可以看到cpu多核心都工作起来了。
在这里插入图片描述
而在之前的模型训练中将全部的数据都直接扔进函数,只有几个cpu核心在工作。
在这里插入图片描述

后续不断更改 num_workers后发现 只有在0的时候 即仅使用主进程的情况下 时间是最短的 ,大概训练10次的时间为1秒,将num_workers改为1后 时间直增到七秒。更改为2之后的时间大概为8秒。
在增加到三个核心时分页区报错,可以直接去你装pycharm的盘,设置一下该盘的虚拟内存分配就可以了。
我设置完成之后,直接从0-8设置 num_workers 发现每多一个核心进程,运行时间就多大概一秒钟。

关于 num_workers的工作原理:

所以:

标签:__,workers,torch,workeres,dataloader,batch,dataset,num,self
来源: https://blog.csdn.net/qq_38737428/article/details/121208034