pytorch从零开始学习4
1.Dataset与Dataloader的理解
下图是关于dataloader读取batch size data的流程
1.1 Dataset
针对单个样本
getitem
- 接收index来找到一个样本,相当于也是路径,只不过这里是单个样本的路径
- 返回样本与标签矩阵
init
- 路径(数据与标签的路径)
- 一些数据预处理
len
- 返回数据的大小(长度)
1.2 Dataloader
针对多个样本
2.数据的读取
dataset是根据index来读取数据及标签,可是index是从哪里获取?
index是经过sampler.py中的__iter__(self)去采样数据的索引,采集batch size个就返回,返回的列表是给self.dataset_fetcher.fetch(index),而该函数是如何实现利用index就取到数据呢?是通过调用dataset来读取。
为什么要重写len方法呢?因为,这个是告诉计算机一共有多少个样本,不然的话计算机无法知道样本,也就无法根据batch size的个数确定一共有多少批数据。
注:train_loader = DataLoader(),是按照样本总数/batch size得到的总可迭代对象返回了。如:假如样本一共有1000,batch size为100,epoch为10,这里的train_loader表示的是10个DataLoader对象。所以说,在训练迭代时用到的。如下所示
for epoch in range(100):
# 这里train_loader 暗示了要迭代int(样本总数/batch size)次
for i, data in enumerate(train_loader, 0): # enumerate返回数据及其索引,这里即(index,(样本,标签))
inputs, labels = data
y_pred = model(inputs)
loss = criterion(y_pred, labels)
print(epoch, i, loss.item())
optimizer.zero_grad()
loss.backward()
optimizer.step()
import torch
import numpy as np
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
import torch.nn as nn
# ---------------------------------------------------------prepare data------------------------------------------------------
class DiabetesDateset(Dataset):
def __init__(self, filepath):
# read data
data = np.loadtxt(filepath, delimiter=',', dtype=np.float32)
self.len = data.shape[0]
# 这里直接在自定义处导入了所有的数据,原因在于数据量不大,当数据量很大时直接在这里导入会导入内存不足
self.x_data = torch.from_numpy(data[:, :-1])
self.y_data = torch.from_numpy(data[:, [-1]])
def __getitem__(self, item):
return self.x_data[item], self.y_data[item]
def __len__(self):
return self.len
dataset = DiabetesDateset('diabetes.csv.gz')
# --------------------------------得到batch size大小的样本和标签,打包成元组(样本,标签)------------------------------------------
train_loader = DataLoader(dataset=dataset, batch_size=32, shuffle=True, num_workers=0)
# ---------------------------------------------------------定义模型----------------------------------------------------------
class Model(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):
out1 = self.sigmoid(self.linear1(x))
out2 = self.sigmoid(self.linear2(out1))
out = self.sigmoid(self.linear3(out2))
return out
# ------------------------------------------------------实例化模型------------------------------------------------------------
model = Model()
# ---------------------------------------------定义损失函数与优化器------------------------------------------------------------
criterion = torch.nn.BCELoss(reduction='mean')
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
if __name__ == '__main__':
# 下面来个for循环的理解:首先,整体需要迭代100次,每次迭代都需要训练所有数据
# 当使用mini-batch时,需要在每一个epoch中迭代所有的数据,即需要在每一个epoch中迭代(样本总数/batch size)次,才能将所有数据训练完全
# 即这样才能实现每个epoch训练所有数据
for epoch in range(100):
for i, data in enumerate(train_loader, 0): # enumerate返回数据及其索引,这里即(index,(样本,标签))
inputs, labels = data
y_pred = model(inputs)
loss = criterion(y_pred, labels)
print(epoch, i, loss.item())
optimizer.zero_grad()
loss.backward()
optimizer.step()