中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

佛山營銷網(wǎng)站建設(shè)seo快速工具

佛山營銷網(wǎng)站建設(shè),seo快速工具,臨海市城鄉(xiāng)建設(shè)規(guī)劃局網(wǎng)站,大學網(wǎng)站 作風建設(shè)專題Contents混合精度訓練 (Mixed Precision Training)單精度浮點數(shù) (FP32) 和半精度浮點數(shù) (FP16)為什么要用 FP16為什么只用 FP16 會有問題解決方案損失縮放 (Loss Scaling)FP32 權(quán)重備份黑名單Tensor CoreNVIDIA apex 庫代碼解讀opt-level (o1, o2, o3, o4)apex 的 o1 實現(xiàn)apex …

Contents

  • 混合精度訓練 (Mixed Precision Training)
    • 單精度浮點數(shù) (FP32) 和半精度浮點數(shù) (FP16)
    • 為什么要用 FP16
    • 為什么只用 FP16 會有問題
    • 解決方案
      • 損失縮放 (Loss Scaling)
      • FP32 權(quán)重備份
      • 黑名單
      • Tensor Core
    • NVIDIA apex 庫代碼解讀
      • opt-level (o1, o2, o3, o4)
      • apex 的 o1 實現(xiàn)
      • apex 的 o2 實現(xiàn)
  • 在 PyTorch 中使用混合精度訓練
    • Automatic Mixed Precision (AMP)
      • Typical Mixed Precision Training
      • Saving/Resuming
      • Working with Unscaled Gradients (Gradient Clipping)
      • Working with Scaled Gradients
        • Gradient accumulation
        • Gradient penalty
      • Working with Multiple GPUs
  • 其他注意事項
  • References

PyTorch 1.6 之前,大家都是用 NVIDIA 的 apex 庫來實現(xiàn) AMP 訓練。1.6 版本之后,PyTorch 出廠自帶 AMP,僅需幾行代碼,就能讓顯存占用減半,訓練速度加倍

混合精度訓練 (Mixed Precision Training)

單精度浮點數(shù) (FP32) 和半精度浮點數(shù) (FP16)

  • PyTorch 默認使用單精度浮點數(shù) (FP32) 來進行網(wǎng)絡(luò)模型的計算和權(quán)重存儲,表示范圍為 [?3e38,?1e?38]∪[1e?38,3e38]\left[-3 e^{38},-1 e^{-38}\right] \cup\left[1 e^{-38}, 3 e^{38}\right][?3e38,?1e?38][1e?38,3e38]. 而半精度浮點數(shù) (FP16) 表示范圍只有 [?6.5e4,?5.9e?8]∪[5.9e?8,6.5e4]\left[-6.5 e^{4},-5.9 e^{-8}\right] \cup\left[5.9 e^{-8}, 6.5 e^{4}\right][?6.5e4,?5.9e?8][5.9e?8,6.5e4],可以看到 FP32 能夠表示的范圍要比 FP16 大的多得多
    在這里插入圖片描述其中sign 位表示正負,exponent 位表示指數(shù),fraction 位表示分數(shù)
  • 此外浮點數(shù)還存在舍入誤差當兩個數(shù)字相差太大時,相加是無效的。例如 2?3+2?142^{-3}+2^{-14}2?3+2?14 在 FP32 中就不會有問題,但在 FP16 中,由于 FP16 表示的固定間隔為 2?132^{-13}2?13,因此 2?142^{-14}2?14 加了跟沒加一樣
# FP32
>>> torch.tensor(2**-3) + torch.tensor(2**-14)
tensor(0.1251)# FP16
>>> torch.tensor(2**-3).half() + torch.tensor(2**-14).half()
tensor(0.1250, dtype=torch.float16)

在這里插入圖片描述


對于 float16

  • 如果 Exponent 位全部為 0:
    • 如果 fraction 位全部為 0,則表示數(shù)字 0
    • 如果 fraction 位不為 0,則表示一個非常小的數(shù)字 (subnormal numbers),其計算方式為 (?1)signbit×2?14×(0+fraction1024)(-1)^{signbit}\times2^{-14}\times(0+\frac{fraction}{1024})(?1)signbit×2?14×(0+1024fraction?)
  • 如果 Exponent 位全部為 1:
    • 如果 fraction 位全部為 0,則表示 ±inf±inf±inf
    • 如果 fraction 位不為0,則表示 NAN
  • Exponent 位的其他情況:(?1)signbit×(exponent×2?15)×(1+fraction1024)(-1)^{signbit}\times(exponent\times2^{-15})\times(1+\frac{fraction}{1024})(?1)signbit×(exponent×2?15)×(1+1024fraction?)

