目录
1、基础知识
1、DataSet 是抽象类,不能实例化对象,主要是用于构造我们的数据集
2、DataLoader 需要获取DataSet提供的索引[i]和len;用来帮助我们加载数据,比如说做shuffle(提高数据集的随机性),batch_size,能拿出Mini-Batch进行训练。它帮我们自动完成这些工作。DataLoader可实例化对象。DataLoader is a class to help us loading data in Pytorch.
3、__getitem__目的是为支持下标(索引)操作
4、注意事项
train_loader = DataLoader(dataset=dataset, shuffle=True, num_workers=0) # num_workers 多线程,如果不设置 batch_size ,则默认使用的是随机梯度下降方法,因为每一次训练中都会将整个样本随机选取一个执行 759 次,一次是一个随机样本 。 __getitem__(self, index)中返回的是一个样本的索引值。虽然是optimizer = torch.optim.SGD(model.parameters(), lr = 0.01),但是要看传进来的数据是单个的还是批量的。这里传递的是单个样本,所以SGD就是随机梯度下降。
def __getitem__(self, index):
print("索引的顺序 index = ",index)
return self.x_data[index], self.y_data[index]
train_loader = DataLoader(dataset=dataset, batch_size= 32, shuffle=True, num_workers=0) # num_workers 多线程,如果设置 batch_size = 32,对于总共有759个样本和批处理大小为32的情况,你需要进行759 / 32 = 23.72 # 次训练迭代。由于无法进行部分迭代,所以最后一次可能不是完整的32个样本。因此,你需要进行24次迭代,其中前23次迭代每次处理32个样本,最后一次迭代处理23个样本。_getitem__(self, index)中返回的是一个样本的索引值,而不是整个批处理的索引值,一批是 32 个样本。虽然是optimizer = torch.optim.SGD(model.parameters(), lr = 0.01),但是要看传进来的数据是单个的还是批量的。这里传递的是32个样本,所以SGD就是mini-batch梯度下降方法。
for i, data in enumerate(train_loader, 0): # train_loader 是先shuffle后mini_batch,i表示的是第几个mini-batch,序号从 0 开始
5、总结
当使用 train_loader = DataLoader(dataset=dataset, shuffle=True, num_workers=0) 时,也即如果不设置 batch_size,则默认使用的是随机梯度下降,则 inputs, labels = data 和 y_pred = model(inputs) 中的 inputs 表示随机选取的一个又一个元素
当使用train_loader = DataLoader(dataset=dataset, batch_size= 32, shuffle=True, num_workers=0) # num_workers 多线程,如果设置 batch_size = 32,则inputs, labels = data 和 y_pred = model(inputs) 中的 inputs 表示一次处理的是 32 个元素,总共需要处理 24 次,这是一次训练的结果
2、代码实现
import torch
import numpy as np
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
# prepare dataset
class DiabetesDataset(Dataset):
def __init__(self, filepath):
xy = np.loadtxt(filepath, delimiter=',', dtype=np.float32)
self.len = xy.shape[0] # shape(多少行,多少列) (759,9)
print("xy",xy)
print("xy.shape",xy.shape)
print("self.len",self.len)
self.x_data = torch.from_numpy(xy[:, :-1])
self.y_data = torch.from_numpy(xy[:, [-1]])
def __getitem__(self, index):
# print("索引的顺序 index = ",index)
return self.x_data[index], self.y_data[index]
def __len__(self):
return self.len
dataset = DiabetesDataset('diabetes.csv')
train_loader = DataLoader(dataset=dataset, batch_size= 32, shuffle=True, num_workers=0) # num_workers 多线程
# design model using class
class Model(torch.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):
x = self.sigmoid(self.linear1(x))
x = self.sigmoid(self.linear2(x))
x = self.sigmoid(self.linear3(x))
return x
model = Model()
# construct loss and optimizer
criterion = torch.nn.BCELoss(reduction='mean')
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
# training cycle forward, backward, update
if __name__ == '__main__':
epoch_list = []
loss_list = []
for epoch in range(100):
sum_loss = 0
for i, data in enumerate(train_loader, 0): # train_loader 是先shuffle后mini_batch,i表示每个mini-batch的索引
inputs, labels = data
y_pred = model(inputs) # inputs是每一批处理 32 个样本
loss = criterion(y_pred, labels)
print(epoch, i, loss.item())
sum_loss += loss.item()
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 对于总共有759个样本和批处理大小为32的情况,你需要进行759 / 32 = 23.72
# 次训练迭代。由于无法进行部分迭代,所以最后一次可能不是完整的32个样本。因此,你需要进行24次迭代,其中前23次迭代每次处理32个样本,最后一次迭代处理23个样本。
loss_list.append(sum_loss)
epoch_list.append(epoch)
plt.plot(epoch_list, loss_list)
plt.ylabel('loss')
plt.xlabel('epoch')
plt.show()
3、拓展知识
所有的datasets都是 Dataset的子类,所以他们都有 __getitem__和 __len__方法(用于加载数据集)