欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用pytorch讀取數(shù)據(jù)集

 更新時間:2022年05月18日 11:36:20   作者:日常搬磚xbw  
這篇文章主要介紹了使用pytorch讀取數(shù)據(jù)集,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

pytorch讀取數(shù)據(jù)集

使用pytorch讀取數(shù)據(jù)集一般有三種情況

第一種

讀取官方給的數(shù)據(jù)集,例如Imagenet,CIFAR10,MNIST等

這些庫調(diào)用torchvision.datasets.XXXX()即可,例如想要讀取MNIST數(shù)據(jù)集

import torch
import torch.nn as nn
import torch.utils.data as Data
import torchvision
train_data = torchvision.datasets.MNIST(
    root='./mnist/',
    train=True,                                     # this is training data
    transform=torchvision.transforms.ToTensor(),    # Converts a PIL.Image or numpy.ndarray to
                                                    # torch.FloatTensor of shape (C x H x W) and normalize in the range [0.0, 1.0]
    download=True,
)

這樣就會自動從網(wǎng)上下載MNIST數(shù)據(jù)集,并且以保存好的數(shù)據(jù)格式來讀取

然后直接定義DataLoader的一個對象,就可以進(jìn)行訓(xùn)練了

train_loader = Data.DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True)
for epoch in range(EPOCH):
    for step, (b_x, b_y) in enumerate(train_loader):   # gives batch data, normalize x when iterate train_loader
    	XXXX
    	XXXX

第二種

這種就比較常用了,針對圖像的分類問題

適用情況是,對于圖片的多分類問題,圖片按照指定的格式來存放:

  • 根路徑/類別(標(biāo)簽label)/圖片

按照上面的格式來存放圖片,根路徑下面保存了許多文件夾,每個文件夾中存放了某一類的圖片,并且文件夾名就是類的映射,例如這樣,根目錄就是learn_pytorch,下面的每個文件夾代表一個類,類的名字隨便命名,在訓(xùn)練過程中會自動被映射成0,1,2,3…

在這里插入圖片描述

在這里插入圖片描述

保存成這樣的格式之后,就可以直接利用pytorch定義好的派生類ImageFolder來讀取了,ImageFolder其實(shí)就是Dataset的派生類,專門被定義來讀取特定格式的圖片的,它也是 torchvision庫幫我們方便使用的,比如這樣

然后就可以作為DataLoader的數(shù)據(jù)集輸入用了

from torchvision.datasets import ImageFolder
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)

它的構(gòu)造函數(shù)要求輸入兩個參數(shù),一個根目錄,一個對數(shù)據(jù)的操作,因?yàn)閳D片被自動讀取成PILimage數(shù)據(jù)格式,因此Totensor()必不可少,而且可以用transforms.Compose把許多操作合成一個參數(shù)輸入,就能實(shí)現(xiàn)數(shù)據(jù)增強(qiáng),非常方便。上面的例子是先轉(zhuǎn)成tensor,然后歸一化,沒做數(shù)據(jù)增強(qiáng)的各種操作。如果要數(shù)據(jù)增強(qiáng),可以再加一些裁剪、反轉(zhuǎn)之類的,都可以。比如下面的

transforms.RandomSizedCrop
transforms.RandomHorizontalFlip()

還有一個問題是,如何知道文件夾名被映射成了什么標(biāo)簽,這個可以直接查看定義的對象的class_to_idx屬性

這個ImageFolder產(chǎn)生的dataset對象,第一維就是第幾張圖片,第二維元素0是圖片矩陣 元素1是label

在這里插入圖片描述

接下來就是建立模型+訓(xùn)練了

訓(xùn)練的過程和第一種一樣

在這里插入圖片描述

第三種

這種情況是最通用的,適用于不是分類問題,或者標(biāo)簽不是簡單的文件名的映射

思路就是自己定義一個Dataset的派生類,并且對數(shù)據(jù)的處理、數(shù)據(jù)增強(qiáng)之類的都需要自己定義,這些定義的時候利用__call_()就可以了

實(shí)現(xiàn)過程是:

首先

定義一個Dataset的派生類,這個派生類目標(biāo)是重載兩個魔法方法 __ len __ (),__ getitem__()

  • __ len __ () 函數(shù)是在調(diào)用 len(對象)的時候會被調(diào)用并返回,重載的目的是,在調(diào)用的時候返回數(shù)據(jù)集的大小
  • __getitem __() 函數(shù)可讓對象編程可迭代的,定義了它之后就可以使得對像被for語句迭代,重載它的目的是能夠使得它每次都迭代返回數(shù)據(jù)集的一個樣本

