最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

MegEngine Python 層模塊串講(上)

2023-07-21 18:26 作者:曠視天元MegEngine  | 我要投稿

在前面的文章中,我們簡單介紹了在?MegEngine imperative?中的各模塊以及它們的作用。對于新用戶而言可能不太了解各個模塊的使用方法,對于模塊的結(jié)構(gòu)和原理也是一頭霧水。Python?作為現(xiàn)在深度學習領域的主流編程語言,其相關(guān)的模塊自然也是深度學習框架的重中之重。

模塊串講將對?MegEngine?的?Python?層相關(guān)模塊分別進行更加深入的介紹,會涉及到一些原理的解釋和代碼解讀。Python?層模塊串講共分為上、中、下三個部分,本文介紹?Python?層的?data?模塊。讀者將通過本文了解到要構(gòu)建數(shù)據(jù)?pipeline?所需要的對象,以及如何高效地構(gòu)建?pipeline。

構(gòu)建數(shù)據(jù)處理 pipeline —— data 模塊

神經(jīng)網(wǎng)絡需要數(shù)據(jù)才可以訓練,數(shù)據(jù)源文件可能是各種格式,讀取數(shù)據(jù)需要定義采樣規(guī)則、數(shù)據(jù)變換規(guī)則、數(shù)據(jù)合并策略等,這些和數(shù)據(jù)相關(guān)的模塊都封裝在?data?下。

在?MegEngine?中訓練模型讀取數(shù)據(jù)的?pipeline?一般是:

  1. 創(chuàng)建一個?Dataset?對象;

  2. 按照訓練場景的需求可能需要對數(shù)據(jù)做一些變換或合并的處理,這里可能需要創(chuàng)建?Sampler、Transform、Collator?等對象來完成相應操作;

  3. 創(chuàng)建一個?DataLoader?對象;

  4. 將數(shù)據(jù)分批加載到?DataLoader?里,迭代?DataLoader?對象進行訓練。

下面我們看一下這幾個對象的實現(xiàn)。

Dataset

在?MegEngine?中,數(shù)據(jù)集是一個可迭代的對象,所有的?Dataset?對象都繼承自?class Dataset,都需要實現(xiàn)自己的?__getitem__()?方法和?__len__()?方法,這兩個方法分別是用來獲取給定索引的對應的數(shù)據(jù)樣本和返回數(shù)據(jù)集的大小。

根據(jù)對數(shù)據(jù)集訪問方式的區(qū)別,MegEngine?中的數(shù)據(jù)集類型主要分為兩種:ArrayDataset?和?StreamDataset,前者支持隨機訪問數(shù)據(jù)樣本,而后者只可以順序訪問。二者的主要區(qū)別見下表:

Dataset

Dataset?支持對數(shù)據(jù)集的隨機訪問,訪問類型是?Map-style?的,也就是可以從索引映射到數(shù)據(jù)樣本,使用時需要實現(xiàn)?__getitem__()?方法和?__len__()?方法。

下面是一個使用?Dataset?生成一個由?0?到?5?的數(shù)組成的數(shù)據(jù)集的例子:

使用起來如下:

可以發(fā)現(xiàn)?Dataset?最大的特點就是可以根據(jù)給定索引隨機訪問數(shù)據(jù)集中對應下標的數(shù)據(jù)。

ArrayDataset

對于?Numpy ndarray?類型的數(shù)據(jù),MegEngine?中對?Dataset?進一步封裝實現(xiàn)了?ArrayDataset,使用?ArrayDataset?無需實現(xiàn)?__getitem__()?方法和?__len__()?方法。

下面的例子隨機生成了一個具有?100?個樣本、每張樣本為?32 × 32?像素的?RGB?圖片的數(shù)據(jù)集:

