Fastai-数据准备
Fastai數(shù)據(jù)準備
簡介
數(shù)據(jù)是深度學習的立足之本,本文主要介紹Fastai框架如何進行數(shù)據(jù)加載與數(shù)據(jù)預(yù)處理。
模塊劃分
在之前的Fastai簡介文章我提到過,Fastai最核心的API是按照應(yīng)用領(lǐng)域(任務(wù)類型)進行劃分的,打開官方文檔也會看到Fastai最核心的思路:在一個DataBunch(Fastai的數(shù)據(jù)加載器)上訓(xùn)練一個Model對象,是非常簡單的,只需要將數(shù)據(jù)和模型綁定到一個Learner對象即可。
在Fastai的設(shè)計中,主要有四大應(yīng)用領(lǐng)域,對應(yīng)的四個模塊名為collab(協(xié)同過濾問題)、tabular(表格或者結(jié)構(gòu)化數(shù)據(jù)問題)、text(自然語言處理問題)以及vision(計算機視覺問題)。**本系列所有文章圍繞都是圖像數(shù)據(jù)進行處理,也就是說主要使用vision模塊。**本系列所有文章圍繞都是圖像數(shù)據(jù)進行處理,也就是說主要使用vision模塊。
而在vision模塊中,主要有如下幾個模塊:data(數(shù)據(jù)集構(gòu)建)、models(預(yù)定義模型結(jié)構(gòu),依賴torchvision)、learner(學習器,將模型和數(shù)據(jù)關(guān)聯(lián)起來,定義了大量回調(diào)函數(shù))、transform(數(shù)據(jù)預(yù)處理,包括常見數(shù)據(jù)增廣手段)等。
數(shù)據(jù)集構(gòu)建
為了契合Fastai的API設(shè)計,這里并沒有像之前Pytorch系列和Keras系列那樣重構(gòu)數(shù)據(jù)集為三個文件夾(對應(yīng)訓(xùn)練集、驗證集和測試集),這是考慮到Fastai的自動訓(xùn)練集劃分的API的介紹,事實上劃分數(shù)據(jù)集文件夾也是可以的,只不過多幾個DataBunch對象而已。
關(guān)于數(shù)據(jù)集讀取的API都在fastai.vision.data模塊下,該模塊定義了一個類ImageDataBunch用于處理大量的Image對象,這里的Image對象也是由fastai.vision.data模塊下定義的一種Image類,它包含一個圖片的矩陣表示、路徑、維度、尺寸等屬性,也包含圖像顯示、旋轉(zhuǎn)、縮放、變換等。此外,Fastai依舊定義了不少具體視覺任務(wù)的類如用于圖像分割的ImageSegment、用于檢測的ImageBBox、用于關(guān)鍵點定位的ImagePoints等。
在Fastai中數(shù)據(jù)集的處理都是基于DataBunch類的,ImageDataBunch是其子類,封裝了很多具體的適合計算機視覺使用的方法。而在Fastai中數(shù)據(jù)的導(dǎo)入一般通過data_block API實現(xiàn),不過,對于常見的CV數(shù)據(jù)集格式,ImageDataBunch已經(jīng)做了封裝,無需進行繁瑣的API編寫。這些函數(shù)用于從固定格式的文件中獲取圖像數(shù)據(jù),返回的也是ImageDataBunch對象,具體如下。
Folder(文件夾)
ImageDataBunch.from_folder(path:PathOrStr, # 數(shù)據(jù)集根目錄train:PathOrStr='train', # 訓(xùn)練集子目錄valid:PathOrStr='valid', # 驗證集子目錄test:Union[Path, str, NoneType]=None, # 測試集子目錄valid_pct=None, # 驗證集劃分比例seed:int=None, # 驗證集隨機劃分種子classes:Collection[T_co]=None, # 加載哪些類 **kwargs:Any)從Imagenet風格的數(shù)據(jù)集內(nèi)加載圖像,文件存儲必須是如下格式,其中train、valid和test參數(shù)指定對應(yīng)數(shù)據(jù)集的子文件夾名,如訓(xùn)練集為tra文件夾那么則需要指定train='tra'。
path\train\class1\class2\...valid\class1\class2\...test\當然,如果數(shù)據(jù)集是本文案例的Caltech101的格式(下面所示),那么只需要簡單指定valid_pct作為劃分訓(xùn)練集和驗證集時驗證集占整個數(shù)據(jù)集的比例即可,seed參數(shù)指定隨機劃分種子,便于復(fù)現(xiàn)結(jié)果。
path\class1\class2\class3\執(zhí)行下面的代碼。
from fastai import visiondata = vision.ImageDataBunch.from_folder("../data/101_ObjectCategories/", valid_pct=0.2, size=224) print(data) train_ds = data.train_ds # 取出訓(xùn)練集 valid_ds = data.valid_ds # 取出測試集結(jié)果如下,生成了訓(xùn)練集和驗證集(包括數(shù)據(jù)列表和類別列表)。
ImageDataBunch;Train: LabelList (6942 items) x: ImageList Image (3, 224, 224),Image (3, 224, 224),Image (3, 224, 224),Image (3, 224, 224),Image (3, 224, 224) y: CategoryList accordion,accordion,accordion,accordion,accordion Path: ..\data\101_ObjectCategories;Valid: LabelList (1735 items) x: ImageList Image (3, 224, 224),Image (3, 224, 224),Image (3, 224, 224),Image (3, 224, 224),Image (3, 224, 224) y: CategoryList dollar_bill,umbrella,Motorbikes,pigeon,nautilus Path: ..\data\101_ObjectCategories;Test: None上面的代碼在參數(shù)中加入了size參數(shù),該參數(shù)表示將圖像的寬度和高度調(diào)整為指定尺寸,并且指定df_tfms可以自定義預(yù)處理方法。而且,通過屬性獲取的操作得到了具體的訓(xùn)練集和驗證集,這會得到一個LabelList對象,對其索引可以得到圖像和標簽,如img, label = train_ds[0],其中img就是一個Fastai的Image對象。
DataFrame(表格說明文件)
ImageDataBunch.from_folder(path:PathOrStr, # 數(shù)據(jù)集根目錄df:DataFrame, # 包含文件路徑和標簽的DataFramefolder:PathOrStr=None, # 相對于Path的數(shù)據(jù)存放的子目錄label_delim:str=None, # 標簽分隔符valid_pct:float=0.2, seed:int=None, fn_col:IntsOrStrs=0, # 文件名列的名稱或者索引號label_col:IntsOrStrs=1, # 標簽列的名稱或者索引號suffix:str='', # 添加的文件名后綴**kwargs:Any)通過DataFrame獲取整個數(shù)據(jù)集信息,大多數(shù)參數(shù)同上一節(jié)(下文不再說明)。
其針對的數(shù)據(jù)格式一般如下
path\data\description.csvCSV(表格說明文件)
ImageDataBunch.from_csv(path:PathOrStr, folder:PathOrStr=None, label_delim:str=None, csv_labels:PathOrStr='labels.csv', # 如果有單獨的標簽CSV文件可以這樣指定valid_pct:float=0.2, seed:int=None, fn_col:int=0, label_col:int=1, suffix:str='', delimiter:str=None, header:Union[int, str, NoneType]='infer', **kwargs:Any)直接從CSV文件中讀取數(shù)據(jù)集,省去讀取為DataFrame的步驟。
文件名
很多數(shù)據(jù)集存儲方式是不同的,有些數(shù)據(jù)集的標簽就存放在文件名中,下面定義的三個方法用于從文件名中提取出標簽。
ImageDataBunch.from_name_re(path:PathOrStr, # 文件所在路徑fnames:FilePathList, 文件名列表pat:str, # 匹配模式valid_pct:float=0.2, # 同上 **kwargs)從文件名中按照正則表達式提取標簽。
ImageDataBunch.from_name_func(path:PathOrStr, fnames:FilePathList, label_func:Callable, # 標簽提取函數(shù)valid_pct:float=0.2, seed:int=None, **kwargs)根據(jù)指定的標簽提取函數(shù)(自行定義)來從文件名中提取標簽。
ImageDataBunch.from_lists(path:PathOrStr, fnames:FilePathList, labels:StrList, # 標簽列表valid_pct:float=0.2, seed:int=None, item_cls:Callable=None, **kwargs)需要傳入一個和fnames同等大小的列表,依次為每個文件指定標簽。
數(shù)據(jù)增強
上一節(jié)介紹了構(gòu)建Fastai中數(shù)據(jù)集導(dǎo)入部分最為核心的DataBunch的幾種常見方法,它就是輸入模型的數(shù)據(jù)了。但是,在輸入模型數(shù)據(jù)之前我們往往會對圖像數(shù)據(jù)進行各種變換,稱為數(shù)據(jù)增強(Data Augmentation)。數(shù)據(jù)增強本質(zhì)上其實就是一種正則化,不過發(fā)生在數(shù)據(jù)層面而已。
Transform類
Fastai定義了大量的圖像變換函數(shù),通過實例化這些函數(shù)對象可以直接對圖像數(shù)據(jù)進行操作。但是這些基礎(chǔ)的變換函數(shù)都是以_開頭的函數(shù)如_brightness(x, change)表示改變圖像的亮度函數(shù),注意是個函數(shù)。但是實際進行數(shù)據(jù)增強的時候往往要增加一些隨機性(如隨機進行翻轉(zhuǎn)),所以Fastai提供了一個對這些變換進行封裝的類fastai.vision.image.Transform。該類提供共有的特性如變換函數(shù)優(yōu)先級等,這些封裝好的變換都在fastai.vision.transform模塊下,是不以_開頭的一系列對象(由Transform的子類實例化) ,注意是對象,同時,所有這類封裝都相比于原函數(shù)多了一個參數(shù)p,表示以概率p進行變換,如果p是區(qū)間則從區(qū)間內(nèi)隨機選擇作為概率。可以通過該對象的call方法對圖像數(shù)據(jù)進行處理,如使用brightness(x, change)。
圖像變換
下面描述具體的圖像變換手段,主要介紹的都是圖像變換對象,變換函數(shù)只是少了概率參數(shù)p而已。
brightness(x, change:uniform)對圖像進行亮度調(diào)整,按照change的數(shù)值進行,其值為1表示圖像為白色,為0表示黑色,為0.5表示無變化,可在0與1之間調(diào)整。
contrast(x, scale:log_uniform)對圖像進行對比度調(diào)整,sacle表示調(diào)整量,當其值為0會將圖片轉(zhuǎn)為灰度圖,其值為1不調(diào)整對比度,大于1會增大對比度。
crop(x, size, row_pct:uniform=0.5, col_pct:uniform=0.5)對圖像進行裁減,按照中心位置(row_pct, col_pct)把圖像裁減一個大小為size的patch,這兩個位置值以歸一化格式表示。
crop_pad(x, size, padding_mode='reflection', row_pct:uniform=0.5, col_pct:uniform=0.5)和crop類似,不過當裁減圖像大于原始圖像,會自動進行填充,填充方法為’zeros’, ‘border’或者’reflection’。
dihedral(x, k:partial(uniform_int, 0, 7))進行圖像翻轉(zhuǎn)并伴有一個k*90度的旋轉(zhuǎn)。
dihedral_affine(k:partial(uniform_int, 0, 7))效果同上,返回的類型不同,當目標是ImageBBox或者ImagePoints時使用。
flip_lr(x)水平鏡像翻轉(zhuǎn)圖片。
flip_affine()同上面的以_affine為結(jié)尾的含義。
jitter(c, magnitude:uniform)鄰域像素替換,鄰域范圍由magnitude參數(shù)指定。
pad(x, padding:int, mode='reflection')圖像填充,填充模式三種:zeros(0填充)、border(邊角填充)以及默認的reflection(反射填充)。
perspective_warp(c, magnitude:partial(uniform, size=8)=0, invert=False)透視變換,magnitude是8元組參數(shù),表示四個角歸一化坐標的變換幅度。
Image.resize(self, size:Union[int,TensorImageSize])引用自Torch的圖像縮放,size為整數(shù)(正方形)或者(3,H,W)格式。
rotate(degrees:uniform)圖像旋轉(zhuǎn),指定角度即可。
rgb_randomize(x, channel:int=None, thresh:float=0.3)隨機化RGB的某一通道,可以設(shè)置最大閾值。
skew(c, direction:uniform_int, magnitude:uniform=0, invert=False)圖像扭曲,可以指定方向和幅度。
squish(scale:uniform=1.0, row_pct:uniform=0.5, col_pct:uniform=0.5)圖像拉伸,scale<1為橫向拉伸,scale>1為縱向拉伸。
symmetric_warp(c, magnitude:partial(uniform, size=4)=0, invert=False)指定的透視變換。
tilt(c, direction:uniform_int, magnitude:uniform=0, invert=False)傾斜。
zoom(scale:uniform=1.0, row_pct:uniform=0.5, col_pct:uniform=0.5)等比例縮放。
cutout(x, n_holes:uniform_int=1, length:uniform_int=40)孔洞產(chǎn)生。
get_transforms()
該函數(shù)封裝在fastai.vision.transform模塊下,返回兩個變換列表(每個列表包含一系列變換),用于訓(xùn)練集和驗證集。
get_transforms(do_flip:bool=True, flip_vert:bool=False, max_rotate:float=10.0, max_zoom:float=1.1, max_lighting:float=0.2, max_warp:float=0.2, p_affine:float=0.75, p_lighting:float=0.75, xtra_tfms:Optional[Collection[Transform]]=None)該函數(shù)可以很方便地返回大量需要的變換用于數(shù)據(jù)集的載入,如使用下述代碼構(gòu)建用于隨機翻轉(zhuǎn)變換的數(shù)據(jù)集。
from fastai.vision import transform, open_image, data tfms = transform.get_transforms(do_flip=True) data = data.ImageDataBunch.from_folder("../data/101_ObjectCategories/", valid_pct=0.2, size=224, ds_tfms=tfms) train_ds, valid_ds = data.train_ds, data.valid_ds補充說明
本文依據(jù)最新的官方文檔講解了Fastai中數(shù)據(jù)讀入以及數(shù)據(jù)增強(文檔)的相關(guān)知識,具體代碼開源于我的Github,歡迎star或者fork。
總結(jié)
以上是生活随笔為你收集整理的Fastai-数据准备的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Keras-数据准备
- 下一篇: Fastai-学习器训练