工具类:
Dataset 用于构造数据集,可以用索引取出数据
DataLoader: 取出一个 mini-batch,做训练
“Batch” 是把全部数据输入神经网络,计算预测值,这样可以充分发挥向量计算的并行性,速度很快,但是可能到达鞍点,无法继续训练。可以利用数据的噪声避免停留在鞍点上,从而达到全局最优,所以需要1个样本,1个样本地计算,叫作随机梯度下降SGD,性能较好但是训练时间太长。所以采用 “mini-batch” 来平衡速度和性能。(通常把mini-batch叫做batch)
Epoch: 训练轮数,所有的样本都做过一次前馈和反馈
Batch-size: 每次训练使用的样本量,经过一次前馈、反馈和更新
Iteration:迭代次数,分了几个batch
DataLoader: 对支持索引,支持获取其长度的数据集进行加载,生成一个 iterable loader, 对数据分组,每次迭代给出一个batch的X和y,并自动转换成Tensor。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
import torch
from torch.utils.data import Dataset #抽象类,不能实例化,只能被它的子类继承
from torch.utils.data import DataLoader #加载, 划分数据
class DiabetesDataset(Dataset): #自定义的类继承自Dataset
def __init__(self):
pass #
def __getitem__(self, index): #使对象支持下标操作,根据索引返回数据
pass
def __len__(self): #返回数据集的条数
pass
dataset = DiabetesDataset() #实例化数据集,支持索引数据和获取长度
train_loader = DataLoader(dataset=dataset, batch_size=32, shuffle=True, num_workers=2) #实例化加载器, 洗牌使每次epoch的数据都不一样,使用2个并行进程读取数据
|
加载数据有两种方式,如果数据量小,直接把所有的数据加载进内存,之后使用getitem读取;当数据集很大时,需要将其拆分成小文件,在__init__方法中初始化列表,把小文件名放入列表中;有时标签也很大,比如对图片的每个像素预测语义信息,y的维度与x相同,所以也需要拆分,文件名放入列表。在需要使用某数据的时候,用__getitem__方法读取。
pytorch 0.4中出现一个问题:由于windows 和 linux的多进程库不同,spawn与fork不同。Windows下需要把迭代的loader封装起来,不能直接“顶格”写
1
2
3
4
5
6
|
train_loader = DataLoder(...)
if __name__ == '__main__':
for epoch in range(100):
for i, data in enumerate (train_loader, 0):
...
|
加载糖尿病数据集:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
import numpy as np
import torch
from torch.utils.data import Dataset, DataLoader
class DiabetesDataset(Dataset):
def __init__(self, filepath): #需要文件名
xy = np.loadtxt(filepath, delimiter=',', dtype=np.float32)
self.len = xy.shape[0] #样本条数:矩阵的第一个维度
self.x_data = torch.from_numpy(xy[:, :-1]) #样本, 直接放在内存中
self.y_data = torch.from_numpy(xy[:, [-1]]) #标签取最后一列
def __getitem__(self, index):
return self.x_data[index], self.y_data[index] #返回一个元组
def __len__():
return self.len
data = DiabetesDataset('diabetes.csv.gz')
train_loader = DataLoader(dataset=dataset, batch_size=32, shuffle=True, num_workers=2)
for epoch in range(100):
for i, data in enumerate(train_loader, 0): #迭代加载器,enumerate获得第几次迭代,x和y的元组放入data
inputs, labels = data #取出样本和标签
y_pred = model(inputs) #计算预测值
loss = criterion(y_pred, labels) #计算损失
optimizer.zero_grad() #梯度清零
loss.backward() #反向传播
optimizer.step() #更新梯度
|