由于需要支持隨機訪問,因此對于支持順序訪問的?Dataset?需要將索引等信息加載進內(nèi)存,如果數(shù)據(jù)集規(guī)模較大導致內(nèi)存無法存放從而發(fā)生?OOM(Out Of Memory),我們需要考慮使用流式數(shù)據(jù)?StreamDataset。

StreamDataset

當數(shù)據(jù)集規(guī)模較大時,使用流失數(shù)據(jù)迭代訪問數(shù)據(jù)對象是比較主流的做法。從類的定義可以看到:由于無法根據(jù)索引獲取數(shù)據(jù),因此?StreamDataset?無需實現(xiàn)?__getitem__()?方法和?__len__()?方法,但是需要實現(xiàn)一個?__iter__()?方法定義流式獲取數(shù)據(jù)的規(guī)則:

StreamDataset?適用的場景主要是:

  • 隨機讀取成本過高,或者數(shù)據(jù)規(guī)模太大,無法支持;

  • 必須根據(jù)流數(shù)據(jù)才能判斷當前批是否已經(jīng)完整。

可以使用流數(shù)據(jù)返回從數(shù)據(jù)庫、遠程服務器甚至實時生成的日志中讀取的數(shù)據(jù)流。

下面的例子展示了如何生成一個由?0?到?5?這五個數(shù)組成的數(shù)據(jù)集:

Sampler

有了?DataSet?之后,DataLoader?可以從數(shù)據(jù)集加載數(shù)據(jù)到內(nèi)存,但是對每批數(shù)據(jù)有時候需要規(guī)定規(guī)模的大小,還有定義抽樣規(guī)則等需求,使用?Sampler?可以對每批數(shù)據(jù)的抽樣規(guī)則進行自定義。

準確來說,抽樣器的職責是決定數(shù)據(jù)的獲取順序,方便為?DataLoader?提供一個可供迭代的多批數(shù)據(jù)的索引:

在 MegEngine 中,Sampler?是所有抽樣器的抽象基類,在大部分情況下用戶無需對抽樣器進行自定義實現(xiàn), 因為在 MegEngine 中已經(jīng)實現(xiàn)了常見的各種抽樣器,比如上面示例代碼中的?RandomSampler?抽樣器。

下面介紹?MegEngine?中幾種常見的?Sampler。

SequentialSampler

SequentialSampler(https://github.com/MegEngine/MegEngine/blob/master/imperative/python/megengine/data/sampler.py#L178)?也叫?MapSampler, 顧名思義就是對數(shù)據(jù)集進行順序抽樣的抽樣器。

對一個含有?100?個數(shù)據(jù)樣本的數(shù)據(jù)集,batch_size?為?10,可以得到?10?批順序索引:

默認情況下?batch_size?為?1,表示逐個遍歷數(shù)據(jù)集中的樣本,drop_last?為?False

RandomSampler

RandomSampler?用來對數(shù)據(jù)集進行無放回隨機抽樣(也叫簡單隨機抽樣)。

直接看例子:

ReplacementSampler

ReplacementSampler?是有放回隨機抽樣,也就是可能抽樣到之前已經(jīng)抽樣過的數(shù)據(jù)。

使用方法和無放回隨機抽樣類似:

Infinite

通常數(shù)據(jù)集在給定?batch_size?的情況下,只能劃分為有限個?batch。 這意味著抽樣所能得到的數(shù)據(jù)批數(shù)是有限的,想要重復利用數(shù)據(jù), 最常見的做法是循環(huán)多個周期?epochs?來反復遍歷數(shù)據(jù)集:

、但在一些情況下,我們希望能夠直接從數(shù)據(jù)集中無限進行抽樣, 因此MegEngine提供了?Infinite?包裝類用來進行無限抽樣:

以上就是常見的?Sampler?的使用方法,有時候?qū)τ跀?shù)據(jù)集中的數(shù)據(jù)還需要做一些變換以滿足業(yè)務需要,這就是我們接下來要說的?transform。

Transform

在深度學習中對數(shù)據(jù)進行變換(Transformation)以滿足業(yè)務需求和增強模型性能是很常見的操作。