在這里插入圖片描述

為什么要用 FP16

  • 如果我們在訓練過程中將 FP32 替代為 FP16,有以下兩個好處:(1) 減少顯存占用: FP16 的顯存占用只有 FP32 的一半,這使得我們可以用更大的 batch size;(2) 加速訓練: 使用 FP16,模型的訓練速度幾乎可以提升 1 倍

為什么只用 FP16 會有問題

如果我們簡單地把模型權(quán)重和輸入從 FP32 轉(zhuǎn)化成 FP16,雖然速度可以翻倍,但是模型的精度會被嚴重影響。原因如下:

  • 上/下溢出: FP16 的表示范圍不大,超過 6.5e46.5 e^{4}6.5e4 的數(shù)字會上溢出變成 inf,小于
    5.9e?85.9 e^{-8}5.9e?8 的數(shù)字會下溢出變成 0。下溢出更加常見,因為在網(wǎng)絡(luò)訓練的后期,模型的梯度往往很小,甚至會小于 FP16 的下限,此時梯度值就會變成 0,模型參數(shù)無法更新。下圖為 SSD 網(wǎng)絡(luò)在訓練過程中的梯度統(tǒng)計,有 67% 的值下溢出變成 0
    在這里插入圖片描述
  • 舍入誤差: 就算梯度不會上/下溢出,如果梯度值和模型的參數(shù)值相差太遠,也會發(fā)生舍入誤差的問題。假設(shè)模型參數(shù) w=2?3w=2^{-3}w=2?3,學習率 η=2?2\eta=2^{-2}η=2?2,梯度 g=2?12g=2^{-12}g=2?12,則 w′=w+η×g=2?3+2?2×2?12=2?3w'=w+\eta\times g=2^{-3}+2^{-2}\times 2^{-12}=2^{-3}w=w+η×g=2?3+2?2×2?12=2?3

解決方案

損失縮放 (Loss Scaling)

  • 為了解決下溢出的問題,論文中對計算出來的 loss 值進行縮放 (scale),由于鏈式法則的存在,對 loss 的縮放會作用在每個梯度上。縮放后的梯度,就會平移到 FP16 的有效范圍內(nèi)。這樣就可以用 FP16 存儲梯度而又不會溢出了。此外,在進行更新之前,需要先將縮放后的梯度轉(zhuǎn)化為 FP32,再將梯度反縮放 (unscale) 回去以便進行參數(shù)的梯度下降 (注意這里一定要先轉(zhuǎn)成 FP32,不然 unscale 的時候還是會下溢出)
  • 縮放因子 (loss_scale) 一般都是框架自動確定的,只要沒有發(fā)生 inf 或者 nan,loss_scale 越大越好。因為隨著訓練的進行,網(wǎng)絡(luò)的梯度會越來越小,更大的 loss_scale 可以更加充分地利用 FP16 的表示范圍

FP32 權(quán)重備份

  • 為了實現(xiàn) FP16 的訓練,我們需要把模型權(quán)重和輸入數(shù)據(jù)都轉(zhuǎn)成 FP16,反向傳播的時候就會得到 FP16 的梯度。如果此時直接進行更新,因為梯度 ×\times× 學習率的值往往較小,和模型權(quán)重的差距會很大,可能會出現(xiàn)舍入誤差的問題
  • 解決思路是: 將模型權(quán)重、激活值、梯度等數(shù)據(jù)用 FP16 來存儲,同時維護一份 FP32 的模型權(quán)重副本用于更新。在反向傳播得到 FP16 的梯度以后,將其轉(zhuǎn)化成 FP32 并 unscale,最后更新 FP32 的模型權(quán)重。因為整個更新過程是在 FP32 的環(huán)境中進行的,所以不會出現(xiàn)舍入誤差

黑名單

  • 對于那些在 FP16 環(huán)境中運行不穩(wěn)定的模塊,我們會將其添加到黑名單中,強制它在 FP32 的精度下運行。比如需要計算 batch 均值的 BN 層就應(yīng)該在 FP32 下運行,否則會發(fā)生舍入誤差。還有一些函數(shù)對于算法精度要求很高,比如 torch.acos(),也應(yīng)該在 FP32 下運行
  • 如何保證黑名單模塊在 FP32 環(huán)境中運行: 以 BN 層為例,將其權(quán)重轉(zhuǎn)為 FP32,并且將輸入從 FP16 轉(zhuǎn)成 FP32,這樣就可以保證整個模塊是在 FP32 下運行的

