pytorch 数据加载器的示例或解释?
Examples or explanations of pytorch dataloaders?
我对 Pytorch 还很陌生(并且从未进行过高级编码)。我正在尝试使用 d2l.ai 教科书学习深度学习的基础知识,但无法理解数据加载器代码背后的逻辑。我阅读了 torch.utils.data docs,但不确定 DataLoader class 的用途,例如我应该将 torch.utils.data.TensorDataset class 与它结合使用。比如d2l定义了一个函数:
def load_array(data_arrays, batch_size, is_train=True):
"""Construct a PyTorch data iterator."""
dataset = data.TensorDataset(*data_arrays)
return data.DataLoader(dataset, batch_size, shuffle=is_train)
我假设这应该是 return 一个迭代不同批次的可迭代对象。但是,我不明白 data.TensorDataset 部分的作用(似乎文档页面上列出了很多选项)。此外,文件说有两种类型的数据集:可迭代和地图样式。在描述前一种类型时,它说
“这种类型的数据集特别适用于随机读取代价高昂甚至不可能的情况,并且批量大小取决于获取的数据。”
“随机读取是昂贵的或不可能的”以及 batch_size 依赖于获取的数据是什么意思?谁能举个例子?
如果有任何资源可供像我这样的 CompSci 菜鸟学习这些基础知识,我将不胜感激!
非常感谢!
我会给你一个如何使用数据加载器的例子,并解释这些步骤:
数据加载器是数据集上的可迭代对象。所以当你迭代它时,它会 return B 从数据集中随机收集样本(包括数据样本和 target/label),其中 B 是批量大小。
要创建这样的数据加载器,您首先需要一个 class,它继承自数据集 Pytorch class。在 pytorch 中有这个 class 的标准实现,应该是 TensorDataset
。但是标准的方法是创建一个自己的。这是图像 classification:
的示例
import torch
from PIL import Image
class YourImageDataset(torch.utils.data.Dataset):
def __init__(self, image_folder):
self.image_folder = image_folder
self.images = os.listdir(image_folder)
# get sample
def __getitem__(self, idx):
image_file = self.images[idx]
image = Image.open((self.image_folder + image_file))
image = np.array(image)
# normalize image
image = image / 255
# convert to tensor
image = torch.Tensor(image).reshape(3, 512, 512)
# get the label, in this case the label was noted in the name of the image file, ie: 1_image_28457.png where 1 is the label and the number at the end is just the id or something
target = int(image_file.split("_")[0])
target = torch.Tensor(target)
return image, target
def __len__(self):
return len(self.images)
要获取示例图像,您可以调用 class 并将一些随机索引传递给 getitem 函数。然后它将 return 图像矩阵的张量和该索引处标签的张量。例如:
dataset = YourImageDataset("/path/to/image/folder")
data, sample = dataset.__getitem__(0) # get data at index 0
好的,现在您已经创建了 class 预处理和 return 一个样本及其标签。现在我们必须创建 datalaoder,它“环绕”这个 class,然后可以 return 来自数据集 class 的整批样本。
让我们创建三个数据加载器,一个遍历训练集,一个用于测试集,一个用于验证集:
dataset = YourImageDataset("/path/to/image/folder")
# lets split the dataset into three parts (train 70%, test 15%, validation 15%)
test_size = 0.15
val_size = 0.15
test_amount, val_amount = int(dataset.__len__() * test_size), int(dataset.__len__() * val_size)
# this function will automatically randomly split your dataset but you could also implement the split yourself
train_set, val_set, test_set = torch.utils.data.random_split(dataset, [
(dataset.__len__() - (test_amount + val_amount)),
test_amount,
val_amount
])
# B is your batch-size, ie. 128
train_dataloader = torch.utils.data.DataLoader(
train_set,
batch_size=B,
shuffle=True,
)
val_dataloader = torch.utils.data.DataLoader(
val_set,
batch_size=B,
shuffle=True,
)
test_dataloader = torch.utils.data.DataLoader(
test_set,
batch_size=B,
shuffle=True,
)
现在您已经创建了数据加载器并可以开始训练了!
例如像这样:
for epoch in range(epochs):
for images, targets in train_dataloder:
# now 'images' is a batch containing B samples
# and 'targets' is a batch containing B targets (of the images in 'images' with the same index
optimizer.zero_grad()
images, targets = images.cuda(), targets.cuda()
predictions = model.train()(images)
. . .
通常您会为“YourImageDataset”创建一个自己的文件class,然后导入您要在其中创建数据加载器的文件。
希望能说清楚dataloader和Datasetclass的作用是什么,怎么用!
我对 iter 风格的数据集了解不多,但据我了解:我上面向您展示的方法是 map 风格。如果您的数据集存储在 .csv、.json 或任何类型的文件中,您就可以使用它。因此,您可以遍历数据集的所有行或条目。 Iter-style 将带你数据集或数据集的一部分,并将转换为可迭代的。例如,如果您的数据集是一个列表,则列表的可迭代对象如下所示:
dataset = [1,2,3,4]
dataset = iter(dataset)
print(next(a))
print(next(a))
print(next(a))
print(next(a))
# output:
# >>> 1
# >>> 2
# >>> 3
# >>> 4
因此 next
将为您提供列表的下一项。将它与 Pytorch Dataloader 一起使用可能更高效、更快速。通常 map-dataloader 足够快且易于使用,但文档假设当您从数据库加载数据批次(这可能更慢)时,iter 风格的数据集会更有效率。
这个对 iter-style 的解释有点模糊,但我希望它能让你明白我所理解的。我建议您首先使用地图样式,正如我在原始答案中所解释的那样。
您使用数据加载器将数据拆分成批次、打乱数据或动态转换现有数据。
地图式数据集提供随机访问功能。示例:Numpy 数组、Python 字典、磁盘上的文件。
只能按顺序访问可迭代样式数据集。示例:Python 个生成器,来自网络的流式数据。
一般来说,您应该尽可能使用地图样式的数据集。地图风格的数据集提前给你它们的大小,更容易洗牌,并允许简单的并行加载。
我写了一篇简短的 post 关于如何使用 PyTorch 数据集,以及 map-style 和 iterable-style 数据集之间的区别。查看完整的 post here.
我对 Pytorch 还很陌生(并且从未进行过高级编码)。我正在尝试使用 d2l.ai 教科书学习深度学习的基础知识,但无法理解数据加载器代码背后的逻辑。我阅读了 torch.utils.data docs,但不确定 DataLoader class 的用途,例如我应该将 torch.utils.data.TensorDataset class 与它结合使用。比如d2l定义了一个函数:
def load_array(data_arrays, batch_size, is_train=True):
"""Construct a PyTorch data iterator."""
dataset = data.TensorDataset(*data_arrays)
return data.DataLoader(dataset, batch_size, shuffle=is_train)
我假设这应该是 return 一个迭代不同批次的可迭代对象。但是,我不明白 data.TensorDataset 部分的作用(似乎文档页面上列出了很多选项)。此外,文件说有两种类型的数据集:可迭代和地图样式。在描述前一种类型时,它说
“这种类型的数据集特别适用于随机读取代价高昂甚至不可能的情况,并且批量大小取决于获取的数据。”
“随机读取是昂贵的或不可能的”以及 batch_size 依赖于获取的数据是什么意思?谁能举个例子?
如果有任何资源可供像我这样的 CompSci 菜鸟学习这些基础知识,我将不胜感激!
非常感谢!
我会给你一个如何使用数据加载器的例子,并解释这些步骤:
数据加载器是数据集上的可迭代对象。所以当你迭代它时,它会 return B 从数据集中随机收集样本(包括数据样本和 target/label),其中 B 是批量大小。
要创建这样的数据加载器,您首先需要一个 class,它继承自数据集 Pytorch class。在 pytorch 中有这个 class 的标准实现,应该是 TensorDataset
。但是标准的方法是创建一个自己的。这是图像 classification:
import torch
from PIL import Image
class YourImageDataset(torch.utils.data.Dataset):
def __init__(self, image_folder):
self.image_folder = image_folder
self.images = os.listdir(image_folder)
# get sample
def __getitem__(self, idx):
image_file = self.images[idx]
image = Image.open((self.image_folder + image_file))
image = np.array(image)
# normalize image
image = image / 255
# convert to tensor
image = torch.Tensor(image).reshape(3, 512, 512)
# get the label, in this case the label was noted in the name of the image file, ie: 1_image_28457.png where 1 is the label and the number at the end is just the id or something
target = int(image_file.split("_")[0])
target = torch.Tensor(target)
return image, target
def __len__(self):
return len(self.images)
要获取示例图像,您可以调用 class 并将一些随机索引传递给 getitem 函数。然后它将 return 图像矩阵的张量和该索引处标签的张量。例如:
dataset = YourImageDataset("/path/to/image/folder")
data, sample = dataset.__getitem__(0) # get data at index 0
好的,现在您已经创建了 class 预处理和 return 一个样本及其标签。现在我们必须创建 datalaoder,它“环绕”这个 class,然后可以 return 来自数据集 class 的整批样本。 让我们创建三个数据加载器,一个遍历训练集,一个用于测试集,一个用于验证集:
dataset = YourImageDataset("/path/to/image/folder")
# lets split the dataset into three parts (train 70%, test 15%, validation 15%)
test_size = 0.15
val_size = 0.15
test_amount, val_amount = int(dataset.__len__() * test_size), int(dataset.__len__() * val_size)
# this function will automatically randomly split your dataset but you could also implement the split yourself
train_set, val_set, test_set = torch.utils.data.random_split(dataset, [
(dataset.__len__() - (test_amount + val_amount)),
test_amount,
val_amount
])
# B is your batch-size, ie. 128
train_dataloader = torch.utils.data.DataLoader(
train_set,
batch_size=B,
shuffle=True,
)
val_dataloader = torch.utils.data.DataLoader(
val_set,
batch_size=B,
shuffle=True,
)
test_dataloader = torch.utils.data.DataLoader(
test_set,
batch_size=B,
shuffle=True,
)
现在您已经创建了数据加载器并可以开始训练了! 例如像这样:
for epoch in range(epochs):
for images, targets in train_dataloder:
# now 'images' is a batch containing B samples
# and 'targets' is a batch containing B targets (of the images in 'images' with the same index
optimizer.zero_grad()
images, targets = images.cuda(), targets.cuda()
predictions = model.train()(images)
. . .
通常您会为“YourImageDataset”创建一个自己的文件class,然后导入您要在其中创建数据加载器的文件。 希望能说清楚dataloader和Datasetclass的作用是什么,怎么用!
我对 iter 风格的数据集了解不多,但据我了解:我上面向您展示的方法是 map 风格。如果您的数据集存储在 .csv、.json 或任何类型的文件中,您就可以使用它。因此,您可以遍历数据集的所有行或条目。 Iter-style 将带你数据集或数据集的一部分,并将转换为可迭代的。例如,如果您的数据集是一个列表,则列表的可迭代对象如下所示:
dataset = [1,2,3,4]
dataset = iter(dataset)
print(next(a))
print(next(a))
print(next(a))
print(next(a))
# output:
# >>> 1
# >>> 2
# >>> 3
# >>> 4
因此 next
将为您提供列表的下一项。将它与 Pytorch Dataloader 一起使用可能更高效、更快速。通常 map-dataloader 足够快且易于使用,但文档假设当您从数据库加载数据批次(这可能更慢)时,iter 风格的数据集会更有效率。
这个对 iter-style 的解释有点模糊,但我希望它能让你明白我所理解的。我建议您首先使用地图样式,正如我在原始答案中所解释的那样。
您使用数据加载器将数据拆分成批次、打乱数据或动态转换现有数据。
地图式数据集提供随机访问功能。示例:Numpy 数组、Python 字典、磁盘上的文件。
只能按顺序访问可迭代样式数据集。示例:Python 个生成器,来自网络的流式数据。
一般来说,您应该尽可能使用地图样式的数据集。地图风格的数据集提前给你它们的大小,更容易洗牌,并允许简单的并行加载。
我写了一篇简短的 post 关于如何使用 PyTorch 数据集,以及 map-style 和 iterable-style 数据集之间的区别。查看完整的 post here.