pytorch 數(shù)據(jù)準(zhǔn)備

準(zhǔn)備工作

本篇文章參考自pytorch官方教程拴测,即末尾參考的第一篇垫蛆,略去了不必要的亂七八糟的matlab顯示功能壹将,保留最實(shí)用的數(shù)據(jù)加載功能嗤攻。
先從這里下載并解壓示例數(shù)據(jù)集。這里介紹如何創(chuàng)建一個(gè)dataloader去加載該文件夾內(nèi)的數(shù)據(jù)集诽俯。

import torch
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms, utils
import os
import pandas as pd
from skimage import io, transform
import numpy as np
import matplotlib.pyplot as plt

Dataset Class

torch.utils.data.Dataset是一個(gè)抽象類妇菱,代表了一個(gè)數(shù)據(jù)集。自定義數(shù)據(jù)集的時(shí)候需要重寫兩個(gè)方法暴区。
__len__使得len(dataset)可以返回dataset的大小
__getitem__支持dataset[i]可以取出第i個(gè)數(shù)據(jù)闯团。
下面為我們的數(shù)據(jù)集創(chuàng)建一個(gè)dataset類,首先會(huì)在__init__方法中讀取csv文件仙粱,在__getitem__方法中讀取圖片房交,這樣可以節(jié)約內(nèi)存,根據(jù)需要讀取圖片伐割,而不是一次性加載圖片到內(nèi)存中候味。

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:]
        landmarks = np.array([landmarks])
        landmarks = landmarks.astype('float').reshape(-1, 2)
        sample = {'image': image, 'landmarks': landmarks}
        if self.transform:
            sample = self.transform(sample)
        return sample
face_dataset = FaceLandmarksDataset(csv_file='data/faces/face_landmarks.csv', root_dir='data/faces/')

至此數(shù)據(jù)就可以從face_dataset中讀取了。

變換

可以看到文件夾內(nèi)的圖片大小都不一致隔心,大多數(shù)的網(wǎng)絡(luò)都需要接受統(tǒng)一大小白群,所以需要對(duì)數(shù)據(jù)進(jìn)行一些預(yù)處理,例如縮放济炎,隨機(jī)裁剪川抡,轉(zhuǎn)化成張量。
我們會(huì)將這些方法寫道一個(gè)可調(diào)用的類中,而不是簡(jiǎn)單的函數(shù)中崖堤,如此一來變換的參數(shù)就不用每次調(diào)用都傳遞一次侍咱。所以我們需要在類中實(shí)現(xiàn)__call__方法,有必要的話還要實(shí)現(xiàn)__init__方法密幔。
我們可以像下面這樣調(diào)用楔脯。

tsfm = Transform(params)
transformed_sample = tsfm(sample)

像下面這樣定義

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}

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)}

組合變換

如果我們需要做很最多變換,就需要把這些類組合到一起胯甩。像下面這樣

scale = Rescale(256)
crop = RandomCrop(128)
composed = transforms.Compose([Rescale(256),
                               RandomCrop(224)])

# Apply each of the above transforms on sample.
fig = plt.figure()
sample = face_dataset[65]
for i, tsfrm in enumerate([scale, crop, composed]):
    transformed_sample = tsfrm(sample)

    ax = plt.subplot(1, 3, i + 1)
    plt.tight_layout()
    ax.set_title(type(tsfrm).__name__)
plt.show()

迭代器

下面把這些變換都結(jié)合到一起創(chuàng)建一個(gè)dataset昧廷。所有圖片都從文件名中,變換在讀取圖片是生效偎箫,每一個(gè)變換都是隨機(jī)的木柬。

transformed_dataset = FaceLandmarksDataset(csv_file='data/faces/face_landmarks.csv',
                                           root_dir='data/faces/',
                                           transform=transforms.Compose([
                                               Rescale(256),
                                               RandomCrop(224),
                                               ToTensor()
                                           ]))

然而我們丟失了一些特征,比如數(shù)據(jù)的批大小淹办,數(shù)據(jù)隨機(jī)眉枕,多gpu并行處理×可以用dataloader來玩速挑。

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

然后可以遍歷dataloader,讀取里面的數(shù)據(jù)副硅。

還有一點(diǎn)沒看完