Tensor Core

  • Tensor Core 可以讓 FP16 做矩陣相乘,然后把結(jié)果累加到 FP32 的矩陣中。這樣既可以享受 FP16 高速的矩陣乘法,又可以利用 FP32 來消除舍入誤差
    在這里插入圖片描述

NVIDIA apex 庫代碼解讀

opt-level (o1, o2, o3, o4)

在這里插入圖片描述

  • 首先介紹下 apex 提供的幾種 opt-level: o1, o2, o3, o4
  • o0純 FP32,用來當精度的基準。o3純 FP16,用來當速度的基準
  • 重點講 o1 和 o2 。我們之前講的 AMP 策略其實就是 o2: 除了 BN 層的權(quán)重和輸入使用 FP32,模型的其余權(quán)重和輸入都會轉(zhuǎn)化為 FP16。此外還會創(chuàng)建一個 FP32 的權(quán)重副本來執(zhí)行更新操作
  • 和 o2 不同, o1 不再需要 FP32 權(quán)重備份,因為 o1 的模型一直都是 FP32。 可能有些讀者會好奇,既然模型參數(shù)是 FP32,那怎么在訓練過程中使用 FP16 呢?答案是 o1 建立了一個 PyTorch 函數(shù)的黑白名單,對于白名單上的函數(shù),強制要求其用 FP16,即會將函數(shù)的參數(shù)先轉(zhuǎn)化為 FP16,再執(zhí)行函數(shù)本身。黑名單則強制要求 FP32。以 nn.Linear 為例, 這個模塊有兩個權(quán)重參數(shù) weight 和 bias,輸入為 input,前向傳播就是調(diào)用了 torch.nn.functional.linear(input, weight, bias)。 o1 模式會將 input、weight、bias 先轉(zhuǎn)化為 FP16 格式 input_fp16、weight_fp16、bias_fp16,再調(diào)用函數(shù) torch.nn.functional.linear(input_fp16, weight_fp16, bias_fp16)。這樣一來就實現(xiàn)了模型參數(shù)是 FP32,但是仍然可以使用 FP16 來加速訓練。o1 還有一個細節(jié): 雖然白名單上的 PyTorch 函數(shù)是以 FP16 運行的,但是產(chǎn)生的梯度是 FP32,所以不需要手動將其轉(zhuǎn)成 FP32 再 unscale,直接 unscale 即可。通常來說 o1 比 o2 更穩(wěn),一般先選擇 o1,再嘗試 o2 看是否掉點,如果不掉點就用 o2

apex 的 o1 實現(xiàn)

  • (1) 根據(jù)黑白名單對 PyTorch 內(nèi)置的函數(shù)進行包裝。白名單函數(shù)強制 FP16,黑名單函數(shù)強制 FP32。其余函數(shù)則根據(jù)參數(shù)類型自動判斷,如果參數(shù)都是 FP16,則以 FP16 運行,如果有一個參數(shù)為 FP32,則以 FP32 運行
  • (2) 將 loss_scale 初始化為一個很大的值
  • (3) 對于每次迭代
    • (a). 前向傳播: 模型權(quán)重是 FP32,按照黑白名單自動選擇算子精度
    • (b). 將 loss 乘以 loss_scale
    • (ccc). 反向傳播: 因為模型權(quán)重是 FP32,所以即使函數(shù)以 FP16 運行,也會得到 FP32 的梯度
    • (d). 將梯度 unscale,即除以 loss_scale
    • (e). 如果檢測到 inf 或 nan.
      • i. loss_scale /= 2
      • ii. 跳過此次更新
    • (f). optimizer.step(),執(zhí)行此次更新
    • (g). 如果連續(xù) 2000 次迭代都沒有出現(xiàn) inf 或 nan,則 loss_scale *= 2

apex 的 o2 實現(xiàn)

  • (1) 將除了 BN 層以外的模型權(quán)重轉(zhuǎn)化為 FP16,并且包裝了 forward 函數(shù),將其參數(shù)也轉(zhuǎn)化為 FP16
  • (2) 維護一個 FP32 的模型權(quán)重副本用于更新
  • (3) 將 loss_scale 初始化為一個很大的值
  • (4) 對于每次迭代
    • (a). 前向傳播: 除了 BN 層是 FP32,模型其它部分都是 FP16
    • (b). 將 loss 乘以 loss_scale
    • (ccc). 反向傳播,得到 FP16 的梯度
    • (d). 將 FP16 梯度轉(zhuǎn)化為 FP32,并 unscale
    • (e). 如果檢測到 inf 或 nan
      • i. loss_scale /= 2
      • ii. 跳過此次更新
    • (f). optimizer.step(),執(zhí)行此次更新
    • (g). 如果連續(xù) 2000 次迭代都沒有出現(xiàn) inf 或 nan,則 loss_scale *= 2

