加载数据、划分数据集(train-valid-test)、从数据集中创建dataloader。
以ML2021Spring-hw1数据为例,代码如下:
代码
import csv
import numpy as np
# 数据处理
import torch
from torch.utils.data import Dataset, DataLoader
class Mydata(Dataset):
def __init__(self):
with open('Datasets/covid.train.csv', 'r') as f:
data = list(csv.reader(f))
data = np.array(data[1:])[:, 1:].astype(float) # 去掉第一行和第一列, 并转为float形式 [2700,94]
target = data[:, -1] # 最后一列
self.data = torch.FloatTensor(data)
self.target = torch.FloatTensor(target)
def __getitem__(self, item):
# 一次返回一个sample
return self.data[item]
def __len__(self):
return len(self.data)
dataset = Mydata() # MyData类的一个对象(数据类型是MyData)
dataloader = DataLoader(dataset, batch_size=2, shuffle=True) # DataLoader类的一个对象(数据类型是DataLoader)
for i, data in enumerate(dataloader):
data = list(map(lambda x: torch.LongTensor(x.long()), data))
print(data)
1. 实例化自定义类的对象
dataset,是MyData类的一个对象(数据类型是MyData)
dataset = Mydata()
上述代码中,首先定义一个自己的数据处理的类,例如MyData类,注意该类具有一定的固定格式,如下:
import torch
from torch.utils.data import Dataset, DataLoader
class Mydata(Dataset): # 固定,写Dataset
def __init__(self, attr1, attr2): # 如果有数据处理的输入参数,写在这里
pass
def __getitem__(self):
pass
def __len__(self):
pass
定义好自己的数据处理的类之后,实例化一个该类的对象:Mydata(attr1, attr2)
中,
__init__
写数据处理的输入参数,如果没有,则dataset = Mydata()
即可。__getitem__
写后续直接对dataloader
进行数据操作得到的结果,例如:
def __getitem__(self, item):
# 一次返回两个sample
return self.data[item], self.target[item]
则对dataloader
操作时有两个值:
for x,y in dataloader:
print(x)
print(y)
例如:
def __getitem__(self, item):
# 一次返回一个sample
return self.data[item]
则对dataloader
操作时有一个值:
for x in dataloader:
print(x)
__len__
得到数据的长度。
def __len__(self):
return len(self.data)
2. 实例化DataLoader的对象
dataloader,是DataLoader类的一个对象(数据类型是DataLoader)
dataloader = DataLoader(dataset, batch_size=2, shuffle=True)
3. 对dataloader进行迭代操作
后续可以对dataloader
进行循环迭代,每次循环得到的数据大小是定义的batch_size
的大小。
例如:
for i, data in enumerate(dataloader):
data = list(map(lambda x: torch.LongTensor(x.long()), data))
print(data)
# 后续再进一步操作
input, label = data
input, label = input.to(device), label.to(device)
output = model(input)
……
其中,i
从0开始累加,data
的第0个维度为batch_size
大小(为2)
len(data) # =2
len(dataloader) # 由数据集中的数据量决定
也可以不使用enumerate
:
for data in dataloader:
data = list(map(lambda x: torch.LongTensor(x.long()), data))
print(data)
区别在于少了i
进行显示判断,data
不变。
补充:可以直接把数据读入,并在自定义的MyData()类中可以进行train-valid的数据划分,也可以提前划分好数据,在自定义的MyData()类中直接转为MyData()类的实例dataset
即可,相当于进行一个数据类型的转换,方便后续创建dataloader
。
后续在计算准确率acc和损失值loss的时候,都是在epoch中进行累加,区别在于:
- acc的是对所有item值进行比较、累加,因此累加值应该除以
dataset
的长度; - loss是计算每个batch的batch_loss的累加,因此累加值应该除以
dataloader
的长度。
参考:
- Pytorch中DataLoader的使用:https://blog.csdn.net/kahuifu/article/details/108654421