使用PyTorch構(gòu)建神經(jīng)網(wǎng)絡(luò),并計(jì)算參數(shù)Params
在深度學(xué)習(xí)中,模型的參數(shù)數(shù)量是一個(gè)非常重要的指標(biāo),通常會(huì)影響模型的大小、訓(xùn)練速度和準(zhǔn)確度等多個(gè)方面。在本教程中,我們將介紹如何計(jì)算深度學(xué)習(xí)模型的參數(shù)數(shù)量。
本教程將以PyTorch為例,展示如何計(jì)算一個(gè)包含卷積、池化、歸一化和全連接等多種層的卷積神經(jīng)網(wǎng)絡(luò)的參數(shù)數(shù)量。具體來說,我們將首先介紹一個(gè)具有全連接層的神經(jīng)網(wǎng)絡(luò)的參數(shù)計(jì)算方法,然后擴(kuò)展到包含卷積、池化、歸一化和全連接等多種層的卷積神經(jīng)網(wǎng)絡(luò)。
舉例
計(jì)算具有全連接層的神經(jīng)網(wǎng)絡(luò)的參數(shù)數(shù)量
假設(shè)我們有一個(gè)輸入向量 x x x,其維度為 d i n d_{in} din?,我們想將其映射到一個(gè)輸出向量 y y y,其維度為 d o u t d_{out} dout?。我們可以使用一個(gè)具有 n n n個(gè)隱藏層的全連接神經(jīng)網(wǎng)絡(luò)來完成這個(gè)映射,其中每個(gè)隱藏層具有 h h h個(gè)神經(jīng)元。
在PyTorch中,我們可以通過定義一個(gè)繼承自nn.Module
的類來實(shí)現(xiàn)這個(gè)神經(jīng)網(wǎng)絡(luò)。下面是一個(gè)定義了一個(gè)具有兩個(gè)隱藏層的全連接神經(jīng)網(wǎng)絡(luò)的示例代碼:
import torch
import torch.nn as nn
class Net(nn.Module):
def __init__(self, d_in, h, d_out, n):
super(Net, self).__init__()
self.linear1 = nn.Linear(d_in, h)
self.linear2 = nn.Linear(h, h)
self.linear3 = nn.Linear(h, d_out)
self.n = n
def forward(self, x):
h_relu = self.linear1(x).clamp(min=0)
for i in range(self.n):
h_relu = self.linear2(h_relu).clamp(min=0)
y_pred = self.linear3(h_relu)
return y_pred
其中,nn.Linear
是PyTorch中的一個(gè)線性層,它將輸入向量乘以一個(gè)權(quán)重矩陣,并加上一個(gè)偏置向量,得到輸出向量。在這個(gè)例子中,我們定義了三個(gè)線性層,分別為self.linear1
、self.linear2
和self.linear3
。在forward
函數(shù)中,我們首先將輸入向量x
傳遞給self.linear1
,然后通過ReLU非線性激活函數(shù)得到一個(gè)隱藏層輸出h_relu
。接下來,我們使用for循環(huán)多次將h_relu
傳遞給self.linear2
,再次使用ReLU非線性激活函數(shù)得到另一個(gè)隱藏層輸出。最后,我們將最后一個(gè)隱藏層的輸出傳遞給self.linear3
,得到輸出向量y_pred
。
現(xiàn)在讓我們計(jì)算一下這個(gè)神經(jīng)網(wǎng)絡(luò)的參數(shù)數(shù)量。對(duì)于每個(gè)線性層,它都有一個(gè)權(quán)重矩陣和一個(gè)偏置向量,因此總的參數(shù)數(shù)量為:
參數(shù)數(shù)量 = d_in * h + h * h * (n-1) + h * d_out + h + d_out
其中,第一項(xiàng) d i n ? h d_{in} * h din??h是輸入層到第一個(gè)隱藏層的權(quán)重矩陣的參數(shù)數(shù)量;第二項(xiàng) h ? h ? ( n ? 1 ) h * h * (n-1) h?h?(n?1)是每個(gè)隱藏層之間的權(quán)重矩陣的參數(shù)數(shù)量;第三項(xiàng) h ? d o u t h * d_{out} h?dout?是最后一個(gè)隱藏層到輸出層的權(quán)重矩陣的參數(shù)數(shù)量;第四項(xiàng) h h h和 d o u t d_{out} dout?分別是偏置向量的參數(shù)數(shù)量。
因此,這個(gè)具有兩個(gè)隱藏層的全連接神經(jīng)網(wǎng)絡(luò)的參數(shù)數(shù)量取決于輸入向量的維度 d i n d_{in} din?,輸出向量的維度 d o u t d_{out} dout?,每個(gè)隱藏層的神經(jīng)元數(shù)量 h h h和隱藏層數(shù)量 n n n。
計(jì)算卷積神經(jīng)網(wǎng)絡(luò)的參數(shù)數(shù)量
現(xiàn)在讓我們將上述方法擴(kuò)展到卷積神經(jīng)網(wǎng)絡(luò)中。卷積神經(jīng)網(wǎng)絡(luò)是一種常用的深度學(xué)習(xí)模型,通常用于圖像識(shí)別、自然語(yǔ)言處理等領(lǐng)域。它由多個(gè)卷積層、池化層、歸一化層和全連接層等多種層組成。
為了計(jì)算卷積神經(jīng)網(wǎng)絡(luò)的參數(shù)數(shù)量,我們需要考慮每一層的參數(shù)數(shù)量。下面是一個(gè)簡(jiǎn)單的卷積神經(jīng)網(wǎng)絡(luò)的示例代碼:
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchsummary import summary
from thop import profile
device = torch.device("cuda" if torch.cuda.is_available() else 'cpu')
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=3, stride=1, padding=1)
self.bn1 = nn.BatchNorm2d(16)
self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)
self.conv2 = nn.Conv2d(in_channels=16, out_channels=32, kernel_size=3, stride=1, padding=1)
self.bn2 = nn.BatchNorm2d(32)
self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)
self.fc1 = nn.Linear(32 * 8 * 8, 64)
self.fc2 = nn.Linear(64, 10)
def forward(self, x):
x = self.conv1(x)
x = self.bn1(x)
x = F.relu(x)
x = self.pool1(x)
x = self.conv2(x)
x = self.bn2(x)
x = F.relu(x)
x = self.pool2(x)
x = x.view(-1, 32 * 8 * 8)
x = self.fc1(x)
x = F.relu(x)
x = self.fc2(x)
return x
net = Net().to(device)
input_shape = (3, 224, 224)
summary(net, input_shape)
input_tensor = torch.randn(1, *input_shape).to(device)
flops, params = profile(net, inputs=(input_tensor,))
print('FLOPs: {:.2f}M'.format(flops / 1e6))
在這個(gè)示例中,我們定義了一個(gè)包含兩個(gè)卷積層、兩個(gè)池化層、兩個(gè)歸一化層和兩個(gè)全連接層的卷積神經(jīng)網(wǎng)絡(luò)。我們使用nn.Conv2d
定義了兩個(gè)卷積層,使用nn.BatchNorm2d
定義了兩個(gè)歸一化層,使用nn.MaxPool2d
定義了兩個(gè)池化層,使用nn.Linear
定義了兩個(gè)全連接層。
該網(wǎng)絡(luò)結(jié)構(gòu)輸出如下:
Params計(jì)算過程
我們可以使用如下的方法計(jì)算這個(gè)卷積神經(jīng)網(wǎng)絡(luò)的參數(shù)數(shù)量:
- 對(duì)于每個(gè)卷積層,它有一個(gè)包含卷積核參數(shù)的權(quán)重張量和一個(gè)包含偏置參數(shù)的向量。因此,卷積層的參數(shù)數(shù)量為out_channels * (in_channels * kernel_size^2 + 1)。
- 對(duì)于每個(gè)歸一化層,它有兩個(gè)參數(shù):縮放因子和偏移量。因此,歸一化層的參數(shù)數(shù)量為2 * out_channels。
- 對(duì)于每個(gè)全連接層,它有一個(gè)包含權(quán)重參數(shù)的權(quán)重矩陣和一個(gè)包含偏置參數(shù)的向量。因此,全連接層的參數(shù)數(shù)量為(in_features + 1) * out_features。
根據(jù)上述公式,我們可以計(jì)算這個(gè)示例卷積神經(jīng)網(wǎng)絡(luò)的參數(shù)數(shù)量:
參數(shù)數(shù)量 = conv1參數(shù)數(shù)量 + bn1參數(shù)數(shù)量 + conv2參數(shù)數(shù)量 + bn2參數(shù)數(shù)量 + fc1參數(shù)數(shù)量 + fc2參數(shù)數(shù)量
= 16 * (3 * 3^2 + 1) + 16 * 2 + 32 * (16 * 3^2 + 1) + 32 * 2 + (32 * 8 * 8 + 1) * 64 + (64 + 1) * 10
= 136,970
因此,這個(gè)示例卷積神經(jīng)網(wǎng)絡(luò)的參數(shù)數(shù)量為136,970。
它計(jì)算了模型中各層的參數(shù)數(shù)量,包括卷積層、全連接層和BatchNorm層的參數(shù)數(shù)量。具體來說,公式計(jì)算了:
- 第一層卷積層的參數(shù)數(shù)量:輸入通道數(shù)為3,輸出通道數(shù)為16,卷積核大小為3x3,因此共有16個(gè)卷積核,每個(gè)卷積核有3x3=9個(gè)參數(shù),另外還有16個(gè)偏置參數(shù),因此該層參數(shù)數(shù)量為16x(3x3+1)=448。
- 第一層BatchNorm層的參數(shù)數(shù)量:該層有16個(gè)輸出通道,每個(gè)通道有2個(gè)參數(shù)(縮放因子和偏置項(xiàng)),因此該層參數(shù)數(shù)量為16x2=32。
- 第二層卷積層的參數(shù)數(shù)量:輸入通道數(shù)為16,輸出通道數(shù)為32,卷積核大小為3x3,因此共有32個(gè)卷積核,每個(gè)卷積核有16x3x3=144個(gè)參數(shù),另外還有32個(gè)偏置參數(shù),因此該層參數(shù)數(shù)量為32x(16x3x3+1)=4608。
- 第二層BatchNorm層的參數(shù)數(shù)量:該層有32個(gè)輸出通道,每個(gè)通道有2個(gè)參數(shù),因此該層參數(shù)數(shù)量為32x2=64。
- 第一個(gè)全連接層的參數(shù)數(shù)量:該層輸入特征數(shù)為32x8x8=2048,輸出特征數(shù)為64,因此該層參數(shù)數(shù)量為2048x64+64=131,136。
- 第二個(gè)全連接層的參數(shù)數(shù)量:該層輸入特征數(shù)為64,輸出特征數(shù)為10,因此該層參數(shù)數(shù)量為64x10+10=650。
將上述各層的參數(shù)數(shù)量相加,即可得到模型的總參數(shù)數(shù)量。
另外,需要注意的是,參數(shù)數(shù)量和FLOPs是不同的概念。FLOPs是指在模型推理過程中,需要進(jìn)行的浮點(diǎn)運(yùn)算次數(shù),而參數(shù)數(shù)量則是指模型中需要學(xué)習(xí)的參數(shù)的數(shù)量。在計(jì)算FLOPs時(shí),需要考慮到每個(gè)卷積層、池化層和全連接層的輸入輸出形狀,以及各層的卷積核大小、步長(zhǎng)等參數(shù)信息。
總結(jié)
計(jì)算深度學(xué)習(xí)模型的參數(shù)數(shù)量是深度學(xué)習(xí)中非?;A(chǔ)的知識(shí)點(diǎn),掌握好這一知識(shí)點(diǎn)有助于更好地理解和設(shè)計(jì)深度學(xué)習(xí)模型。
在本教程中,我們介紹了如何計(jì)算具有全連接層的神經(jīng)網(wǎng)絡(luò)和卷積神經(jīng)網(wǎng)絡(luò)的參數(shù)數(shù)量。對(duì)于具有全連接層的神經(jīng)網(wǎng)絡(luò),我們可以使用簡(jiǎn)單的公式計(jì)算參數(shù)數(shù)量;對(duì)于卷積神經(jīng)網(wǎng)絡(luò),我們需要考慮每一層的參數(shù)數(shù)量,并將它們相加得到總的參數(shù)數(shù)量。
需要注意的是,計(jì)算參數(shù)數(shù)量時(shí)需要注意每個(gè)層的超參數(shù),例如卷積層的輸入和輸出通道數(shù)、卷積核大小等等。此外,某些特殊的層,如Dropout層或者BatchNorm層,可能需要特殊的計(jì)算方法。
在實(shí)際應(yīng)用中,我們通常使用現(xiàn)有的深度學(xué)習(xí)框架(如PyTorch、TensorFlow等)來構(gòu)建和訓(xùn)練深度學(xué)習(xí)模型,這些框架通常會(huì)自動(dòng)計(jì)算模型的參數(shù)數(shù)量。但是,對(duì)于自己實(shí)現(xiàn)的模型或者需要手動(dòng)調(diào)整模型參數(shù)的情況,了解計(jì)算參數(shù)數(shù)量的方法仍然非常有用。文章來源:http://www.zghlxwxcb.cn/news/detail-437151.html
希望本教程對(duì)您有所幫助!文章來源地址http://www.zghlxwxcb.cn/news/detail-437151.html
到了這里,關(guān)于使用PyTorch構(gòu)建神經(jīng)網(wǎng)絡(luò),并計(jì)算參數(shù)Params的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!