码迷,mamicode.com
首页 > 其他好文 > 详细

pytorch入门3.0构建分类模型再体验(批处理)

时间:2020-06-13 12:58:56      阅读:73      评论:0      收藏:0      [点我收藏+]

标签:代码   lan   效果   elf   ipython   type   构建   size   eval   

在之前的模型里,会看到有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_datasetdataset属性,即代码如下:

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构建分类模型再体验(批处理)

标签:代码   lan   效果   elf   ipython   type   构建   size   eval   

原文地址:https://www.cnblogs.com/datasnail/p/13111885.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!