現(xiàn)在定義一個派生類

class FaceLandmarksDataset(Dataset):
    """Face Landmarks dataset."""
    def __init__(self, csv_file, root_dir, transform=None):
        """
        Args:
            csv_file (string): Path to the csv file with annotations.
            root_dir (string): Directory with all the images.
            transform (callable, optional): Optional transform to be applied
                on a sample.
        """
        self.landmarks_frame = pd.read_csv(csv_file)
        self.root_dir = root_dir
        self.transform = transform
    def __len__(self):
        return len(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}
        if self.transform:
            sample = self.transform(sample)
        return sample

構(gòu)造函數(shù)就是定義了一些屬性,例如讀取出保存整個數(shù)據(jù)集的表格,然后len就是返回了數(shù)據(jù)集的數(shù)目,getitem則是定義了迭代返回一個數(shù)據(jù)集樣本,返回值可以是包含訓(xùn)練樣本和標(biāo)簽的list,也可以是字典,根據(jù)這個不同后面的用法也回不太一樣(無非就是索引是數(shù)字還是key的區(qū)別)

除此之外,Dataset一般還會要求輸入對數(shù)據(jù)集的操作,要是不想數(shù)據(jù)增強(qiáng),就加個ToTensor就可以(因?yàn)橐D(zhuǎn)換成tensor才能訓(xùn)練),要是想數(shù)據(jù)增強(qiáng)就自己加一些新的類(沒錯,ToTensor、各種數(shù)據(jù)增強(qiáng)的函數(shù)其實(shí)都是一個類,然后定義的一個對象),接著用transforms.Compose把他們連在一起就可以了。上面的transform寫的是None,就是不進(jìn)行數(shù)據(jù)處理,直接輸出

然后實(shí)例化這個類,就可以作為DataLoader的參數(shù)輸入了

face_dataset = FaceLandmarksDataset(csv_file='faces/face_landmarks.csv',
                                    root_dir='faces/')

這時候分析一下這個對象,定義它的參數(shù)就是init構(gòu)造函數(shù)需要的,然后對他進(jìn)行迭代的時候會自動調(diào)用getitem 例如下面的操作結(jié)果是

for i in range(len(face_dataset)):
    sample = face_dataset[i]
    print(sample['image'])
    print(i,sample['image'].shape, sample['landmarks'].shape)

在這里插入圖片描述

可以看到每次迭代的時候都會輸入一個字典

接下來定義一下DataLoader,就可以去迭代輸入了,當(dāng)然這里還不行,因?yàn)樾枰獙?shù)據(jù)集轉(zhuǎn)換成tensor才能輸入到模型進(jìn)行訓(xùn)練

那么接下來就是考慮剛才那個DataSet類里的transform怎么改,最初給的是None,不做處理,因此出來的還是ImageArray,至少要實(shí)現(xiàn)ToTensor才行。

實(shí)現(xiàn)ToTensor這個類就主要用到了 __call __()魔法函數(shù)

__ call__()函數(shù)比較特殊,可以讓對象本身變成可調(diào)用的,可以后面加括號并輸入?yún)?shù),然后就會自動調(diào)用call這個魔法函數(shù)

Totensor類的實(shí)現(xiàn)如下,注意numpy和tensor數(shù)組區(qū)別在 一個通道數(shù)在后,一個通道數(shù)在前,因此還需要交換不同維度的位置

class ToTensor(object):
    """Convert ndarrays in sample to Tensors."""
    def __call__(self, sample):
        image, landmarks = sample['image'], sample['landmarks']
        # swap color axis because
        # numpy image: H x W x C
        # torch image: C X H X W
        image = image.transpose((2, 0, 1))
        return {'image': torch.from_numpy(image),
                'landmarks': torch.from_numpy(landmarks)}

使用的時候先定義一個對象,然后 對象(參數(shù))就會自動調(diào)用call函數(shù)了

再看幾個數(shù)據(jù)增強(qiáng)的類的實(shí)現(xiàn),它們所有的相似點(diǎn)都是,call函數(shù)的參數(shù)都是sample,也就是輸入的數(shù)據(jù)集

