解決pytorch讀取自制數(shù)據(jù)集出現(xiàn)過的問題
問題1
問題描述:
TypeError: default_collate: batch must contain tensors, numpy arrays, numbers, dicts or lists; found <class 'PIL.Image.Image'>
解決方式
數(shù)據(jù)格式不對, 把image轉(zhuǎn)成tensor,參數(shù)transform進行如下設(shè)置就可以了:transform=transform.ToTensor()。注意檢測一下transform
問題2
問題描述:
TypeError: append() takes exactly one argument (2 given)
出現(xiàn)問題的地方
imgs.append(words[0], int(words[1]))
解決方式
加括號,如下
imgs.append((words[0], int(words[1])))
問題3
問題描述
RuntimeError: Input type (torch.cuda.FloatTensor) and weight type (torch.FloatTensor) should be the same
解決方式
數(shù)據(jù)和模型不在同一設(shè)備上,應(yīng)該要么都在GPU運行,要么都在CPU
問題4
問題描述
RuntimeError: Given groups=1, weight of size [64, 1, 3, 3], expected input[1, 3, 512, 512] to have 1 channels, but got 3 channels instead
解決方式
圖像竟然是RGB,但我的訓(xùn)練圖像是一通道的灰度圖,所以得想辦法把 mode 轉(zhuǎn)換成灰度圖L
補充:神經(jīng)網(wǎng)絡(luò) pytorch 數(shù)據(jù)集讀取(自動讀取數(shù)據(jù)集,手動讀取自己的數(shù)據(jù))
對于pytorch,我們有現(xiàn)成的包裝好的數(shù)據(jù)集可以使用,也可以自己創(chuàng)建自己的數(shù)據(jù)集,大致來說有三種方法,這其中用到的兩個包是datasets和DataLoader
datasets:用于將數(shù)據(jù)和標(biāo)簽打包成數(shù)據(jù)集
DataLoader:用于對數(shù)據(jù)集的高級處理,比如分組,打亂,處理等,在訓(xùn)練和測試中可以直接使用DataLoader進行處理
第一種 現(xiàn)成的打包數(shù)據(jù)集
這種比較簡答,只需要現(xiàn)成的幾行代碼和一個路徑就可以完成,但是一般都是常用比如cifar-10
對于常用數(shù)據(jù)集,可以使用torchvision.datasets直接進行讀取,這是對其常用的處理,該類也是繼承于torch.utils.data.Dataset。
#是第一次運行的話會下載數(shù)據(jù)集 現(xiàn)成的話可以使用root參數(shù)指定數(shù)據(jù)集位置 # 存放的格式如下圖 # 根據(jù)接口讀取默認的CIFAR10數(shù)據(jù) 進行訓(xùn)練和測試 #預(yù)處理 transform = transform.Compose([transform.ToTensor(), transform.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) #讀取數(shù)據(jù)集 trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=False, transform=transform) #打包成DataLoader trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True, num_workers=1) #同上 testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=False, transform=transform) testloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=False, num_workers=1) classes = (1,2,3,4,5,6,7,8,9,10) #類別定義 #使用 for epoch in range(3): running_loss = 0.0 #清空loss for i, data in enumerate(trainloader, 0): # get the inputs inputs, labels = data #trainloader返回:id,image,labels # 將inputs與labels裝進Variable中 inputs, labels = Variable(inputs), Variable(labels) #使用print代替輸出 print("epoch:", epoch, "的第", i, "個inputs", inputs.data.size(), "labels", labels.data.size())
第二種 自己的圖像分類
這也是一個方便的做法,在pytorch中提供了torchvision.datasets.ImageFolder讓我們訓(xùn)練自己的圖像。
要求:創(chuàng)建train和test文件夾,每個文件夾下按照類別名字存儲圖像就可以實現(xiàn)dataloader
這里還是拿上個舉例子吧,實際上也可以是我們的數(shù)據(jù)集
每個下面的布局是這樣的
# 預(yù)處理 transform = transform.Compose([transform.ToTensor(), transform.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) #使用torchvision.datasets.ImageFolder讀取數(shù)據(jù)集 指定train 和 test文件夾 img_data = torchvision.datasets.ImageFolder('data/cifar-10/train/', transform=transform) data_loader = torch.utils.data.DataLoader(img_data, batch_size=4, shuffle=True, num_workers=1) testset = torchvision.datasets.ImageFolder('data/cifar-10/test/', transform=transform) testloader = torch.utils.data.DataLoader(testset, batch_size=4, shuffle=True, num_workers=1) for epoch in range(3): for i, data in enumerate(trainloader, 0): # get the inputs inputs, labels = data #trainloader返回:id,image,labels # 將inputs與labels裝進Variable中 inputs, labels = Variable(inputs), Variable(labels) #使用print代替輸出 print("epoch:", epoch, "的第", i, "個inputs", inputs.data.size(), "labels", labels.data.size())
第三種 一維向量數(shù)據(jù)集
這個是比較尷尬的,首先我們
假設(shè)將數(shù)存儲到txt等文件中,先把他讀取出來,讀取的部分就不仔細說了,讀到一個列表里就可以
常用的可以是列表等,舉例子
trainlist = [] # 保存特征的列表 targetpath = 'a/b/b' filelist = os.listdir(targetpath) #列出文件夾下所有的目錄與文件 filecount = len(filelist) # 根據(jù)根路徑 讀取所有文件名 循環(huán)讀取文件內(nèi)容 添加到list for i in range(filecount): filepath = os.path.join(targetpath, filelist[j]) with open(filepath, 'r') as f: line = f.readline() # 例如存儲格式為 1,2,3,4,5,6 數(shù)字之間以逗號隔開 templist = list(map(int, line.split(','))) trainlist.append(templist) # 數(shù)據(jù)讀取完畢 現(xiàn)在為維度為filecount的列表 我們需要轉(zhuǎn)換格式和類型 # 將數(shù)據(jù)轉(zhuǎn)換為Tensor # 假如我們的兩類數(shù)據(jù)分別存在list0 和 list1中 split = len(list0) # 用于記錄標(biāo)簽的分界 #使用numpy.array 和 torch.from_numpy 連續(xù)將其轉(zhuǎn)換為tensor 使用torch.cat拼接 train0_numpy = numpy.array(list0) train1_numpy = numpy.array(list1) train_tensor = torch.cat([torch.from_numpy(train0_numpy), torch.from_numpytrain1_numpy)], 0) #現(xiàn)在的尺寸是【樣本數(shù),長度】 然而在使用神 經(jīng)網(wǎng)絡(luò)處理一維數(shù)據(jù)要求【樣本數(shù),維度,長度】 # 這個維度指的像一個圖像實際上是一個二維矩陣 但是有三個RGB通道 實際就為【3,行,列】 那么需要處理三個矩陣 # 我們需要在我們的數(shù)據(jù)中加上這個維度信息 # 注意類型要一樣 可以轉(zhuǎn)換 shaper = train_tensor.shape #獲取維度 【樣本數(shù),長度】 aa = torch.ones((shaper[0], 1, shaper[1])) # 生成目標(biāo)矩陣 for i in range(shaper[0]): # 將所有樣本復(fù)制到新矩陣 · aa[i][0][:] = train_tensor[i][:] train_tensor = aa # 完成了數(shù)據(jù)集的轉(zhuǎn)換 【樣本數(shù),維度,長度】 # 注 意 如果是讀取的圖像 我們需要的目標(biāo)維度是【樣本數(shù),維度,size_w,size_h】 # 卷積接受的輸入是這樣的四維度 最后的兩個是圖像的尺寸 維度表示是通道數(shù)量 # 下面是生成標(biāo)簽 標(biāo)簽注意類別之間的分界 split已經(jīng)在上文計算出來 # 訓(xùn)練標(biāo)簽的 total = len(list0) + len(list1) train_label = numpy.zeros(total) train_label[split+1:total] = 1 train_label_tensor = torch.from_numpy(train_label).int() # print(train_tensor.size(),train_label_tensor.size()) # 搭建dataloader完畢 train_dataset = TensorDataset(train_tensor, train_label_tensor) train_loader = DataLoader(dataset=train_dataset, batch_size=4, shuffle=True) for epoch in range(3): for i, data in enumerate(trainloader, 0): # get the inputs inputs, labels = data #trainloader返回:id,image,labels # 將inputs與labels裝進Variable中 inputs, labels = Variable(inputs), Variable(labels) #使用print代替輸出 print("epoch:", epoch, "的第", i, "個inputs", inputs.data.size(), "labels", labels.data.size())
第四種 保存路徑和標(biāo)簽的方式創(chuàng)建數(shù)據(jù)集
該方法需要略微的麻煩一些,首先你有一個txt,保存了文件名和對應(yīng)的標(biāo)簽,大概是這個意思
然后我們在程序中,根據(jù)給定的根目錄找到文件,并將標(biāo)簽對應(yīng)保存
class Dataset(object): """An abstract class representing a Dataset. All other datasets should subclass it. All subclasses should override ``__len__``, that provides the size of the dataset, and ``__getitem__``, supporting integer indexing in range from 0 to len(self) exclusive. """ def __getitem__(self, index): raise NotImplementedError def __len__(self): raise NotImplementedError def __add__(self, other): return ConcatDataset([self, other])
這是dataset的原本內(nèi)容,getitem就是獲取元素的部分,用于返回對應(yīng)index的數(shù)據(jù)和標(biāo)簽。那么大概需要做的是我們將txt的內(nèi)容讀取進來,使用程序處理標(biāo)簽和數(shù)據(jù)
# coding: utf-8 from PIL import Image from torch.utils.data import Dataset class MyDataset(Dataset): # 初始化讀取txt 可以設(shè)定變換 def __init__(self, txt_path, transform = None, target_transform = None): fh = open(txt_path, 'r') imgs = [] for line in fh: line = line.rstrip() words = line.split() # 保存列表 其中有圖像的數(shù)據(jù) 和標(biāo)簽 imgs.append((words[0], int(words[1]))) self.imgs = imgs self.transform = transform self.target_transform = target_transform def __getitem__(self, index): fn, label = self.imgs[index] img = Image.open(fn).convert('RGB') if self.transform is not None: img = self.transform(img) # 返回圖像和標(biāo)簽 return img, label def __len__(self): return len(self.imgs) # 當(dāng)然也可以創(chuàng)建myImageFloder 其txt格式在下圖顯示 import os import torch import torch.utils.data as data from PIL import Image def default_loader(path): return Image.open(path).convert('RGB') class myImageFloder(data.Dataset): def __init__(self, root, label, transform = None, target_transform=None, loader=default_loader): fh = open(label) #打開label文件 c=0 imgs=[] # 保存圖像的列表 class_names=[] for line in fh.readlines(): #讀取每一行數(shù)據(jù) if c==0: class_names=[n.strip() for n in line.rstrip().split(' ')] else: cls = line.split() #分割為列表 fn = cls.pop(0) #彈出最上的一個 if os.path.isfile(os.path.join(root, fn)): # 組合路徑名 讀取圖像 imgs.append((fn, tuple([float(v) for v in cls]))) #添加到列表 c=c+1 # 設(shè)置信息 self.root = root self.imgs = imgs self.classes = class_names self.transform = transform self.target_transform = target_transform self.loader = loader def __getitem__(self, index): # 獲取圖像 給定序號 fn, label = self.imgs[index] #讀取圖像的內(nèi)容和對應(yīng)的label img = self.loader(os.path.join(self.root, fn)) if self.transform is not None: # 是否變換 img = self.transform(img) return img, torch.Tensor(label) # 返回圖像和label def __len__(self): return len(self.imgs) def getName(self): return self.classes #
# 而后使用的時候就可以正常的使用 trainset = MyDataset(txt_path=pathFile,transform = None, target_transform = None) # trainset = torch.utils.data.DataLoader(myFloder.myImageFloder(root = "../data/testImages/images", label = "../data/testImages/test_images.txt", transform = mytransform ), batch_size= 2, shuffle= False, num_workers= 2) trainloader = torch.utils.data.DataLoader(trainset, batch_size=32, shuffle=True, num_workers=8)
它的要點是,繼承dataset,在初始化中處理txt文本數(shù)據(jù),保存對應(yīng)的數(shù)據(jù),并實現(xiàn)對應(yīng)的功能。
這其中的原理就是如此,但是注意可能有些許略微不恰當(dāng)?shù)牡胤?,可能就需要到時候現(xiàn)場調(diào)試了。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python return語句如何實現(xiàn)結(jié)果返回調(diào)用
這篇文章主要介紹了Python return語句如何實現(xiàn)結(jié)果返回調(diào)用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-10-10Python函數(shù)元數(shù)據(jù)實現(xiàn)為一個參數(shù)指定多個類型
這篇文章主要介紹了Python函數(shù)元數(shù)據(jù)實現(xiàn)為一個參數(shù)指定多個類型方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-02-02Python3.4 tkinter,PIL圖片轉(zhuǎn)換
我們給大家整理了關(guān)于Python3.4 tkinter,PIL圖片轉(zhuǎn)換的相關(guān)完整代碼,大家可以學(xué)習(xí)測試下。2018-06-06Pandas中DataFrame基本函數(shù)整理(小結(jié))
這篇文章主要介紹了Pandas中DataFrame基本函數(shù)整理(小結(jié)),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07Python3調(diào)用百度AI識別圖片中的文字功能示例【測試可用】
這篇文章主要介紹了Python3調(diào)用百度AI識別圖片中的文字功能,結(jié)合實例形式分析了Python3安裝及使用百度AI接口的相關(guān)操作技巧,并附帶說明了百度官方AI平臺的注冊及接口調(diào)用操作方法,需要的朋友可以參考下2019-03-03Python中shapefile轉(zhuǎn)換geojson的示例
今天小編就為大家分享一篇關(guān)于Python中shapefile轉(zhuǎn)換geojson的示例,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-01-01