在?megengine.data.transform?中提供的各種數(shù)據(jù)變換都是基于?Transform?抽象類實現(xiàn)的,其中:

  • apply?抽象方法可用于單個的數(shù)據(jù)樣本, 需要在子類中實現(xiàn);

  • 各種變換操作可以通過?Compose?進行組合,這樣使用起來更加方便。

我們能夠很方便地在?DataLoader?加載數(shù)據(jù)時進行相應地變換操作。例如:

上面就是將兩個?transform?操作?Resize()?和?ToMode()?組合起來對數(shù)據(jù)進行變換。

下面舉個例子如何實現(xiàn)自己的?Transform

上面這個?Transform?實現(xiàn)了自己的?apply()?方法,對數(shù)據(jù)集中的所有樣本做了一個?+1?操作。

可以使用?Compose?對數(shù)據(jù)變換進行組合:

最終,我們的各種Transform實現(xiàn)應當被應用于DataLoader

實際使用時對數(shù)據(jù)做的操作往往比上面的例子要復雜許多,MegEngine?在?VisionTransform?中已經(jīng)實現(xiàn)了很多轉(zhuǎn)換方法供用戶使用。用戶也可以根據(jù)需要實現(xiàn)自己的數(shù)據(jù)變換方法。

當我們從?DataLoader?中獲取批數(shù)據(jù)時,如果定義了?Transform, 則會在每次加載完樣本后立即對其進行變換。

數(shù)據(jù)變換操作也是有計算開銷的,且該流程通常在?CPU?設備上進行,以及有些操作會調(diào)用類似?OpenCV?的庫。 如果我們對每個樣本進行多次加載(比如訓練多個周期),那么變換操作也會被執(zhí)行多次,這可能會帶來額外的開銷。 因此在有些時候,我們會選擇將預處理操作在更早的流程中進行,即直接對原始數(shù)據(jù)先進行一次預處理操作, 這樣在?DataLoader?中獲取的輸入便已經(jīng)是經(jīng)過預處理的數(shù)據(jù)了,這樣可以盡可能地減少?Transform?操作。

用戶應當考慮到,原始數(shù)據(jù)相關(guān)的?I/O?和處理也有可能成為模型訓練整體流程中的瓶頸。

Collator

在使用?DataLoader?獲取批數(shù)據(jù)的整個流程中,?Collator?負責合并樣本,最終得到批數(shù)據(jù)。

Collator?僅適用于?Map-style?的數(shù)據(jù)集,因為?Iterable-style?數(shù)據(jù)集的批數(shù)據(jù)必然是逐個合并的。

經(jīng)過?DataSet?和?Transform?的處理后,?Collator?通常會接收到一個列表:

  • 如果你的?Dataset?子類的?__getitem__?方法返回的是單個元素,則?Collator?得到一個普通列表;

  • 如果你的?Dataset?子類的?__getitem__?方法返回的是一個元組,則?Collator?得到一個元組列表。

MegEngine?中使用?Collator?作為默認實現(xiàn),通過調(diào)用?apply?方法來將列表數(shù)據(jù)合并成批數(shù)據(jù):

默認的?Collator?支持?NumPy ndarray,?Numbers,?Unicode strings,?bytes,?dicts?或?lists?數(shù)據(jù)類型。 要求輸入必須包含至少一種上述數(shù)據(jù)類型,否則用戶需要使用自己定義的?Collator

Collator?的作用是合并數(shù)據(jù),比如每個數(shù)據(jù)樣本是?shape?為?(C, H, W)?的圖片,如果我們在?Sampler?中指定了?batch_size?為?N。那么?Collator?就會將獲得的樣本列表合并成一個?shape?為?(N, C, H, W)?的批樣本結(jié)構(gòu)。

我們可以模擬得到這樣一個?image_list?數(shù)據(jù),并借助?Collator?得到?batch_image


