import numpy as np
#dataset 数据集
#作用:存储数据集信息,self.xxx
# 获取数据集长度:__len__
# 获取数据集某特定条目内容:__getitem__
class ImageDataset:
def __init__(self, raw_data):
self.raw_data = raw_data
def __len__(self):
return len(self.raw_data)
def __getitem__(self, index):
image, label = self.raw_data[index]#返回一个元组
return image, label
#dataloader 数据加载器
#作用:从数据集中加载数据,并拼接为一个数据batch
# 实现迭代器,让使用者获取数据集的内容
class DataLoader:
def __init__(self, dataset, batch_size):
self.dataset = dataset
self.batch_size = batch_size
def __iter__(self):
#正常序列 并重置指针
self.indexs = np.arange(len(self.dataset))
self.cursor = 0
#打乱序列
np.random.shuffle(self.indexs)
return self
def __next__(self):
# 预期在这里返回一个batch数据,一个batch是随机抓取的
# 抓batch个数据前,先抓batch个index
begin = self.cursor
end = self.cursor + self.batch_size
if end > len(self.dataset):
raise StopIteration
self.cursor = end
select_index = self.indexs[begin:end]
batch_data = []
for index in select_index:
batch_data.append(self.dataset[index])
return batch_data
images = [[f"image{i}", i] for i in range(10)]
dataset = ImageDataset(images)
loader = DataLoader(dataset, batch_size=5)
# for index, batch_data in enumerate(loader):#enumerate 表明的是打包函数,将标签和标签所对应的值一同返回
# print(batch_data)
for batch_data in loader:
print(batch_data)
因为初学python,在最后面对于
loader.__iter__()
print(loader.__next__())#这种方式与这种方式相比较为什么前一种只能输出一个batch的内容?
for index, batch_data in enumerate(loader)print(batch_data)
最后顿悟了,解释:第一种这种方式只能输出一个batch的内容,因为 loader.next() 只调用了一次,它只返回了序列中的下一个元素,也就是第一个batch。之后,如果没有再次调用 next() 方法,迭代器不会自动移动到下一个元素,因此不会输出更多的batch。
针对第二种:
这种方式可以输出所有batch的内容,因为 for 循环会自动处理迭代过程。在每次迭代中,for 循环会调用 loader.next() 来获取下一个元素,直到抛出 StopIteration 异常,这表明所有的batch都已经遍历完毕。
python的for循环可以自动管理对象,太智能辣
最后学会了enumerate的捆绑大法。可以将数据和标签捆绑到一起返回。