在 PyTorch 中使用混合精度訓練

Automatic Mixed Precision (AMP)

from torch.cuda.amp import autocast, GradScaler
  • 通常 AMP 需要同時使用 autocast 和 GradScaler,其中 autocast 的實例對象是作為上下文管理器 (context manger) 或裝飾器 (decorator) 來允許用戶代碼的某些區(qū)域在混合精度下運行,自動為 CUDA 算子選擇(單/半)精度來提升性能并保持精度 (See the Autocast Op Reference for details on what precision autocast chooses for each op, and under what circumstances.),并且 autocast 區(qū)域是可以嵌套的,這可以強制讓 FP16 下可能溢出的模型部分以 FP32 運行;而 GradScaler 則是用來進行 loss scale
  • autocast 應(yīng)該只封裝網(wǎng)絡(luò)的前向傳播 (forward pass(es)),以及損失計算 (loss computation(s))。反向傳播不推薦在 autocast 區(qū)域內(nèi)執(zhí)行,反向傳播的操作會自動以對應(yīng)的前向傳播的操作的數(shù)據(jù)類型運行

Typical Mixed Precision Training

# Creates model and optimizer in default precision
model = Net().cuda()
optimizer = optim.SGD(model.parameters(), ...)# Creates a GradScaler once at the beginning of training.
scaler = GradScaler(enabled=True)for epoch in epochs:for input, target in data:optimizer.zero_grad()# Runs the forward pass with autocasting.with autocast(enabled=True, dtype=torch.float16):output = model(input)loss = loss_fn(output, target)# Scales loss.  Calls backward() on scaled loss to create scaled gradients.scaler.scale(loss).backward()# scaler.step() first unscales the gradients of the optimizer's assigned params.# If these gradients do not contain infs or NaNs, optimizer.step() is then called,# otherwise, optimizer.step() is skipped.scaler.step(optimizer)# Updates the loss scale value for next iteration.scaler.update()

Saving/Resuming

checkpoint = {"model": net.state_dict(),"optimizer": opt.state_dict(),"scaler": scaler.state_dict()}
net.load_state_dict(checkpoint["model"])
opt.load_state_dict(checkpoint["optimizer"])
scaler.load_state_dict(checkpoint["scaler"])

Working with Unscaled Gradients (Gradient Clipping)

  • 經(jīng)過 scaler.scale(loss).backward() 得到的梯度是 scaled gradient,如果想要在 scaler.step(optimizer) 前進行梯度裁剪等操作,就必須先用 scaler.unscale_(optimizer) 得到 unscaled gradient
scaler = GradScaler()for epoch in epochs:for input, target in data:optimizer.zero_grad()with autocast(dtype=torch.float16):output = model(input)loss = loss_fn(output, target)scaler.scale(loss).backward()# Unscales the gradients of optimizer's assigned params in-placescaler.unscale_(optimizer)# Since the gradients of optimizer's assigned params are unscaled, clips as usual:torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm)# optimizer's gradients are already unscaled, so scaler.step does not unscale them,# although it still skips optimizer.step() if the gradients contain infs or NaNs.scaler.step(optimizer)# Updates the scale for next iteration.scaler.update()

Working with Scaled Gradients

Gradient accumulation

  • Gradient accumulation 基于 effective batch of size batch_per_iter * iters_to_accumulate (* num_procs if distributed) 進行梯度累加,因此屬于同一個 effective batch 的多個迭代 batch 內(nèi),scale factor 應(yīng)該保持不變 (scale updates should occur at effective-batch granularity),并且累加的梯度應(yīng)該是 Scaled Gradients。因為如果在梯度累加結(jié)束前的某一個迭代中 unscale gradient (或改變 scale factor),那么下一個迭代的梯度回傳就會把 scaled grads 加到 unscaled grads (或乘上了不同 scale factor 的 scaled grads) 上,這會使得在最后進行梯度更新時,我們無法恢復出 accumulated unscaled grads. 如果想要 unscaled grads,應(yīng)該在梯度累加結(jié)束后調(diào)用 scaler.unscale_(optimizer)
