pytorch入门3.0构建分类模型再体验(批处理)
Posted datasnail
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了pytorch入门3.0构建分类模型再体验(批处理)相关的知识,希望对你有一定的参考价值。
在之前的模型里,会看到有batch_size的变量,但是从来没用过,这里我们就使用一下batchsize这个变量。
之前应该讲过epoch是什么意思,一个EPOCH代表的意思就是用所有的样本训练一次,换句话讲,就是所有的样本都完成了一次前向传播(forward)和反向传播(backward propagation)。因为数据量不足,要用有限的样本让模型达到更好的效果,也就是要多次使用这些样本数据。
而batch_size是模型进行一次forward操作时,使用的样本数据数量。每次模型要用这些数据来更新一次模型的参数。batch_size设置的越大,需要的内存也越大,但是梯度也越稳定,但是有时候,我们不太需要那么稳定的梯度,反而batch_size相对小一些能提高模型训练的速度。一般情况下,我们使用的batch_size都是2的幂指数,例如64/128/512/1024等等。
首先,准备数据的部分还是这样子。
# preparing the dataset
x = torch.unsqueeze((torch.rand(5000)-0.5)*10,dim=0).reshape(-1,2)
y = torch.LongTensor([1 if _x[0]*_x[1]>=0 else 0 for _x in x])
其次,我们要使用pytorch提供的TensorDataset和DataLoader来封装我们的数据,因为这些类包里面已经实现了batch的划分,使得我们可以更加简便地操作。
from torch.utils.data import TensorDataset, DataLoader # 导入包
xy_dataset = TensorDataset(x,y)
data_loader = DataLoader(dataset=xy_dataset, # 数据源
batch_size=BATCH_SIZE, # batch 的大小
shuffle=True, # 数据是否需要打乱
num_workers=2) #多线程
s = int(len(train_loader)*0.8) #
e = len(train_loader)-s
# assert(s+e ==len(train_loader) #要保证分的几部分的和,要跟数据的样本数量相等,否则会报错,如下图红框部分。
train_dataset, test_dataset = torch.utils.data.random_split(train_loader,[s,e]) # 把train_loader划分为两个部分,每个部分的数量用后面的list类型向量表示。
图像来源,官网文档
此时,我们想看看划分后的数据,没啥,就想看看。结果遇到了问题,发现不行,并报了一个错。
for i,b in enumerate(train_dataset):
print(i)
break
‘‘‘
===output===
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-23-c1469be83646> in <module>
1 # type(train_dataset)
----> 2 for i,b in enumerate(train_dataset):
3 print(i)
4 break
5 # for i in train_dataset:
/usr/local/anaconda3/lib/python3.7/site-packages/torch/utils/data/dataset.py in __getitem__(self, idx)
255
256 def __getitem__(self, idx):
--> 257 return self.dataset[self.indices[idx]]
258
259 def __len__(self):
TypeError: ‘DataLoader‘ object is not subscriptable
‘‘‘
查了一会是这样的,因为torch.utils.data.random_split()
函数在划分数据集的时候,用torch.utils.data.Subset
类封装了Dataloader,源码如下:
图像来源,官网文档
封装完后原有的数据就存到了Subset的dataset属性中:
图片来源:官网文档
所以再使用的时候要用其返回值train_dataset
的dataset
属性,即代码如下:
for i,b in enumerate(train_dataset.dataset): # 修改了这里,使用dataset属性
print(b)
break
这样就正常啦。
最终,我们在训练的地方进行修改,此处按照每个batch输入到模型进行训练,他所有的batch都使用完成后,进行下一个epoch次总数据集训练:
for epoch in range(EPOCH):
for i,batch in enumerate(train_dataset.dataset): # 按照batch进行训练
x,y = batch
if torch.cuda.is_available():
x = torch.autograd.Variable(x).cuda()
y = torch.autograd.Variable(y).cuda()
else:
x = torch.autograd.Variable(x)
y = torch.autograd.Variable(y)
out = model(x)
# print(out.shape,y.shape)
loss = loss_func(out,y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if (epoch+1)%100==0:
print(‘Epoch[{}/{}],loss:{:.6f}‘.format(epoch+1,EPOCH,loss.data.item()))
测试部分,这里也使用每个batch单独测试,然后再计算总的结果(其他部分类似):
from sklearn.metrics import accuracy_score
model.eval()
acc = 0.0
for i,batch in enumerate(test_dataset.dataset): # 按照batch测试结果
x,y=batch
if torch.cuda.is_available():
x = x.cuda()
predict = model(x)
predict = torch.max(predict,1)[1]
predict = predict.cpu().data.numpy()
acc += accuracy_score(y.cpu().numpy(),predict)
print(‘{:.3f}‘.format(acc/(i+1)))
使用batch size改动的版本源代码在此:github
以上是关于pytorch入门3.0构建分类模型再体验(批处理)的主要内容,如果未能解决你的问题,请参考以下文章