一般情況來說,我們通過收集數(shù)據(jù),訓(xùn)練深度學(xué)習(xí)模型,通過反向傳播求導(dǎo)更新模型的參數(shù),得到一個(gè)契合數(shù)據(jù)和任務(wù)的模型。這一階段,通常使用python&pytorch進(jìn)行模型的訓(xùn)練得到pth等類型文件。AI模型部署就是將在python環(huán)境中訓(xùn)練的模型參數(shù)放到需要部署的硬件環(huán)境中去跑,比如云平臺(tái)和其他cpu、gpu設(shè)備中。一般來說,權(quán)重信息以及權(quán)重分布基本不會(huì)變(可能會(huì)改變精度、也可能會(huì)合并一些權(quán)重)。
該部分筆記參考o(jì)ldpan內(nèi)容
模型權(quán)重
一般我們使用Pytorch模型進(jìn)行訓(xùn)練。訓(xùn)練得到的權(quán)重,我們一般都會(huì)使用torch.save()保存為.pth的格式。
pth文件內(nèi)容
pth是Pytorch使用python中內(nèi)置模塊pickle來保存和讀取,pth文件的中主要包含字符段{‘epoch’: 190, ‘state_dict’: OrderedDict([(‘conv1.weight’, tensor([[…,},其中epoch 為pth保存的輪次數(shù)、state_dict中包含主要的模型結(jié)構(gòu)名稱和對(duì)應(yīng)模型參數(shù)值,
state_dict的key:
- 主要權(quán)重結(jié)構(gòu)
在模型訓(xùn)練過程中,有很多需要通過反向傳播更新的權(quán)重,常見的有:
卷積層(conv.weight \conv.bias)
全連接層 (fc.weight)
批處理化層(BN層、或者各種其他LN、IN、GN)
transformer-encoder層
DCN層
這些層一般都是神經(jīng)網(wǎng)絡(luò)的核心部分,當(dāng)然都是有參數(shù)的,一定會(huì)參與模型的反向傳播更新,是我們?cè)谟?xùn)練模型時(shí)候需要注意的重要參數(shù)。
- BN的反向傳播與參數(shù)更新
BN層中的可學(xué)習(xí)參數(shù)(如果affine=True)會(huì)參與反向傳播并在訓(xùn)練過程中更新,而用于歸一化的統(tǒng)計(jì)量(running_mean和running_var)則通過不同的機(jī)制進(jìn)行更新。
# 截取了Pytorch中BN層的部分代碼
def __init__(
self,
num_features: int,
eps: float = 1e-5,
momentum: float = 0.1,
affine: bool = True,
track_running_stats: bool = True
) -> None:
super(_NormBase, self).__init__()
self.num_features = num_features
self.eps = eps
self.momentum = momentum
self.affine = affine
self.track_running_stats = track_running_stats
if self.affine:
self.weight = Parameter(torch.Tensor(num_features))
self.bias = Parameter(torch.Tensor(num_features))
else:
self.register_parameter('weight', None)
self.register_parameter('bias', None)
if self.track_running_stats:
# 可以看到在使用track_running_stats時(shí),BN層會(huì)更新這三個(gè)參數(shù)
self.register_buffer('running_mean', torch.zeros(num_features))
self.register_buffer('running_var', torch.ones(num_features))
self.register_buffer('num_batches_tracked', torch.tensor(0, dtype=torch.long))
else:
self.register_parameter('running_mean', None)
self.register_parameter('running_var', None)
self.register_parameter('num_batches_tracked', None)
self.reset_parameters()
- 模型結(jié)構(gòu)無參數(shù)層
網(wǎng)絡(luò)中其實(shí)有很多op,僅僅是做一些維度變換、索引取值或者上/下采樣的操作,例如:
Reshape
Squeeze
Unsqueeze
Split
Transpose
Gather
這些操作沒有參數(shù)僅僅是對(duì)上一層傳遞過來的張量進(jìn)行維度變換。有時(shí)候在通過Pytorch轉(zhuǎn)換為ONNX的時(shí)候,偶爾會(huì)發(fā)生一些轉(zhuǎn)換詭異的情況。比如一個(gè)簡單的reshape會(huì)四分五裂為gather+slip+concat,這種操作相當(dāng)于復(fù)雜化了,不過一般來說這種情況可以使用ONNX-SIMPLIFY去優(yōu)化掉,當(dāng)然遇到較為復(fù)雜的就需要自行優(yōu)化了。此外,對(duì)于這些變形類的操作算子,其實(shí)有些是有參數(shù)的,例如下圖的reshap
像這種的op,有時(shí)候會(huì)比較棘手。如果想要將這個(gè)ONNX模型轉(zhuǎn)換為TensorRT,那么100%會(huì)遇到問題,因?yàn)門ensorRT的解釋器在解析ONNX的時(shí)候,不支持reshape層的shape是輸入TensorRT,而是把這個(gè)shape當(dāng)成attribute來處理,而ONNX的推理框架Inference則是支持的。
state_dict的value:
模型訓(xùn)練出的各層參數(shù),都是有固定精度的0-1數(shù)據(jù)。通常來說,pth文件的參數(shù)精度為FP32,然而對(duì)于模型參數(shù)的部署來說我們需要在硬件中進(jìn)行精度和推理速度之間的協(xié)調(diào)。
不過執(zhí)行模型操作(卷積、全連接、反卷積)的算子會(huì)變化,可能從Pytorch->TensorRT或者TensorFlow->TFLITE,也就是實(shí)現(xiàn)算子的方式變了,同一個(gè)卷積操作,在Pytorch框架中是一種實(shí)現(xiàn),在TensorRT又是另一種實(shí)踐,兩者的基本原理是一樣的,但是精度和速度不一樣,TensorRT可以借助Pytorch訓(xùn)練好的卷積的權(quán)重,實(shí)現(xiàn)與Pytorch中一樣的操作,不過可能更快些。
參數(shù)精度
浮點(diǎn)數(shù)精度:雙精度(FP64)、單精度(FP32、TF32)、半精度(FP16、BF16)、8位精度(FP8)、4位精度(FP4、NF4)
量化精度:INT8、INT4 (也有INT3/INT5/INT6的)
為什么要有這么多精度
因?yàn)槌杀竞蜏?zhǔn)確度。
都知道精度高肯定更準(zhǔn)確,但是也會(huì)帶來更高的計(jì)算和存儲(chǔ)成本。**較低的精度會(huì)降低計(jì)算精度,但可以提高計(jì)算效率和性能。**所以多種不同精度,可以讓你在不同情況下選擇最適合的一種。
雙精度比單精度表達(dá)的更精確,但是存儲(chǔ)占用多一倍,計(jì)算耗時(shí)也更高,如果單精度足夠,就沒必要雙精度。
但如何評(píng)估是否要進(jìn)行精度降低?
不同的浮點(diǎn)數(shù)精度
在計(jì)算機(jī)中,浮點(diǎn)數(shù)存儲(chǔ)方式,由由**符號(hào)位(sign)、指數(shù)位(exponent)和小數(shù)位(fraction)**三部分組成。符號(hào)位都是1位,指數(shù)位影響浮點(diǎn)數(shù)范圍,小數(shù)位影響精度。
FP精度
特殊精度
- TF32(1,8,10)
其實(shí)只有19位,Tensor Float 32,英偉達(dá)針對(duì)機(jī)器學(xué)習(xí)設(shè)計(jì)的一種特殊的數(shù)值類型,用于替代FP32。首次在A100 GPU中支持。 - BF16(1,8,7)
Brain Float 16,由Google Brain提出,也是為了機(jī)器學(xué)習(xí)而設(shè)計(jì)。由1個(gè)符號(hào)位,8位指數(shù)位(和FP32一致)和7位小數(shù)位(低于FP16)組成。所以精度低于FP16,但是表示范圍和FP32一致,和FP32之間很容易轉(zhuǎn)換。在 NVIDIA GPU 上,只有 Ampere 架構(gòu)以及之后的GPU 才支持。 - NF4
4-bit NormalFloat,一種用于量化的特殊格式,于23年5月由華盛頓大學(xué)在QLoRA量化論文中提出,論文地址:https://arxiv.org/abs/2305.14314
NF4是建立在分位數(shù)量化技術(shù)的基礎(chǔ)之上的一種信息理論上最優(yōu)的數(shù)據(jù)類型。把4位的數(shù)字歸一化到均值為 0,標(biāo)準(zhǔn)差為 [-1,1] 的正態(tài)分布的固定期望值上,知道量化原理的應(yīng)該就會(huì)理解。文章來源:http://www.zghlxwxcb.cn/news/detail-809426.html
一般情況下,精度越低,模型尺寸和推理內(nèi)存占用越少,為了盡可能的減少資源占用,量化算法被發(fā)明。FP32占用4個(gè)字節(jié),量化為8位,只需要1個(gè)字節(jié)。常用的是INT8和INT4,也有其他量化格式(6位、5位甚至3位)。雖然資源占用減少,但是推理結(jié)果差不了多少。那么接下來就是我們說到的量化問題。文章來源地址http://www.zghlxwxcb.cn/news/detail-809426.html
到了這里,關(guān)于AI模型部署基礎(chǔ)知識(shí)(一):模型權(quán)重與參數(shù)精度的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!