《PyTorch深度学习实践》学习笔记(2)
一 数据集的加载
前文主要是自定义的小批量数据集,这里主要介绍加载外部开源的数据集方法
数据集加载常用的工具:
1)Dataset:主要用于构造数据集,该数据集应该能够支持索引结构;
2)DataLoader:主要用于加载数据集,支持训练时的Mini-Batch(分批进行训练)形式。
1.1 Dataset的构造
import torch
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
//准备数据,自定义数据集类,用以继承Dataset抽象类
//在torch.utils.data中有Dataset抽象类,我们需要根据自己的需要继承这个抽象类,来实现自己的数据集类
class DiabetesDataset(Dataset):
def __init__(self): #init:对数据集类进行初始化
pass
def __getitem__(self, item): #该方法的实现是为了实例化后的数据集对象支持下标操作dataset[index]
pass
def __len__(self): #该方法的实现是为了方便我们输出数据集每一个batch的数据项条目数
pass
dataset = DiabetesDataset()#实例化这个数据集类
数据集的数据加载方式(init和getitem的实现)
1)若数据集本身规模不是很大,可以直接将原数据集全部加载到内存中,则getitem方法只需要从内存中顺序读出即可;
2)若数据集本身规模较大,则可以将数据在磁盘中按照文件夹分装,将输入出的各个文件夹名以列表的形式载入内存中;则getitem的方法就是按照文件夹路径从磁盘中索引并读出文件。
1.2 DataLoader的构造
train_loader = DataLoader(dataset=dataset,batch_size=32,shuffle=True,num_workers=2)
'''
dataset:数据集对象
batch_size:批量训练的大小
shuffle:是否要进行随机打乱
num_workers:使用多少个线程对数据进行载入操作;使用并行化可以提高数据读取的效率
'''
1)首先DataLoader类需要传入一个支持索引操作的数据集兑现Dataset
2)对原始数据集中的各个数据项进行随机打乱操作(Shuffle)
3)使用Loader工具,按照给定的Batch-Size大小将原始的数据集划分成以Batch-Size为基本大小的,Batch为基本单位的数据单元
1.3 具体实例的实现
import numpy as np
import torch
from torch.utils.data import Dataset,DataLoader
import matplotlib.pyplot as plt
#准备数据,自定义数据集类,用以继承Dataset抽象类
class DiabetesDataset(Dataset):
def __init__(self):
#xy = np.loadtxt(filepath,delimiter=' ',dtype = np.float32)
self.x_data = torch.from_numpy(np.loadtxt('diabetes_data.csv.gz',delimiter=' ',dtype=np.float32))
self.y_data = torch.from_numpy(np.loadtxt('diabetes_target.csv.gz',dtype=np.float32))
self.len = self.y_data.shape[0]
def __getitem__(self, index):
#该方法的实现是为了实例化后的数据集对象支持下标操作
return self.x_data[index],self.y_data[index]
def __len__(self):
#该方法的实现是为了方便我们输出数据集每一个batch的数据项条目数
return self.len
# x_data = torch.from_numpy(np.loadtxt('diabetes_data.csv.gz',delimiter=' ',dtype=np.float32))
# y_data = torch.from_numpy(np.loadtxt('diabetes_target.csv.gz',dtype=np.float32))
dataset = DiabetesDataset()#实例化这个数据集类
train_loader = DataLoader(dataset=dataset,batch_size=32,shuffle=True)
'''
dataset:数据集对象
batch_size:批量训练的大小
shuffle:是否要进行随机打乱
num_workers:使用多少个线程对数据进行载入操作;使用并行化可以提高数据读取的效率
'''
#自定义多层模型
class Model(torch.nn.Module):
def __init__(self):
super(Model,self).__init__()
self.linear1 = torch.nn.Linear(10,8)
self.linear2 = torch.nn.Linear(8,6)
self.linear3 = torch.nn.Linear(6,4)
self.linear4 = torch.nn.Linear(4,1)
self.sigmoid = torch.nn.Sigmoid() #增加非线性映射
def forward(self,x):
#在多隐层的网络中书写前向计算的逻辑时,只用一个变量x串联整个输入输出
#这是一种习惯
x = self.sigmoid(self.linear1(x))
x = self.sigmoid(self.linear2(x))
x = self.sigmoid(self.linear3(x))
x = self.sigmoid(self.linear4(x))
return x
model = Model()
#构建损失函数的计算和优化器
criterion = torch.nn.BCELoss(size_average = True)#逻辑回归模型适用二分类交叉熵损失函数
op = torch.optim.SGD(model.parameters(),lr = 0.01)
epochs = []
costs = []
#训练过程,包括前向计算和反向传播
for epoch in range(100):
epochs.append(epoch)
loss_sum = 0.0
for i,data in enumerate(train_loader,0):
inputs,labels = data
#从train_loader中取出数据data
#从数据data中提取属性x和标签y
#并且自动转换成tensor张量传给inputs和data两个变量
y_pred = model(inputs)
loss = criterion(y_pred,labels)
loss_sum += loss.item()
print(epoch,i,loss.item())
op.zero_grad()
loss.backward()
op.step()
costs.append(loss_sum/(i+1))
# 训练过程可视化
plt.ylabel('Cost')
plt.xlabel('Epoch')
plt.plot(epochs, costs)
plt.show()