卷积神经网络|制作自己的Dataset(最终版)

卷积神经网络|制作自己的Dataset(最终版)_第1张图片

​之前文章已经实现了一个自定义的类,制定了自己的数据集。其实,细看代码,可传入的参数过多,有些简单问题复杂化,实现上不是那么简洁。

既然是自己定义的数据集,那么许多功能是自己写好的,如何写,为什么这样写都是已知的

这里,我们考虑让自己定义的Dataset类简单化,并由此完成全部数据准备工作。

图片名处理

在实现Dataset类之前,图片准备工作是必须要进行的,或者说是对我们收集到的图片进行改名。就像之前那篇文章所写的,写个小程序批量改变图片命名

就像这样:

import ospath="E:\\3-10\\dogandcats\\train\\cat\\"#猫图片路径filenames=[name for name in os.listdir(path)]for i,filename in enumerate(filenames):    src=path+filename    dst=path+path[-4:-1]+str(i+1)+'.0'+".jpg"    os.rename(src,dst)

同样,我们类似的可以处理狗图片,此时仅需修改路径名以及将

dst=path+path[-4:-1]+str(i+1)+'.0'+".jpg"

修改为:

dst=path+path[-4:-1]+str(i+1)+'.1'+".jpg"

处理其它类的图片同样如此。最终是这种形式:

                  cat1.0.jpg

                  cat2.0.jpg

                  ...

                  dog1.1.jpg

                  dog2.1.jpg

                  ...

需要强调的是这里的cat1,dog1...,jpg格式仅仅是一个习惯,没有太多的含义,真正重要的是0,1,...,这是个标签,指明了这张图片的类别。0代表cat,而1代表dog...

这里,图片准备工作已经完成!

之后,我们将处理后的所有用于训练的图片放于此路径:

E:\3-10\dogandcats\train

Dataset实现

import torchimport osfrom torch.utils.data import Datasetfrom torchvision import transformsfrom PIL import Imageimport numpy as npimport torchclass MyDataset(Dataset):    def __init__(self, path_file,transform=None):        self.path_file=path_file        self.imgs=[name for name in os.listdir(path_file)]        self.transform=transform    def __len__(self):        return len(self.imgs)    def __getitem__(self, idx):        #get the image        img_path = os.path.join(self.path_file,self.imgs[idx])        image=Image.open(img_path)        image=image.resize((28,28))#修改图片大小,默认大小        #image = np.array(image)        #image=torch.tensor(image,dtype=torch.float32)#将numpy数组转化为数据类型为float32的张量        #image=image.permute(2,0,1)#将HxWxC变为CxHxW        #以上三行所起的功能可以用transforms.ToTensor()代替(差别仅仅在于后者将像素全部归为[0,1]。         if self.transform:            image = self.transform(image)        #get the label        str1=self.imgs[idx].split('.')        label=torch.tensor(eval(str1[1]))        return image, labelpath="E:\\3-10\\dogandcats\\train"training_data=MyDataset(path,transform=transforms.Compose([transforms.ToTensor()]))train_dataloader = torch.utils.data.DataLoader(training_data, batch_size=4, shuffle=True)

让我们run一下:

>>> BatchImg,Label=next(iter(train_dataloader))>>> BatchImg.size()torch.Size([4, 3, 28, 28])>>> Label.size()torch.Size([4])

均值和标准差,归一化

然后我们尝试获取所有图片的三个通道的均值和标准差,最后让图片数据变为均值为0,标准差为1的新数据。

>>> IMGEND=torch.stack([ig for ig,_ in training_data],dim=0)#堆叠tensor>>> IMGEND.size()torch.Size([17, 3, 28, 28])

此时,可以看到我们已经获得了所有图片(共17张)的数据

>>> mean=torch.mean(IMGEND,dim=(0,2,3))#获得均值>>> meantensor([0.6479, 0.6043, 0.5521])>>> std=torch.std(IMGEND,dim=(0,2,3))#获得标准差>>> stdtensor([0.2343, 0.2485, 0.2925])

好吧,这里,借助:transforms.Normalize()方法,我们可以很容易对所有图片数据进行变换,最终获得均值为0,标准差为1的数据。

就像这样:

training_data1=MyDataset(path,transform=transforms.Compose([transforms.ToTensor(),transforms.Normalize([0.6479, 0.6043, 0.5521],[0.2343, 0.2485, 0.2925])]))

接着我们就可以将training_data1传入Dataloader:

train_dataloader1 = torch.utils.data.DataLoader(training_data1, batch_size=4, shuffle=True)

此时,对于图片数据我们完成了归一化操作,将数据分布变为了均值为0,标准差为1的分布,training_data1就是之后在神经网络用于训练的数据集

检验training_data1数据,就像之前那个计算均值和标准差的过程:

>>> IMGEND1=torch.stack([ig for ig,_ in training_data1],dim=0)>>> IMGEND1.size()torch.Size([17, 3, 28, 28])>>> mean1=torch.mean(IMGEND1,dim=(0,2,3))>>> mean1tensor([ 1.1959e-04, -3.3379e-05, -1.4900e-04])>>> std=torch.std(IMGEND1,dim=(0,2,3))>>> stdtensor([1.0001, 0.9998, 1.0001])

总结

总的来看,我们实现Dataset类时,完成了对数据的归一化,以及将Dataset数据传入了Dataloader。

一些操作可以使用transforms模块所提供的方法以简化步骤,当然,算数据的均值和标准差用于归一化仍然还是比较繁琐的。

到这里,数据的预处理工作基本结束!

你可能感兴趣的:(pytorch,cnn,人工智能,神经网络)