FLOPs、FLOPS、Params的含義及PyTorch中的計算方法
含義解釋
-
FLOPS:注意全大寫,是floating point operations per second的縮寫(這里的大S表示second秒),表示每秒浮點運算次數,理解為計算速度。是一個衡量硬件性能的指標。
-
FLOPs:注意s小寫,是floating point operations的縮寫(這里的小s則表示復數),表示浮點運算數,理解為計算量。可以用來衡量算法/模型的復雜度。
-
Params:沒有固定的名稱,大小寫均可,表示模型的參數量,也是用來衡量算法/模型的復雜度。通常我們在論文中見到的是這樣:# Params,那個井號是表示 number of 的意思,因此 # Params 的意思就是:參數的數量。
FLOPs與模型時間復雜度、GPU利用率有關,Params與模型空間復雜度、顯存占用有關。即我們常見的nvidia-smi
命令中的GPU利用率(紅框)和顯存占用(籃框)。
MAC
MAC:Multiply Accumulate,乘加運算。乘積累加運算(英語:Multiply Accumulate, MAC)是在數字信號處理器或一些微處理器中的特殊運算。實現此運算操作的硬件電路單元,被稱為“乘數累加器”。這種運算的操作,是將乘法的乘積結果和累加器的值相加,再存入累加器:
a←a+b×ca\leftarrow a+b\times c a←a+b×c
使用MAC可以將原本需要的兩個指令操作減少到一個指令操作,從而提高運算效率。
FLOPs的計算
以下不考慮激活函數的計算量。
卷積層
(2×Ci×K2?1)×H×W×C0(2\times C_i\times K^2-1)\times H\times W\times C_0(2×Ci?×K2?1)×H×W×C0?
CiC_iCi?=輸入通道數, KKK=卷積核尺寸,H,WH,WH,W=輸出特征圖空間尺寸,CoC_oCo?=輸出通道數。
一個MAC算兩個個浮點運算,所以在最前面×2\times 2×2。不考慮bias時有?1-1?1,有bias時沒有?1-1?1。由于考慮的一般是模型推理時的計算量,所以上述公式是針對一個輸入樣本的情況,即batch size=1。
理解上面這個公式分兩步,括號內是第一步,計算出輸出特征圖的一個pixel的計算量,然后再乘以 H×W×CoH\times W\times C_oH×W×Co? 拓展到整個輸出特征圖。
括號內的部分又可以分為兩步,(2?Ci?K2?1)=(Ci?K2)+(Ci?K2?1)(2\cdot C_i\cdot K^2-1)=(C_i\cdot K^2)+(C_i\cdot K^2-1)(2?Ci??K2?1)=(Ci??K2)+(Ci??K2?1)。第一項是乘法運算數,第二項是加法運算數,因為 nnn 個數相加,要加 n?1n-1n?1 次,所以不考慮bias,會有一個?1-1?1,如果考慮bias,剛好中和掉,括號內變為 2?Ci?K22\cdot C_i\cdot K^22?Ci??K2。
全連接層
全連接層: (2×I?1)×O(2\times I-1)\times O(2×I?1)×O
III=輸入層神經元個數 ,OOO=輸出層神經元個數。
還是因為一個MAC算兩個個浮點運算,所以在最前面×2\times 2×2。同樣不考慮bias時有?1-1?1,有bias時沒有?1-1?1。分析同理,括號內是一個輸出神經元的計算量,拓展到OOO了輸出神經元。
NVIDIA Paper [2017-ICLR]
筆者在這里放上 NVIDIA 在 【2017-ICLR】的論文:PRUNING CONVOLUTIONAL NEURAL NETWORKS FOR RESOURCE EFFICIENT INFERENCE 的附錄部分FLOPs計算方法截圖放在下面供讀者參考。
使用PyTorch直接輸出模型的Params(參數量)
完整統計參數量
import torch
from torchvision.models import resnet50
import numpy as npTotal_params = 0
Trainable_params = 0
NonTrainable_params = 0model = resnet50()
for param in model.parameters():mulValue = np.prod(param.size()) # 使用numpy prod接口計算參數數組所有元素之積Total_params += mulValue # 總參數量if param.requires_grad:Trainable_params += mulValue # 可訓練參數量else:NonTrainable_params += mulValue # 非可訓練參數量print(f'Total params: {Total_params / 1e6}M')
print(f'Trainable params: {Trainable_params/ 1e6}M')
print(f'Non-trainable params: {NonTrainable_params/ 1e6}M')
輸出:
Total params: 25.557032M
Trainable params: 25.557032M
Non-trainable params: 0.0M
簡單統計可訓練的參數量
通常,我們想知道的只是可訓練的參數量,我們也可以簡單地直接一行統計出可訓練的參數量:
import torchvision.models as modelsmodel = models.resnet50(pretrained=False)Trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
print(f'Trainable params: {Trainable_params/ 1e6}M')
輸出:
Trainable params: 25.557032M
統計每一層的參數量
倘若想要統計每一層的參數量,參考代碼如下:
model = vgg16()
for name, parameters in model.named_parameters():print(name, ':', np.prod(parameters.size()))
會打印出每一層的名稱及參數量:
features.0.weight : 1728
features.0.bias : 64
features.2.weight : 36864
features.2.bias : 64
features.5.weight : 73728
...
使用thop庫來獲取模型的FLOPs(計算量)和Params(參數量)
安裝
直接pypi安裝即可
pip install thop
使用
我們使用thop
庫來計算vgg16模型的計算量和參數量。
import torch
from thop import profile
from archs.ViT_model import get_vit, ViT_Aes
from torchvision.models import resnet50model = resnet50()
input1 = torch.randn(4, 3, 224, 224)
flops, params = profile(model, inputs=(input1, ))
print('FLOPs = ' + str(flops/1000**3) + 'G')
print('Params = ' + str(params/1000**2) + 'M')
輸出:
FLOPs = 16.446058496G
Params = 25.557032M
Ref:
https://openreview.net/forum?id=SJGCiw5gl
https://www.zhihu.com/question/65305385/answer/451060549
https://www.cnblogs.com/chuqianyu/p/14254702.html