class Rescale(object):
    """Rescale the image in a sample to a given size.
    Args:
        output_size (tuple or int): Desired output size. If tuple, output is
            matched to output_size. If int, smaller of image edges is matched
            to output_size keeping aspect ratio the same.
    """
    def __init__(self, output_size):
        assert isinstance(output_size, (int, tuple))
        self.output_size = output_size
    def __call__(self, sample):
        image, landmarks = sample['image'], sample['landmarks']
        h, w = image.shape[:2]
        if isinstance(self.output_size, int):
            if h > w:
                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))
        # h and w are swapped for landmarks because for images,
        # x and y axes are axis 1 and 0 respectively
        landmarks = landmarks * [new_w / w, new_h / h]
        return {'image': img, 'landmarks': landmarks}
class RandomCrop(object):
    """Crop randomly the image in a sample.
    Args:
        output_size (tuple or int): Desired output size. If int, square crop
            is made.
    """
    def __init__(self, output_size):
        assert isinstance(output_size, (int, tuple))
        if isinstance(output_size, int):
            self.output_size = (output_size, output_size)
        else:
            assert len(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}

這兩個就很清晰了,首先是構(gòu)造函數(shù)要求在定義對象的時候輸入?yún)?shù),接著再用call實(shí)現(xiàn)直接調(diào)用對象。

用的時候就可以

transformed_dataset = FaceLandmarksDataset(csv_file='faces/face_landmarks.csv',
                                           root_dir='faces/',
                                           transform=transforms.Compose([
                                               Rescale(256),
                                               RandomCrop(224),
                                               ToTensor()
                                           ]))
for i in range(len(transformed_dataset)):
    sample = transformed_dataset[i]
    print(i, sample['image'].size(), sample['landmarks'].size())
    if i == 3:
        break

分析一下,首先定義重載DataSet類的對象,transform參數(shù)寫成上面定義的三個操作類的組合,回頭去看這個類的定義

        self.transform = transform

上面就定義了一個三個類聯(lián)合起來的對象

        if self.transform:
            sample = self.transform(sample)

然后直接調(diào)用該對象,調(diào)用了三個類的call函數(shù),就返回了處理后的數(shù)據(jù)集了

最后終于可以迭代訓(xùn)練了

在這里插入圖片描述

dataloader = DataLoader(transformed_dataset, batch_size=4, shuffle=True, num_workers=4)

定義一個DataLoader的對象,剩下的用法就和第二種的一樣,兩重循環(huán)進(jìn)行訓(xùn)練了,這個DataLoader也有點(diǎn)技巧,就是每次對它迭代的時候,返回的還是DataSet類對象返回值的形式,但是里面的內(nèi)容又在前面加了一個維度,大小就是batch_size,也就是說,DataLoader對象調(diào)用的時候每次從迭代器里取出來batch_size個樣本,并把它們堆疊起來(這個堆疊是在列表/字典內(nèi)堆疊的),每次迭代出來的內(nèi)容還都是一個字典/數(shù)組

pytorch學(xué)習(xí)記錄

這是我隨便搭的一個簡單模型,測試一下

import os
import torch
import torch.nn as nn
import torch.utils.data as Data
import torchvision
import matplotlib.pyplot as plt
from torchvision import transforms
from torchvision.datasets import ImageFolder
import matplotlib.pyplot as plt
%matplotlib inline
#定義幾個參數(shù)
EPOCH = 20
BATCH_SIZE = 4
LR = 0.001
#讀取數(shù)據(jù)
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的繼承類,思路是先把每個層都定義出來,每個都是模型類的屬性,然后再定義一個成員函數(shù)forward()作為前向傳播過程,就可以把每個層連起來了,通過這個就搭好了整個模型
class CNN(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),
        )
    def forward(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)           # flatten the output of conv2 to (batch_size, 32 * 7 * 7)
        x = self.out1(x)
        x = self.out2(x)
        output = self.out3(x)
        return output, x    # return x for visualization