DataLoader

前面介紹的?Dataset、SamplerTransform、Collator?等對象都是為了更靈活地配置?DataLoader?對象的。

當單進程運行?DataLoader?時(設置?num_workers=0),每當我們向?DataLoader?索要一批數(shù)據(jù)時,DataLoader?將從 Sampler 獲得下一批數(shù)據(jù)的索引, 根據(jù)?Dataset?提供的?__getitem__()?方法將對應的數(shù)據(jù)逐個加載到內(nèi)存, 加載進來的數(shù)據(jù)可以通過指定的?Transform?做一些處理,再通過?Collator?將單獨的數(shù)據(jù)組織成批數(shù)據(jù)。

DataLoader?也支持多進程加載以提升數(shù)據(jù)加載處理速度(提高?num_workers?數(shù)量)。 一般?worker?數(shù)量越多,數(shù)據(jù)加載處理的速度會越快。不過如果?worker?數(shù)過多, 并大大超出了系統(tǒng)中 cpu 的數(shù)量,這些子進程可能會存在競爭?cpu?資源的情況,反而導致效率的降低。

一般來說,我們建議根據(jù)系統(tǒng)中?cpu?的數(shù)量設置?worker?的值。 比如在一臺?64 cpu,?8 gpu?的機器上,預期中每個?gpu?會對應?8?個?cpu, 那么我們在使用時對應的把?worker?數(shù)設置在?8?左右就是個不錯的選擇。

下面以一個加載圖像分類數(shù)據(jù)的流程來舉例說明如何創(chuàng)建一個加載數(shù)據(jù)的?pipeline

1、假設圖像數(shù)據(jù)按照一定的規(guī)則放置于同一目錄下(通常數(shù)據(jù)集主頁會對目錄組織和文件命名規(guī)則進行介紹)。 要創(chuàng)建對應的數(shù)據(jù)加載器,首先需要一個繼承自?Dataset?的類。 我們可以創(chuàng)建一個自定義的數(shù)據(jù)集:



要獲取示例圖像,可以創(chuàng)建一個數(shù)據(jù)集對象,并將示例索引傳遞給__getitem__()方法, 然后將返回圖像數(shù)組和對應的標簽,例如:

2、現(xiàn)在我們已經(jīng)預先創(chuàng)建了能夠返回一個樣本及其標簽的類CustomImageDataset, 但僅依賴Dataset本身還無法實現(xiàn)自動分批、亂序、并行等功能; 我們必須接著創(chuàng)建DataLoader, 它通過其它的參數(shù)配置項圍繞這個類“包裝”, 可以按照我們的要求從數(shù)據(jù)集類中返回整批樣本。

3、現(xiàn)在可以加載數(shù)據(jù)并進行訓練了:

更多 MegEngine 信息獲取,您可以:查看文檔:https://www.megengine.org.cn/doc/stable/zh/

GitHub 項目: https://github.com/MegEngine

加入 MegEngine 用戶交流 QQ 群:1029741705

歡迎參與 MegEngine 社區(qū)貢獻,成為?Awesome MegEngineerhttps://www.megengine.org.cn/community-AMGE,榮譽證書、定制禮品享不停。

MegEngine Python 層模塊串講(上)的評論 (共 條)

分享到微博請遵守國家法律
兰坪| 镇巴县| 松潘县| 孟州市| 赤壁市| 潍坊市| 长兴县| 西峡县| 锡林浩特市| 大渡口区| 绍兴市| 周口市| 宁强县| 灵璧县| 新昌县| 昂仁县| 西乌珠穆沁旗| 普兰店市| 崇明县| 安多县| 海口市| 松江区| 兴山县| 龙海市| 夏邑县| 平罗县| 湛江市| 湘西| 临猗县| 平罗县| 邹城市| 巴南区| 澜沧| 衡水市| 黑山县| 娄底市| 治县。| 焉耆| 英山县| 开远市| 镇宁|