版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第使用pytorch读取数据集目录pytorch读取数据集第一种第二种第三种pytorch学习记录注意事项
pytorch读取数据集
使用pytorch读取数据集一般有三种情况
第一种
读取官方给的数据集,例如Imagenet,CIFAR10,MNIST等
这些库调用torchvision.datasets.XXXX()即可,例如想要读取MNIST数据集
importtorch
importtorch.nnasnn
importtorch.utils.dataasData
importtorchvision
train_data=torchvision.datasets.MNIST(
root='./mnist/',
train=True,#thisistrainingdata
transform=torchvision.transforms.ToTensor(),#ConvertsaPIL.Imageornumpy.ndarrayto
#torch.FloatTensorofshape(CxHxW)andnormalizeintherange[0.0,1.0]
download=True,
这样就会自动从网上下载MNIST数据集,并且以保存好的数据格式来读取
然后直接定义DataLoader的一个对象,就可以进行训练了
train_loader=Data.DataLoader(dataset=train_data,batch_size=BATCH_SIZE,shuffle=True)
forepochinrange(EPOCH):
forstep,(b_x,b_y)inenumerate(train_loader):#givesbatchdata,normalizexwheniteratetrain_loader
XXXX
XXXX
第二种
这种就比较常用了,针对图像的分类问题
适用情况是,对于图片的多分类问题,图片按照指定的格式来存放:
根路径/类别(标签label)/图片
按照上面的格式来存放图片,根路径下面保存了许多文件夹,每个文件夹中存放了某一类的图片,并且文件夹名就是类的映射,例如这样,根目录就是learn_pytorch,下面的每个文件夹代表一个类,类的名字随便命名,在训练过程中会自动被映射成0,1,2,3
保存成这样的格式之后,就可以直接利用pytorch定义好的派生类ImageFolder来读取了,ImageFolder其实就是Dataset的派生类,专门被定义来读取特定格式的图片的,它也是torchvision库帮我们方便使用的,比如这样
然后就可以作为DataLoader的数据集输入用了
fromtorchvision.datasetsimportImageFolder
data_transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(mean=[0.5,0.5,0.5],std=[0.5,0.5,0.5])
dataset=ImageFolder("/home/xxx/learn_pytorch/",transform=data_transform)
train_loader=Data.DataLoader(dataset=dataset,batch_size=BATCH_SIZE,shuffle=True)
它的构造函数要求输入两个参数,一个根目录,一个对数据的操作,因为图片被自动读取成PILimage数据格式,因此Totensor()必不可少,而且可以用transforms.Compose把许多操作合成一个参数输入,就能实现数据增强,非常方便。上面的例子是先转成tensor,然后归一化,没做数据增强的各种操作。如果要数据增强,可以再加一些裁剪、反转之类的,都可以。比如下面的
transforms.RandomSizedCrop
transforms.RandomHorizontalFlip()
还有一个问题是,如何知道文件夹名被映射成了什么标签,这个可以直接查看定义的对象的class_to_idx属性
这个ImageFolder产生的dataset对象,第一维就是第几张图片,第二维元素0是图片矩阵元素1是label
接下来就是建立模型+训练了
训练的过程和第一种一样
第三种
这种情况是最通用的,适用于不是分类问题,或者标签不是简单的文件名的映射
思路就是自己定义一个Dataset的派生类,并且对数据的处理、数据增强之类的都需要自己定义,这些定义的时候利用__call_()就可以了
实现过程是:
首先
定义一个Dataset的派生类,这个派生类目标是重载两个魔法方法__len__(),__getitem__()
__len__()函数是在调用len(对象)的时候会被调用并返回,重载的目的是,在调用的时候返回数据集的大小__getitem__()函数可让对象编程可迭代的,定义了它之后就可以使得对像被for语句迭代,重载它的目的是能够使得它每次都迭代返回数据集的一个样本
现在定义一个派生类
classFaceLandmarksDataset(Dataset):
"""FaceLandmarksdataset."""
def__init__(self,csv_file,root_dir,transform=None):
Args:
csv_file(string):Pathtothecsvfilewithannotations.
root_dir(string):Directorywithalltheimages.
transform(callable,optional):Optionaltransformtobeapplied
onasample.
self.landmarks_frame=pd.read_csv(csv_file)
self.root_dir=root_dir
self.transform=transform
def__len__(self):
returnlen(self.landmarks_frame)
def__getitem__(self,idx):
img_name=os.path.join(self.root_dir,
self.landmarks_frame.iloc[idx,0])
image=io.imread(img_name)
landmarks=self.landmarks_frame.iloc[idx,1:].as_matrix()
landmarks=landmarks.astype('float').reshape(-1,2)
sample={'image':image,'landmarks':landmarks}
ifself.transform:
sample=self.transform(sample)
returnsample
构造函数就是定义了一些属性,例如读取出保存整个数据集的表格,然后len就是返回了数据集的数目,getitem则是定义了迭代返回一个数据集样本,返回值可以是包含训练样本和标签的list,也可以是字典,根据这个不同后面的用法也回不太一样(无非就是索引是数字还是key的区别)
除此之外,Dataset一般还会要求输入对数据集的操作,要是不想数据增强,就加个ToTensor就可以(因为要转换成tensor才能训练),要是想数据增强就自己加一些新的类(没错,ToTensor、各种数据增强的函数其实都是一个类,然后定义的一个对象),接着用transforms.Compose把他们连在一起就可以了。上面的transform写的是None,就是不进行数据处理,直接输出
然后实例化这个类,就可以作为DataLoader的参数输入了
face_dataset=FaceLandmarksDataset(csv_file='faces/face_landmarks.csv',
root_dir='faces/')
这时候分析一下这个对象,定义它的参数就是init构造函数需要的,然后对他进行迭代的时候会自动调用getitem例如下面的操作结果是
foriinrange(len(face_dataset)):
sample=face_dataset[i]
print(sample['image'])
print(i,sample['image'].shape,sample['landmarks'].shape)
可以看到每次迭代的时候都会输入一个字典
接下来定义一下DataLoader,就可以去迭代输入了,当然这里还不行,因为需要将数据集转换成tensor才能输入到模型进行训练
那么接下来就是考虑刚才那个DataSet类里的transform怎么改,最初给的是None,不做处理,因此出来的还是ImageArray,至少要实现ToTensor才行。
实现ToTensor这个类就主要用到了__call__()魔法函数
__call__()函数比较特殊,可以让对象本身变成可调用的,可以后面加括号并输入参数,然后就会自动调用call这个魔法函数
Totensor类的实现如下,注意numpy和tensor数组区别在一个通道数在后,一个通道数在前,因此还需要交换不同维度的位置
classToTensor(object):
"""ConvertndarraysinsampletoTensors."""
def__call__(self,sample):
image,landmarks=sample['image'],sample['landmarks']
#swapcoloraxisbecause
#numpyimage:HxWxC
#torchimage:CXHXW
image=image.transpose((2,0,1))
return{'image':torch.from_numpy(image),
'landmarks':torch.from_numpy(landmarks)}
使用的时候先定义一个对象,然后对象(参数)就会自动调用call函数了
再看几个数据增强的类的实现,它们所有的相似点都是,call函数的参数都是sample,也就是输入的数据集
classRescale(object):
"""Rescaletheimageinasampletoagivensize.
Args:
output_size(tupleorint):Desiredoutputsize.Iftuple,outputis
matchedtooutput_size.Ifint,smallerofimageedgesismatched
tooutput_sizekeepingaspectratiothesame.
def__init__(self,output_size):
assertisinstance(output_size,(int,tuple))
self.output_size=output_size
def__call__(self,sample):
image,landmarks=sample['image'],sample['landmarks']
h,w=image.shape[:2]
ifisinstance(self.output_size,int):
ifhw:
new_h,new_w=self.output_size*h/w,self.output_size
else:
new_h,new_w=self.output_size,self.output_size*w/h
else:
new_h,new_w=self.output_size
new_h,new_w=int(new_h),int(new_w)
img=transform.resize(image,(new_h,new_w))
#handwareswappedforlandmarksbecauseforimages,
#xandyaxesareaxis1and0respectively
landmarks=landmarks*[new_w/w,new_h/h]
return{'image':img,'landmarks':landmarks}
classRandomCrop(object):
"""Croprandomlytheimageinasample.
Args:
output_size(tupleorint):Desiredoutputsize.Ifint,squarecrop
ismade.
def__init__(self,output_size):
assertisinstance(output_size,(int,tuple))
ifisinstance(output_size,int):
self.output_size=(output_size,output_size)
else:
assertlen(output_size)==2
self.output_size=output_size
def__call__(self,sample):
image,landmarks=sample['image'],sample['landmarks']
h,w=image.shape[:2]
new_h,new_w=self.output_size
top=np.random.randint(0,h-new_h)
left=np.random.randint(0,w-new_w)
image=image[top:top+new_h,
left:left+new_w]
landmarks=landmarks-[left,top]
return{'image':image,'landmarks':landmarks}
这两个就很清晰了,首先是构造函数要求在定义对象的时候输入参数,接着再用call实现直接调用对象。
用的时候就可以
transformed_dataset=FaceLandmarksDataset(csv_file='faces/face_landmarks.csv',
root_dir='faces/',
transform=transforms.Compose([
Rescale(256),
RandomCrop(224),
ToTensor()
foriinrange(len(transformed_dataset)):
sample=transformed_dataset[i]
print(i,sample['image'].size(),sample['landmarks'].size())
ifi==3:
break
分析一下,首先定义重载DataSet类的对象,transform参数写成上面定义的三个操作类的组合,回头去看这个类的定义
self.transform=transform
上面就定义了一个三个类联合起来的对象
ifself.transform:
sample=self.transform(sample)
然后直接调用该对象,调用了三个类的call函数,就返回了处理后的数据集了
最后终于可以迭代训练了
dataloader=DataLoader(transformed_dataset,batch_size=4,shuffle=True,num_workers=4)
定义一个DataLoader的对象,剩下的用法就和第二种的一样,两重循环进行训练了,这个DataLoader也有点技巧,就是每次对它迭代的时候,返回的还是DataSet类对象返回值的形式,但是里面的内容又在前面加了一个维度,大小就是batch_size,也就是说,DataLoader对象调用的时候每次从迭代器里取出来batch_size个样本,并把它们堆叠起来(这个堆叠是在列表/字典内堆叠的),每次迭代出来的内容还都是一个字典/数组
pytorch学习记录
这是我随便搭的一个简单模型,测试一下
importos
importtorch
importtorch.nnasnn
importtorch.utils.dataasData
importtorchvision
importmatplotlib.pyplotasplt
fromtorchvisionimporttransforms
fromtorchvision.datasetsimportImageFolder
importmatplotlib.pyplotasplt
%matplotlibinline
#定义几个参数
EPOCH=20
BATCH_SIZE=4
LR=0.001
#读取数据
data_transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(mean=[0.5,0.5,0.5],std=[0.5,0.5,0.5])
dataset=ImageFolder("/home/xxx/learn_pytorch/",transform=data_transform)
print(dataset[0][0].size())
print(dataset.class_to_idx)
train_loader=Data.DataLoader(dataset=dataset,batch_size=BATCH_SIZE,shuffle=True)
#定义模型类,是nn.Module的继承类,思路是先把每个层都定义出来,每个都是模型类的属性,然后再定义一个成员函数forward()作为前向传播过程,就可以把每个层连起来了,通过这个就搭好了整个模型
classCNN(nn.Module):
def__init__(self):
super(CNN,self).__init__()
self.conv1=nn.Sequential(
nn.Conv2d(3,16,5,1,2),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2),
self.conv2=nn.Sequential(
nn.Conv2d(16,32,5,1,2),
nn.ReLU(),
nn.MaxPool2d(2),
self.conv3=nn.Sequential(
nn.Conv2d(32,64,5,1,2),
nn.ReLU(),
nn.MaxPool2d(2),
self.conv4=nn.Sequential(
nn.Conv2d(64,128,5,1,2),
nn.ReLU(),
nn.MaxPool2d(2),
self.out1=nn.Sequential(
nn.Linear(128*16*30,1000),
nn.ReLU(),
self.out2=nn.Sequential(
nn.Linear(1000,100),
nn.ReLU(),
self.out3=nn.Sequential(
nn.Linear(100,4),
defforward(self,x):
x=self.conv1(x)
x=self.conv2(x)
x=self.conv3(x)
x=self.conv4(x)
x=x.view(x.size(0),-1)#flattentheoutputofconv2to(batch_size,32*7*7)
x=self.out1(x)
x=self.out2(x)
output=self.out3(x)
returnoutput,x#returnxforvisualization
#如果使用GPU训练要把模型和tensor放到GPU上,通过.cuda来实现
cnn=CNN().cuda()
print(cnn)
#定义优化器对象、损失函数
optimizer=torch.optim.Adam(cnn.parameters(),lr=LR)#optimize
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 湖盐脱水工安全生产能力水平考核试卷含答案
- 珍珠岩焙烧工操作能力知识考核试卷含答案
- 绝缘成型件制造工岗前理论实践考核试卷含答案
- 剑麻栽培工安全意识评优考核试卷含答案
- 家畜饲养员岗位知识技能考核试卷含答案
- 塑料制品生产检验工安全生产知识评优考核试卷含答案
- 印染丝光工岗中团队合作考核试卷含答案
- 塑料制品烧结工安全规程测试考核试卷含答案
- 三氯氢硅还原工安全知识模拟考核试卷含答案
- 气体分馏装置操作工岗位技术改进考核试卷含答案
- 水果农药安全间隔期执行手册
- 软包墙面施工方案及技术措施
- 急诊科护理人员的血气分析解读
- 2025年闽侯县公安局招聘警务辅助人员真题
- 2025年安徽省《保密知识竞赛必刷100题》考试题库及答案详解【有一套】
- 2025年度新疆新星国有资本投资集团有限公司校园招聘5人笔试参考题库附带答案详解
- 脊髓电刺激护理
- 自愿收养协议书范本
- 新时代幼儿园教师职业行为十项准则培训
- 食品管理管理制度
- 市政工程工程简介
评论
0/150
提交评论