#如果使用GPU訓(xùn)練要把模型和tensor放到GPU上,通過.cuda來實(shí)現(xiàn)
cnn = CNN().cuda()
print(cnn)
#定義優(yōu)化器對象、損失函數(shù)
optimizer = torch.optim.Adam(cnn.parameters(), lr=LR)   # optimize all cnn parameters
loss_func = nn.CrossEntropyLoss()                       # the target label is not one-hotted
#二重循環(huán)開始訓(xùn)練,外層循環(huán)是迭代次數(shù),第二重循環(huán)就是每次對batch_size的數(shù)據(jù)讀取并訓(xùn)練
for epoch in range(EPOCH):
    accy_count = 0
    for step,(b_x,b_y) in enumerate(train_loader):
        output = cnn(b_x.cuda())[0]
        loss = loss_func(output,b_y.cuda())     #carcute loss
        optimizer.zero_grad()           #clear gradient
        loss.backward()                 #sovel gradient
        optimizer.step()                #gradient sovel
        output_index = torch.max(output,1)[1].cpu().data.numpy()
        accy_count += float((output_index==b_y.data.numpy()).astype(int).sum())
    accuracy = accy_count/(BATCH_SIZE * train_loader.__len__())
    print("Epoch:",epoch," accuracy is: ",accuracy)

注意事項(xiàng)

使用GPU訓(xùn)練的時候,要把模型、tensor都放在GPU上,就是后面加個.cuda(),例如定義模型對象的時候,cnn.cuda()

還有輸入進(jìn)模型、計算loss的時候,b_x.cuda() b_y.cuda()

tensor a 轉(zhuǎn)numpy a.data.numpy()

如果是在GPU上,要先a.cpu().data.numpy()

nn.CrossEntropyLoss()這個損失函數(shù)是個大坑,它是softmax + 歸一化,所以使用這個損失函數(shù)的時候模型最后就不要再加softmax了,不然會發(fā)現(xiàn)自己的損失就那幾個值,也降不下去

輸入模型的 input圖像,格式為(batch_size,Nc,H,W)的四維矩陣

以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • django 在原有表格添加或刪除字段的實(shí)例

    django 在原有表格添加或刪除字段的實(shí)例

    今天小編就為大家分享一篇django 在原有表格添加或刪除字段的實(shí)例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-05-05
  • 用python打開攝像頭并把圖像傳回qq郵箱(Pyinstaller打包)

    用python打開攝像頭并把圖像傳回qq郵箱(Pyinstaller打包)

    這篇文章主要介紹了用python打開攝像頭并把圖像傳回qq郵箱,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • 解決Pymongo insert時會自動添加_id的問題

    解決Pymongo insert時會自動添加_id的問題

    這篇文章主要介紹了解決Pymongo insert時會自動添加_id的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • django中cookiecutter的使用教程

    django中cookiecutter的使用教程

    這篇文章主要給大家介紹了關(guān)于django中cookiecutter使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • 利用python如何處理百萬條數(shù)據(jù)(適用java新手)

    利用python如何處理百萬條數(shù)據(jù)(適用java新手)

    這篇文章主要給大家介紹了關(guān)于利用python如何處理百萬條數(shù)據(jù)的相關(guān)資料,本文的教程非常適用于java新手,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-06-06
  • Python二叉樹定義與遍歷方法實(shí)例分析

    Python二叉樹定義與遍歷方法實(shí)例分析

    這篇文章主要介紹了Python二叉樹定義與遍歷方法,結(jié)合實(shí)例形式分析了二叉樹的概念、原理及Python定義、遍歷二叉樹相關(guān)操作技巧,需要的朋友可以參考下
    2018-05-05
  • Python中requests庫的基本概念與具體使用方法

    Python中requests庫的基本概念與具體使用方法

    requests庫是用python編寫的基于urllib,requests唯一的一個非轉(zhuǎn)基因的Python HTTP庫,下面這篇文章主要給大家介紹了關(guān)于Python中requests庫的基本概念與具體使用方法,需要的朋友可以參考下
    2022-08-08
  • 總結(jié)歸納python os庫常用方法

    總結(jié)歸納python os庫常用方法

    這篇文章主要為大家介紹了python os庫常用方法的總結(jié)歸納,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • 利用pytorch實(shí)現(xiàn)對CIFAR-10數(shù)據(jù)集的分類

    利用pytorch實(shí)現(xiàn)對CIFAR-10數(shù)據(jù)集的分類

    今天小編就為大家分享一篇利用pytorch實(shí)現(xiàn)對CIFAR-10數(shù)據(jù)集的分類,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-01-01
  • python xlsxwriter模塊的使用

    python xlsxwriter模塊的使用

    這篇文章主要介紹了python xlsxwriter模塊的使用,幫助大家更好的理解和使用python,感興趣的朋友可以了解下
    2020-12-12

最新評論