我正在训练一个神经网络,总的来说>15GB的数据在一个文件夹中,该文件夹有多个pickle文件,每个文件包含两个列表,每个列表包含多个值.

  • 文件泡菜
  • 文件2.泡菜
  • ...
  • ...
  • 文件\u n.pickle

每个文件\u*.pickle包含一个可变长度的列表(列表x和列表y).

如何在没有内存问题的情况下加载所有数据来训练模型?

推荐答案

通过实现Pytorch提供的定制dataset类,我们需要实现三个方法,以便Pytorch loader可以处理您的数据

  • __len__
  • __getitem__
  • __init__

让我们来看看如何分别实现它们中的每一个.

  • __init__

如上所述,主要思想是使用prefix sum一次性"处理"所有数据集,因此逻辑是,无论何时以后需要访问特定索引,只需查看prefix_sum_idx即可查看此idx出现的位置.

prefix sum illustration

在上图中,假设我们需要访问索引150.由于前缀sum,我们现在可以知道第二个.pickle文件中存在150个.我们仍然需要一个快速的机制来知道idxprefix_sum_idx中的位置.这将在__getitem__中解释

  • __getitem__

判断bisect\u right()文档以了解其工作方式的详细信息,但只需返回排序列表中最右边的位置,即可插入给定元素并保持其排序.在我们的方法中,我们只对以下问题感兴趣,"为了获得适当的数据,我应该访问哪个文件".更重要的是,它在O(log n)

  • __len__

为了获得数据集的长度,我们循环遍历中的每个文件,并累积结果,如图__init__所示.

完整的代码示例如下所示:

import pickle
import torch
import torch.nn as nn
import numpy
import os 
import bisect
from torch.utils.data import Dataset, DataLoader
from src.data.make_dataset import main
from torch.nn import functional as F

class dataset(Dataset):
  def __init__(self):

    # Original Data has the following format
    """
    dict_object = 
    {
        "x":[],
        "y":[]
    }
    """
    DIRECTORY = "data/raw"
    self.dataset_file_name = os.listdir(DIRECTORY)
    self.dataset_file_name_index = 0
    self.dataset_length =0
    self.prefix_sum_idx = list()
    # Loop over each file and calculate the length of overall dataset
    # you might need to check if file_name is file
    for file_name in os.listdir(DIRECTORY):
    with (open(f'{DIRECTORY}/{file_name}', "rb")) as openfile:
        dict_object = pickle.load(openfile)
        curr_page_sum = len(dict_object["x"]) + len(dict_object["y"])
        self.prefix_sum_idx.append(curr_page_sum)
        self.dataset_length += curr_page_sum
    # prefix sum so we have an idea of where each index appeared in which file. 
    for i in range (1,len(self.prefix_sum_idx)):
    self.prefix_sum_idx[i] = self.prefix_sum_idx[i] + self.prefix_sum_idx[i-1]

    assert self.prefix_sum_idx[-1] == self.dataset_length
    self.x = []
    self.y = []

    



def read_pickle_file(self, idx):
 file_name = self.dataset_file_name[idx]
 dict_object = dict()
 with (open(f'{YOUR_DIRECTORY}/{file_name}', "rb")) as openfile:
     dict_object = pickle.load(openfile)

 self.x = dict_object['x']
 self.y = #some logic here
 ......
 # Some logic here....


def __getitem__(self,idx):

 # Similar to C++ std::upper_bound - O(log n)
 temp = bisect.bisect_right(self.prefix_sum_idx, idx)

 self.read_pickle_file(temp)
 local_idx = idx - self.prefix_sum_idx[temp] 

 return self.x[local_idx],self.y[local_idx]



def __len__(self):
 return self.dataset_length


large_dataset = dataset()
train_size = int (0.8 * len(large_dataset))
validation_size = len(large_dataset) - train_size

train_dataset, validation_dataset = torch.utils.data.random_split(large_dataset, [train_size, validation_size])
validation_loader = DataLoader(validation_dataset, batch_size=64, num_workers=4, shuffle=False)
train_loader = DataLoader(train_dataset,batch_size=64, num_workers=4,shuffle=False)

Python-3.x相关问答推荐

如何从枚举中获取某个值?

如何在当前测试中使用fixture 转换后的数据进行参数化?

DataFrame列中如何迭代重复值?

如何沿单列获取嵌套列表中的唯一值?

在字符串中查找正则表达式的所有模式

如何在python中将列表转换为其他格式

如何注释一个以另一个函数作为参数的函数?

python total_ordering:为什么使用 __lt__ 和 __eq__ 而不是 __le__?

Python 类型提示语法如何/为什么起作用?

为什么等效的 Python 代码要慢得多

如何使用 asyncio 添加连接超时?

python asyncio - 如何等待取消的屏蔽任务?

如何在 Selenium 和 Python 中使用类型查找元素

Python的max函数有多高效

Python 的 unittest 和 unittest2 模块有什么区别?

如何使用已打开并使用登录凭据登录的浏览器

使用 urllib3 忽略证书验证

为什么排序列表比未排序列表大

如何在 Pandas 中的超 Big Data 框上创建数据透视表

Python 无法处理以 0 开头的数字字符串.为什么?