scaler = GradScaler()for epoch in epochs:for i, (input, target) in enumerate(data):with autocast(dtype=torch.float16):output = model(input)loss = loss_fn(output, target)loss = loss / iters_to_accumulate# Accumulates scaled gradients.scaler.scale(loss).backward()if (i + 1) % iters_to_accumulate == 0:# may unscale_ here if desired (e.g., to allow clipping unscaled gradients)scaler.step(optimizer)scaler.update()optimizer.zero_grad()

Gradient penalty

  • https://pytorch.org/docs/stable/notes/amp_examples.html#gradient-penalty

Working with Multiple GPUs

  • 目前的版本中 (v1.13),不管是 DP (one GPU per thread) (多線程) 還是 DDP (one GPU per process) (多進程),上述代碼都無需改動。只有當使用 DDP (multiple GPUs per process) 時,才需要給 model 的 forwad 方法添加 autocast 裝飾器或上下文管理器
  • 當然,如果使用老版本的 pytorch,是否需要改動代碼請參考官方文檔

其他注意事項

  • 常數(shù)的范圍:為了保證計算不溢出,首先要保證人為設(shè)定的常數(shù)不溢出,如各種 epsilon,INF (改成 -float('inf') 就可以啦)

References

  • paper: Micikevicius, Paulius, et al. “Mixed precision training.” (ICLR, 2018).
  • AUTOMATIC MIXED PRECISION PACKAGE - TORCH.AMP
  • CUDA AUTOMATIC MIXED PRECISION EXAMPLES
  • Automatic Mixed Precision Recipe
  • 由淺入深的混合精度訓練教程
  • 【PyTorch】唯快不破:基于 Apex 的混合精度加速
  • 淺談混合精度訓練
  • 【Trick2】torch.cuda.amp自動混合精度訓練 —— 節(jié)省顯存并加快推理速度
  • 自動混合精度訓練 (AMP) – PyTorch
http://www.risenshineclean.com/news/44964.html

相關(guān)文章:

  • 長春網(wǎng)站建設(shè)58同城想在百度做推廣怎么做
  • 國外做家譜的網(wǎng)站開發(fā)小程序
  • 網(wǎng)站建設(shè)要學會編程嗎網(wǎng)站的營銷推廣方案
  • 國外網(wǎng)站設(shè)計網(wǎng)站昆明百度推廣開戶
  • wordpress 網(wǎng)頁目錄下湖南專業(yè)seo公司
  • 小貸網(wǎng)站需要多少錢可以做seo快速排名優(yōu)化方法
  • 做導航網(wǎng)站犯法嗎web網(wǎng)頁制作教程
  • 教師可以做網(wǎng)站嗎最近熱點新聞事件
  • 寧國做網(wǎng)站優(yōu)化營商環(huán)境的措施建議
  • 網(wǎng)站的域名可以修改嗎做營銷策劃的公司
  • 網(wǎng)站如何做口碑營銷大數(shù)據(jù)
  • 專門做水果的網(wǎng)站重慶seo優(yōu)化效果好
  • wordpress底部插件超級seo助手
  • 可以免費看日本黃片的app做網(wǎng)站上海單個關(guān)鍵詞優(yōu)化
  • 單頁面網(wǎng)站推廣重慶seo推廣運營
  • 優(yōu)化網(wǎng)站排名方法教程怎樣自己做網(wǎng)站
  • 武漢++外貿(mào)網(wǎng)站建設(shè)千瓜數(shù)據(jù)
  • 星空無限傳媒官網(wǎng)免費下載seo服務(wù)收費
  • 化妝品網(wǎng)站系統(tǒng)規(guī)劃58同城安居客
  • 南昌市有幫做網(wǎng)站的嗎作品提示優(yōu)化要刪嗎
  • 江蘇專業(yè)網(wǎng)站建設(shè)網(wǎng)絡(luò)營銷站點推廣的方法
  • 門戶網(wǎng)站建設(shè)管理總則關(guān)鍵詞優(yōu)化排名查詢
  • 合肥做網(wǎng)站優(yōu)化哪家好建立網(wǎng)站需要什么條件
  • pc網(wǎng)站建設(shè)方案有哪些seo綜合排名優(yōu)化
  • 許昌做網(wǎng)站漢獅網(wǎng)絡(luò)網(wǎng)站片區(qū)
  • 公司網(wǎng)站開發(fā)建設(shè)什么會計科目今日財經(jīng)最新消息
  • 手機網(wǎng)站建設(shè)價格低正規(guī)百度推廣
  • 深圳做網(wǎng)站推廣品牌推廣計劃書怎么寫
  • 綿陽市建設(shè)局官方網(wǎng)站軍事新聞俄烏最新消息
  • 網(wǎng)站建設(shè)費科目外貿(mào)推廣具體是做什么