深度學(xué)習(xí)模型需要數(shù)百 GB 的數(shù)據(jù)才能在看不見的樣本上很好地泛化。數(shù)據(jù)擴(kuò)充有助于增加數(shù)據(jù)集中示例的可變性。
傳統(tǒng)的數(shù)據(jù)擴(kuò)充方法可以追溯到統(tǒng)計(jì)學(xué)習(xí),當(dāng)時(shí)擴(kuò)充的選擇依賴于建立模型訓(xùn)練的工程師的領(lǐng)域知識(shí)、技能和直覺。
自動(dòng)增強(qiáng)出現(xiàn)了減少對(duì)手動(dòng)數(shù)據(jù)預(yù)處理的依賴。它結(jié)合了應(yīng)用自動(dòng)調(diào)整和根據(jù)概率分布隨機(jī)選擇增強(qiáng)的思想。
事實(shí)證明,使用 AutoAugment 和 RandAugment 等自動(dòng)數(shù)據(jù)增強(qiáng)方法可以通過使模型在訓(xùn)練中看到的樣本多樣化來提高模型的準(zhǔn)確性。自動(dòng)擴(kuò)充使數(shù)據(jù)預(yù)處理更加復(fù)雜,因?yàn)橐慌械拿總€(gè)樣本都可以用不同的隨機(jī)擴(kuò)充進(jìn)行處理。
在這篇文章中,我們介紹了如何使用 NVIDIA DALI 實(shí)現(xiàn)和使用 GPU 加速自動(dòng)增強(qiáng)來訓(xùn)練,然后使用條件執(zhí)行。
自動(dòng)數(shù)據(jù)擴(kuò)充方法
自動(dòng)增強(qiáng)是基于標(biāo)準(zhǔn)的圖像變換,如旋轉(zhuǎn)、剪切、模糊或亮度調(diào)整。大多數(shù)操作都接受一個(gè)稱為幅值的控制參數(shù)。幅度越大,操作對(duì)圖像的影響就越大。
傳統(tǒng)上,擴(kuò)充策略是由工程師手工編寫的固定操作序列。自動(dòng)增強(qiáng)策略與傳統(tǒng)策略的區(qū)別在于,增強(qiáng)和參數(shù)的選擇不是固定的,而是概率的。
AutoAugment采用強(qiáng)化學(xué)習(xí)從數(shù)據(jù)中學(xué)習(xí)最佳概率增強(qiáng)策略,將目標(biāo)模型的泛化視為獎(jiǎng)勵(lì)信號(hào)。使用 AutoAugment ,我們發(fā)現(xiàn)了圖像數(shù)據(jù)集的新策略,例如ImageNet,CIFAR-10和SVHN,超過了最先進(jìn)的精度。
AutoAugment 策略是一組增強(qiáng)對(duì)。每個(gè)增強(qiáng)都用應(yīng)用或跳過操作的幅度和概率進(jìn)行參數(shù)化。運(yùn)行策略時(shí),隨機(jī)選擇并應(yīng)用其中一對(duì),獨(dú)立于每個(gè)樣本。
學(xué)習(xí)策略意味著搜索最佳的增強(qiáng)對(duì)、它們的大小和概率。在策略搜索過程中,必須對(duì)目標(biāo)模型進(jìn)行多次再培訓(xùn)。這使得策略搜索的計(jì)算成本巨大。
為了避免計(jì)算成本高昂的搜索步驟,您可以重用在類似任務(wù)中找到的現(xiàn)有策略。或者,您可以使用其他自動(dòng)數(shù)據(jù)擴(kuò)充方法,這些方法旨在將搜索步驟保持在最低限度。
RandAugment將策略搜索步驟減少到只調(diào)整兩個(gè)數(shù)字:N和M.N是要在序列中應(yīng)用的隨機(jī)選擇的操作數(shù),以及M是所有操作共享的大小。盡管 RandAugment 很簡(jiǎn)單,但我們發(fā)現(xiàn),當(dāng)與相同的增強(qiáng)集一起使用時(shí),這種數(shù)據(jù)增強(qiáng)方法優(yōu)于 AutoAugment 的策略。
TrivialAgument通過移除這兩個(gè)超參數(shù)來構(gòu)建 RandAugment 。我們建議對(duì)每個(gè)樣本隨機(jī)選擇一個(gè)增量。 TrivialAugment 和 RandAugment 之間的區(qū)別在于,幅度不是固定的,而是隨機(jī)均勻采樣的。
結(jié)果表明,在訓(xùn)練過程中隨機(jī)采樣增強(qiáng)對(duì)于模型泛化可能比廣泛搜索仔細(xì)調(diào)整的策略更重要。
從開始1.24 版本發(fā)布, DALI 提供了AutoAugment,RandAugment和TrivialAugment在這篇文章中,我們向您展示了如何使用所有這些最先進(jìn)的實(shí)現(xiàn),并討論了 DALI 中新的條件執(zhí)行功能,這是它們實(shí)現(xiàn)的支柱。
DALI 和有條件執(zhí)行
現(xiàn)代 GPU 架構(gòu)顯著加快了深度學(xué)習(xí)模型訓(xùn)練。然而,為了實(shí)現(xiàn)最大的端到端性能,必須快速預(yù)處理模型消耗的數(shù)據(jù)批次,以避免 CPU 出現(xiàn)瓶頸。
NVIDIA DALI 通過異步執(zhí)行、預(yù)取、專用加載程序、一組豐富的面向批處理的擴(kuò)充以及與流行的 DL 框架(如PyTorch,TensorFlow,PaddlePaddle和MXNet.
為了創(chuàng)建一個(gè)數(shù)據(jù)處理管道,我們?cè)?Python 函數(shù)中組合了所需的操作,并用@pipeline_def出于性能原因,該函數(shù)只定義 DALI 的執(zhí)行計(jì)劃,然后由 DALI 執(zhí)行器異步運(yùn)行。
下面的代碼示例顯示了一個(gè)管道定義,該定義加載、解碼并將隨機(jī)噪聲增強(qiáng)應(yīng)用于圖像。
from nvidia.dali import pipeline_def, fn, types @pipeline_def(batch_size=8, num_threads=4, device_id=0) def pipeline(): encoded, _ = fn.readers.file(file_root=data_path, random_shuffle=True) image = fn.decoders.image(encoded, device="mixed") prob = fn.random.uniform(range=[0, 0.15]) distorted = fn.noise.salt_and_pepper(image, prob=prob) return distorted
管道的代碼是面向樣本的,而輸出是一批圖像。在指定運(yùn)算符時(shí)不需要處理批處理,因?yàn)?DALI 在內(nèi)部進(jìn)行管理。
然而,到目前為止,還不可能表達(dá)對(duì)一批樣本子集進(jìn)行操作的操作。這阻止了使用 DALI 實(shí)現(xiàn)自動(dòng)擴(kuò)增,因?yàn)樗鼮槊總€(gè)樣本隨機(jī)選擇不同的操作。
DALI 中引入的條件執(zhí)行使您能夠使用正則 Python 語義為批處理中的每個(gè)樣本選擇單獨(dú)的操作: if 語句。下面的代碼示例隨機(jī)應(yīng)用兩個(gè)增強(qiáng)中的一個(gè)。
@pipeline_def(batch_size=4, num_threads=4, device_id=0, enable_conditionals=True) def pipeline(): encoded, _ = fn.readers.file(file_root=data_path, random_shuffle=True) image = fn.decoders.image(encoded, device="mixed") change_stauration = fn.random.coin_flip(dtype=types.BOOL) if change_stauration: distorted = fn.saturation(image, saturation=2) else: edges = fn.laplacian(image, window_size=5) distorted = fn.cast_like(0.5 * image + 0.5 * edges, image) return distorted
我們?cè)黾恿艘恍颖镜娘柡投龋⒃谄渌麡颖局惺褂美绽顾阕?a target="_blank">檢測(cè)邊緣,基于fn.random.coin_flip后果 DALI 翻譯if-else語句轉(zhuǎn)換為執(zhí)行計(jì)劃,該執(zhí)行計(jì)劃根據(jù) if 條件將批處理拆分為兩個(gè)批處理。通過這種方式,部分批次分別并行處理,而樣本則屬于同一批次if-else分支仍然受益于批處理的 CUDA 內(nèi)核。
您可以很容易地?cái)U(kuò)展該示例,以使用從任意集合中隨機(jī)選擇的擴(kuò)充。在下面的代碼示例中,我們定義了三個(gè)擴(kuò)充,并實(shí)現(xiàn)了一個(gè)選擇運(yùn)算符,該運(yùn)算符根據(jù)隨機(jī)選擇的整數(shù)選擇正確的一個(gè)。
def edges(image): edges = fn.laplacian(image, window_size=5) return fn.cast_like(0.5 * image + 0.5 * edges, image) def rotation(image): angle = fn.random.uniform(range=[-45, 45]) return fn.rotate(image, angle=angle, fill_value=0) def salt_and_pepper(image): return fn.noise.salt_and_pepper(image, prob=0.15) def select(image, operation_idx, operations, i=0): if i >= len(operations): return image if operation_idx == i: return operations[i](image) return select(image, operation_idx, operations, i + 1)
在下面的代碼示例中,我們選擇了一個(gè)隨機(jī)整數(shù),并在 DALI 管道內(nèi)使用 select 運(yùn)算符運(yùn)行相應(yīng)的操作。
@pipeline_def(batch_size=6, num_threads=4, device_id=0, enable_conditionals=True) def pipeline(): encoded, _ = fn.readers.file(file_root=data_path, random_shuffle=True) image = fn.decoders.image(encoded, device="mixed") operations = [edges, rotation, salt_and_pepper] operation_idx = fn.random.uniform(values=list(range(len(operations)))) distorted = select(image, operation_idx, operations) return distorted
因此,我們得到了一批圖像,其中每個(gè)圖像都通過一個(gè)隨機(jī)選擇的操作進(jìn)行變換:邊緣檢測(cè)、旋轉(zhuǎn)和椒鹽噪聲失真。
DALI 自動(dòng)增強(qiáng)
通過按樣本選擇運(yùn)算符,您可以實(shí)現(xiàn)自動(dòng)擴(kuò)充。為了便于使用, NVIDIA 推出了auto_augDALI 中的模塊,具有流行的自動(dòng)增強(qiáng)的現(xiàn)成實(shí)現(xiàn):auto_aug.auto_augment,auto_aug.rand_augment和auto_aug.trivial_augment它們可以開箱即用,也可以通過調(diào)整增強(qiáng)幅度或構(gòu)建 DALI 基元的用戶定義的增強(qiáng)來定制。
這個(gè)auto_aug.augmentationsDALI 中的模塊提供由自動(dòng)增強(qiáng)程序共享的默認(rèn)操作集:
auto_contrast
brightness
color
contrast
equalize
invert
posterize
rotate
sharpness
shear_x
shear_y
solarize
solarize_add
translate_x
translate_y
下面的代碼示例顯示了如何運(yùn)行 RandAugment 。
import nvidia.dali.auto_aug.rand_augment as ra @pipeline_def(batch_size=6, num_threads=4, device_id=0, enable_conditionals=True) def pipeline(): encoded, _ = fn.readers.file(file_root=data_path, random_shuffle=True) shape = fn.peek_image_shape(encoded) image = fn.decoders.image(encoded, device="mixed") distorted = ra.rand_augment(image, n=3, m=15, shape=shape, fill_value=0) return distorted
這個(gè)rand_augment操作員接受解碼后的圖像、圖像的形狀、要在序列中應(yīng)用的隨機(jī)增強(qiáng)的數(shù)量 (n=3) 以及這些行動(dòng)應(yīng)該具有的規(guī)模 (m=15,在可定制的0, 30范圍)。
在某些應(yīng)用程序中,您可能必須限制已使用的擴(kuò)充集。例如,如果數(shù)據(jù)集由數(shù)字圖片組成,則將數(shù)字“ 9 ”旋轉(zhuǎn) 180 度將使相關(guān)標(biāo)簽無效。運(yùn)行以下代碼示例rand_augment具有有限的增強(qiáng)集。
from nvidia.dali.auto_aug import augmentations as a augmentations = [ a.shear_x.augmentation((0, 0.3), randomly_negate=True), a.shear_y.augmentation((0, 0.3), randomly_negate=True), a.translate_x.augmentation((0, 0.45), randomly_negate=True), a.translate_y.augmentation((0, 0.45), randomly_negate=True), a.rotate.augmentation((0, 30), randomly_negate=True), ]
每個(gè)增強(qiáng)都可以通過幅度如何映射到變換強(qiáng)度來參數(shù)化。例如a.rotate.augmentation((0, 30))指定要將圖像旋轉(zhuǎn)不大于 30 度的角度。randomly_negate=True指定角度應(yīng)隨機(jī)取反,以便隨機(jī)順時(shí)針或逆時(shí)針旋轉(zhuǎn)圖像。
下面的代碼示例以類似 RandAugment 的方式應(yīng)用增強(qiáng)。
@pipeline_def(batch_size=8, num_threads=4, device_id=0, enable_conditionals=True) def pipeline(): encoded, _ = fn.readers.file(file_root=data_path, random_shuffle=True) shape = fn.peek_image_shape(encoded) image = fn.decoders.image(encoded, device="mixed") distorted = ra.apply_rand_augment(augmentations, image, n=3, m=15, shape=shape, fill_value=0) return distorted
前兩個(gè)管道定義之間的唯一區(qū)別是使用了更通用的apply_rand_augment接受附加參數(shù)的運(yùn)算符,即擴(kuò)充列表。
接下來,將自定義擴(kuò)充添加到集合中。使用cutout作為一個(gè)例子。它使用 DALI 用一個(gè)歸零的矩形隨機(jī)覆蓋圖像的一部分fn.erase作用包fn.erase與@augmentation描述如何將幅度映射到cutout矩形。cutout_size是從 0 . 01 到 0 . 4 范圍的大小的元組,而不是普通大小。
from nvidia.dali.auto_aug.core import augmentation def cutout_shape(size): # returns the shape of the rectangle return [size, size] @augmentation(mag_range=(0.01, 0.4), mag_to_param=cutout_shape) def cutout(image, cutout_size, fill_value=None): anchor = fn.random.uniform(range=[0, 1], shape=(2,)) return fn.erase(image, anchor=anchor, shape=cutout_size, normalized=True, centered_anchor=True, fill_value=fill_value) augmentations += [cutout]
對(duì)于更改,運(yùn)行一組自定義的幾何增強(qiáng),如TrivialAugment,即具有隨機(jī)幅度。對(duì)代碼的更改是最小的;您導(dǎo)入并調(diào)用trivial_augment而不是rand_augment來自aut_aug單元
import nvidia.dali.auto_aug.trivial_augment as ta @pipeline_def(batch_size=8, num_threads=4, device_id=0, enable_conditionals=True) def pipeline(): encoded, _ = fn.readers.file(file_root=data_path, random_shuffle=True) shape = fn.peek_image_shape(encoded) image = fn.decoders.image(encoded, device="mixed") distorted = ta.apply_trivial_augment(augmentations, image, shape=shape, fill_value=0) return distorted
DALI 的自動(dòng)增強(qiáng)性能
現(xiàn)在,插上 DALI 和AutoAugment進(jìn)入模型訓(xùn)練并比較吞吐量,使用EfficientNet-b0例如,改編自NIVDIA Deep Learning Examples.AutoAugment是 EfficientNet 系列模型預(yù)處理階段的標(biāo)準(zhǔn)部分。
在鏈接的示例中AutoAugment策略使用 PyTorch 數(shù)據(jù)加載器實(shí)現(xiàn),并在 CPU 上運(yùn)行,而模型訓(xùn)練在 GPU 上進(jìn)行。當(dāng) DALI 管道替換在 CPU 上運(yùn)行的數(shù)據(jù)加載器時(shí),吞吐量會(huì)增加。 EfficientNet 加 DALI 的源代碼可在DALI examples.
該模型在自動(dòng)混合精度模式( AMP )下運(yùn)行,批量大小: DGX-1 V100 為 128 , DGX A100 為 256 。
我們用兩種硬件設(shè)置進(jìn)行了實(shí)驗(yàn): DGX-1 V100 16 GB 和 DGX A100 。我們測(cè)量了每秒處理的圖像數(shù)量(越多越好)。在這兩種情況下,速度都有所提高: DGX-1 V100 的速度提高了 33% , DGX A100 的速度增加了 12% 。
圖中虛線所示的理論吞吐量是通過單獨(dú)改進(jìn)數(shù)據(jù)預(yù)處理可以預(yù)期的訓(xùn)練速度的上限。為了測(cè)量理論極限,我們使用在每次迭代中重復(fù)的一批合成數(shù)據(jù)而不是真實(shí)數(shù)據(jù)進(jìn)行訓(xùn)練。這讓我們看到了在不需要預(yù)處理的情況下,模型處理批次的速度有多快。
合成情況和 CPU 數(shù)據(jù)加載器情況之間的顯著性能差距表明存在預(yù)處理瓶頸。為了驗(yàn)證這一假設(shè),請(qǐng)查看訓(xùn)練期間 GPU 的使用情況。
圖 7 。在 EfficientNet-b0 培訓(xùn)期間, DGX-1V 16GB 的 GPU 利用率增加
(批量大小 128 ,具有 DALI 數(shù)據(jù)預(yù)處理的自動(dòng)混合精度模式)
圖 8 。在 EfficientNet-b0 培訓(xùn)期間, DGX-A100 的 GPU 利用率增加
(批量大小 256 ,自動(dòng)混合精度模式,帶 DALI 數(shù)據(jù)預(yù)處理)
這些圖顯示了在給定的 GPU 利用率下我們花費(fèi)了多少時(shí)間。您可以看到,當(dāng)使用在 CPU 上運(yùn)行的數(shù)據(jù)加載器對(duì)數(shù)據(jù)進(jìn)行預(yù)處理時(shí), GPU 的利用率會(huì)反復(fù)下降。值得注意的是,在大約 5% 的時(shí)間里,利用率下降到 10% 以下。這表明訓(xùn)練定期停滯,等待下一批數(shù)據(jù)從數(shù)據(jù)加載程序到達(dá)。
如果您將加載和自動(dòng)增強(qiáng)步驟移動(dòng)到帶有 DALI 的 GPU0, 10條消失,并且整體 GPU 利用率增加。圖 6 中顯示的使用 DALI 的訓(xùn)練吞吐量的增加證實(shí)了我們成功地克服了之前的預(yù)處理瓶頸。
-
NVIDIA
+關(guān)注
關(guān)注
14文章
5076瀏覽量
103719 -
人工智能
+關(guān)注
關(guān)注
1796文章
47666瀏覽量
240278 -
深度學(xué)習(xí)
+關(guān)注
關(guān)注
73文章
5513瀏覽量
121546
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論