## Afterword: torchvision
[Afterword: torchvision](https://pytorch.org/tutorials/beginner/data_loading_tutorial.html#afterword-torchvision)

In this tutorial, we have seen how to write and use datasets, transforms and dataloader. `torchvision` package provides some common datasets and transforms. You might not even have to write custom classes. One of the more generic datasets available in torchvision is `ImageFolder`. It assumes that images are organized in the following way:

<pre style="box-sizing: border-box; font-family: IBMPlexMono, SFMono-Regular, Menlo, Monaco, Consolas, &quot;Liberation Mono&quot;, &quot;Courier New&quot;, monospace; font-size: 14px; margin-top: 0px; margin-bottom: 2.5rem; overflow: auto; display: block; color: rgb(33, 37, 41); padding: 1.375rem; background-color: rgb(243, 244, 247); white-space: pre-wrap; overflow-wrap: break-word;">root/ants/xxx.png
root/ants/xxy.jpeg
root/ants/xxz.png
.
.
.
root/bees/123.jpg
root/bees/nsdf3.png
root/bees/asd932_.png
</pre>

where ‘a(chǎn)nts’, ‘bees’ etc. are class labels. Similarly generic transforms which operate on `PIL.Image` like `RandomHorizontalFlip`, `Scale`, are also available. You can use these to write a dataloader like this:

<pre style="box-sizing: border-box; font-family: IBMPlexMono, SFMono-Regular, Menlo, Monaco, Consolas, &quot;Liberation Mono&quot;, &quot;Courier New&quot;, monospace; font-size: 14px; margin-top: 0px; margin-bottom: 2.5rem; overflow: auto; display: block; color: rgb(33, 37, 41); padding: 1.375rem; background-color: rgb(243, 244, 247); white-space: pre-wrap; overflow-wrap: break-word;">import torch
from torchvision import transforms, datasets

data_transform = transforms.Compose([
        transforms.RandomSizedCrop(224),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.485, 0.456, 0.406],
                             std=[0.229, 0.224, 0.225])
    ])
hymenoptera_dataset = datasets.ImageFolder(root='hymenoptera_data/train',
                                           transform=data_transform)
dataset_loader = torch.utils.data.DataLoader(hymenoptera_dataset,
                                             batch_size=4, shuffle=True,
                                             num_workers=4)</pre>

參考

Data Loading and Processing

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末姥宝,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子恐疲,更是在濱河造成了極大的恐慌腊满,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,651評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件流纹,死亡現(xiàn)場(chǎng)離奇詭異糜烹,居然都是意外死亡违诗,警方通過查閱死者的電腦和手機(jī)漱凝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诸迟,“玉大人茸炒,你說我怎么就攤上這事≌笪” “怎么了壁公?”我有些...
    開封第一講書人閱讀 162,931評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)绅项。 經(jīng)常有香客問我紊册,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,218評(píng)論 1 292
  • 正文 為了忘掉前任囊陡,我火速辦了婚禮芳绩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘撞反。我一直安慰自己妥色,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評(píng)論 6 388
  • 文/花漫 我一把揭開白布遏片。 她就那樣靜靜地躺著嘹害,像睡著了一般。 火紅的嫁衣襯著肌膚如雪吮便。 梳的紋絲不亂的頭發(fā)上笔呀,一...
    開封第一講書人閱讀 51,198評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音髓需,去河邊找鬼凿可。 笑死,一個(gè)胖子當(dāng)著我的面吹牛授账,可吹牛的內(nèi)容都是我干的枯跑。 我是一名探鬼主播,決...
    沈念sama閱讀 40,084評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼白热,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼敛助!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起屋确,我...
    開封第一講書人閱讀 38,926評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤纳击,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后攻臀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體焕数,經(jīng)...
    沈念sama閱讀 45,341評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評(píng)論 2 333
  • 正文 我和宋清朗相戀三年刨啸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了堡赔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,731評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡设联,死狀恐怖善已,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情离例,我是刑警寧澤换团,帶...
    沈念sama閱讀 35,430評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站宫蛆,受9級(jí)特大地震影響艘包,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評(píng)論 3 326
  • 文/蒙蒙 一想虎、第九天 我趴在偏房一處隱蔽的房頂上張望衰絮。 院中可真熱鬧,春花似錦磷醋、人聲如沸猫牡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽淌友。三九已至,卻和暖如春骇陈,著一層夾襖步出監(jiān)牢的瞬間震庭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工你雌, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留器联,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,743評(píng)論 2 368
  • 正文 我出身青樓婿崭,卻偏偏與公主長(zhǎng)得像拨拓,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子氓栈,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容