首頁 > 軟體

Pytorch模型定義與深度學習自查手冊

2022-06-02 14:00:34

定義神經網路

  • 繼承nn.Module類;
  • 初始化函數__init__:網路層設計;
  • forward函數:模型執行邏輯。
class NeuralNetwork(nn.Module):
    def __init__(self):
        super(NeuralNetwork, self).__init__()
        self.flatten = nn.Flatten()
        self.linear_relu_stack = nn.Sequential(
            nn.Linear(28*28, 512),
            nn.ReLU(),
            nn.Linear(512, 512),
            nn.ReLU(),
            nn.Linear(512, 10),
        )
    def forward(self, x):
        x = self.flatten(x)
        logits = self.linear_relu_stack(x)
        return logits

權重初始化

pytorch中的權值初始化

方法1:net.apply(weights_init)

def weights_init(m):
    classname = m.__class__.__name__
    if classname.find('Conv') != -1:
        nn.init.normal_(m.weight.data, 0.0, 0.02)
    elif classname.find('BatchNorm') != -1:
        nn.init.normal_(m.weight.data, 1.0, 0.02)
        nn.init.constant_(m.bias.data, 0)
net=Model()
net.apply(weights_init)

方法2:在網路初始化的時候進行引數初始化

  • 使用net.modules()遍歷模型中的網路層的型別;
  • 對其中的m層的weigth.data(tensor)部分進行初始化操作。
class Model(nn.Module):
    def __init__(self, block, layers, num_classes=1000):
        self.inplanes = 64
        super(Model, self).__init__()
        self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3,
                               bias=False)
        self.bn1 = nn.BatchNorm2d(64)
        self.relu = nn.ReLU(inplace=True)
        self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
        self.layer1 = ...
        ...
        # 權值引數初始化
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
                m.weight.data.normal_(0, math.sqrt(2. / n))
            elif isinstance(m, nn.BatchNorm2d):
                m.weight.data.fill_(1)
                m.bias.data.zero_()

常用的操作

利用nn.Parameter()設計新的層

import torch
from torch import nn
class MyLinear(nn.Module):
  def __init__(self, in_features, out_features):
    super().__init__()
    self.weight = nn.Parameter(torch.randn(in_features, out_features))
    self.bias = nn.Parameter(torch.randn(out_features))
  def forward(self, input):
    return (input @ self.weight) + self.bias

nn.Flatten

展平輸入的張量: 28x28 -> 784

input = torch.randn(32, 1, 5, 5)
m = nn.Sequential(
    nn.Conv2d(1, 32, 5, 1, 1),
    nn.Flatten()
)
output = m(input)
output.size()

nn.Sequential

一個有序的容器,神經網路模組將按照在傳入構造器的順序依次被新增到計算圖中執行,同時以神經網路模組為元素的有序字典也可以作為傳入引數。

net = nn.Sequential(
   ('fc1',MyLinear(4, 3)),
   ('act',nn.ReLU()),
   ('fc2',MyLinear(3, 1))
)

常用的層

全連線層nn.Linear()

torch.nn.Linear(in_features, out_features, bias=True,device=None, dtype=None)

in_features: 輸入維度
out_features:輸出維度
bias: 是否有偏置
m = nn.Linear(20, 30)
input = torch.randn(128, 20)
output = m(input)
print(output.size())

torch.nn.Dropout

'''
p:將元素置0的概率,預設值=0.5
'''
torch.nn.Dropout(p=0.5, inplace=False)

折積torch.nn.ConvNd()

class torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)

in_channels(int) – 輸入訊號的通道   
out_channels(int) – 折積產生的通道
kerner_size(int or tuple) - 折積核的尺寸
stride(int or tuple, optional) - 折積步長
padding (int or tuple, optional)- 輸入的每一條邊補充0的層數   
dilation(int or tuple, optional) – 折積核元素之間的間距
groups(int, optional) – 從輸入通道到輸出通道的阻塞連線數
bias(bool, optional) - 如果bias=True,新增偏置

input: (N,C_in,H_in,W_in) N為批次,C_in即為in_channels,即一批內輸入二維資料個數,H_in是二維資料行數,W_in是二維資料的列數

output: (N,C_out,H_out,W_out) N為批次,C_out即為out_channels,即一批內輸出二維資料個數,H_out是二維資料行數,W_out是二維資料的列數

conv2 = nn.Conv2d( 
            in_channels=5,
            out_channels=32,
            kernel_size=5,
            stride=1,
            padding=2  #padding是需要計算的,padding=(stride-1)/2
)
#只能接受tensor/variable
conv2(torch.Tensor(16, 5, 3, 10))
conv2(Variable(torch.Tensor(16, 5, 3, 10)))

池化

最大池化torch.nn.MaxPoolNd()

torch.nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)

kernel_size- 視窗大小
stride- 步長。預設值是kernel_size
padding - 補0數
dilation– 控制視窗中元素步幅的引數
return_indices - 如果等於True,會返回輸出最大值的序號,對於上取樣操作會有幫助
ceil_mode - 如果等於True,計算輸出訊號大小的時候,會使用向上取整,代替預設的向下取的操作
max2=torch.nn.MaxPool2d(3,1,0,1)
max2(torch.Tensor(16,15,15,14))
#output_shape=torch.Size([16, 15, 13, 12])

均值池化torch.nn.AvgPoolNd()

kernel_size - 池化視窗大小
stride- 步長。預設值是kernel_size
padding- 輸入的每一條邊補充0的層數
dilation – 一個控制視窗中元素步幅的引數
return_indices - 如果等於True,會返回輸出最大值的序號,對於上取樣操作會有幫助
ceil_mode - 如果等於True,計算輸出訊號大小的時候,會使用向上取整,代替預設的向下取整的操作
torch.nn.AvgPool2d(kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True)

反池化

是池化的一個“逆”過程,但“逆”只是通過上取樣恢復到原來的尺寸,畫素值是不能恢復成原來一模一樣,因為像最大池化是不可逆的,除最大值之外的畫素都已經丟棄了。

最大值反池化nn.MaxUnpool2d()

功能:對二維影象進行最大值池化上取樣

引數:

kernel_size- 視窗大小
stride - 步長。預設值是kernel_size
padding - 補0數
torch.nn.MaxUnpool2d(kernel_size, stride=None, padding=0)
img_tensor=torch.Tensor(16,5,32,32)
# 上取樣
max_pool = nn.MaxPool2d(kernel_size=(2, 2), stride=(2, 2), return_indices=True, ceil_mode=True)
img_pool, indices = max_pool(img_tensor)
# 下取樣
img_unpool = torch.rand_like(img_pool, dtype=torch.float)   # 輸入影象的大小和上取樣的大小保持一致
max_unpool = nn.MaxUnpool2d((2, 2), stride=(2, 2))   
img_unpool = max_unpool(img_unpool, indices)

組合池化

組合池化同時利用最大值池化與均值池化兩種的優勢而引申的一種池化策略。常見組合策略有兩種:Cat與Add。其程式碼描述如下:

def add_avgmax_pool2d(x, output_size=1):
    x_avg = F.adaptive_avg_pool2d(x, output_size)
    x_max = F.adaptive_max_pool2d(x, output_size)
    return 0.5 * (x_avg + x_max)
def cat_avgmax_pool2d(x, output_size=1):
    x_avg = F.adaptive_avg_pool2d(x, output_size)
    x_max = F.adaptive_max_pool2d(x, output_size)
    return torch.cat([x_avg, x_max], 1)

正則化層

Transformer相關Normalization方式

Normalization Layers

BatchNorm

torch.nn.BatchNorm1d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
torch.nn.BatchNorm2d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
torch.nn.BatchNorm3d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)

引數:

num_features: 來自期望輸入的特徵數,該期望輸入的大小為batch_size × num_features [× width],和之前輸入折積層的channel位的維度數目相同
eps: 為保證數值穩定性(分母不能趨近或取0),給分母加上的值。預設為1e-5。
momentum: 動態均值和動態方差所使用的動量。預設為0.1。
affine: 布林值,當設為true,給該層新增可學習的仿射變換引數。
track_running_stats:布林值,當設為true,記錄訓練過程中的均值和方差;
# With Learnable Parameters
m = nn.BatchNorm2d(5)
# Without Learnable Parameters
m = nn.BatchNorm2d(5, affine=False)
inputs = torch.randn(20, 5, 35, 45)
output = m(inputs)

LayerNorm

torch.nn.LayerNorm(normalized_shape, eps=1e-05, elementwise_affine=True)

引數:

normalized_shape: 輸入尺寸
[× normalized_shape[0] × normalized_shape[1]×…× normalized_shape[−1]]
eps: 為保證數值穩定性(分母不能趨近或取0),給分母加上的值。預設為1e-5。
elementwise_affine: 布林值,當設為true,給該層新增可學習的仿射變換引數。

LayerNorm就是對(2, 2,4), 後面這一部分進行整個的標準化。可以理解為對整個影象進行標準化。

x_test = np.array([[[1,2,-1,1],[3,4,-2,2]],
                   [[1,2,-1,1],[3,4,-2,2]]])
x_test = torch.from_numpy(x_test).float()
m = nn.LayerNorm(normalized_shape = [2,4])
output = m(x_test)

InstanceNorm

torch.nn.InstanceNorm1d(num_features, eps=1e-05, momentum=0.1, affine=False, track_running_stats=False)
torch.nn.InstanceNorm2d(num_features, eps=1e-05, momentum=0.1, affine=False, track_running_stats=False)
torch.nn.InstanceNorm3d(num_features, eps=1e-05, momentum=0.1, affine=False, track_running_stats=False)

引數:

num_features: 來自期望輸入的特徵數,該期望輸入的大小為batch_size x num_features [x width]
eps: 為保證數值穩定性(分母不能趨近或取0),給分母加上的值。預設為1e-5。
momentum: 動態均值和動態方差所使用的動量。預設為0.1。
affine: 布林值,當設為true,給該層新增可學習的仿射變換引數。
track_running_stats:布林值,當設為true,記錄訓練過程中的均值和方差;

InstanceNorm就是對(2, 2, 4)最後這一部分進行Norm。

x_test = np.array([[[1,2,-1,1],[3,4,-2,2]],
                   [[1,2,-1,1],[3,4,-2,2]]])
x_test = torch.from_numpy(x_test).float()
m = nn.InstanceNorm1d(num_features=2)
output = m(x_test)

GroupNorm

torch.nn.GroupNorm(num_groups, num_channels, eps=1e-05, affine=True)

引數:

num_groups:需要劃分為的groups
num_features: 來自期望輸入的特徵數,該期望輸入的大小為batch_size x num_features [x width]
eps: 為保證數值穩定性(分母不能趨近或取0),給分母加上的值。預設為1e-5。
momentum: 動態均值和動態方差所使用的動量。預設為0.1。
affine: 布林值,當設為true,給該層新增可學習的仿射變換引數。

當GroupNorm中group的數量是1的時候, 是與上面的LayerNorm是等價的。

x_test = np.array([[[1,2,-1,1],[3,4,-2,2]],
                   [[1,2,-1,1],[3,4,-2,2]]])
x_test = torch.from_numpy(x_test).float()
# Separate 2 channels into 1 groups (equivalent with LayerNorm)
m = nn.GroupNorm(num_groups=1, num_channels=2, affine=False)
output = m(x_test)

當GroupNorm中num_groups的數量等於num_channel的數量,與InstanceNorm等價。

# Separate 2 channels into 2 groups (equivalent with InstanceNorm)
m = nn.GroupNorm(num_groups=2, num_channels=2, affine=False)
output = m(x_test)

啟用函數

參考資料:GELU 啟用函數

Pytorch啟用函數及優缺點比較

torch.nn.GELU

bert原始碼給出的GELU程式碼pytorch版本表示如下:

def gelu(input_tensor):
	cdf = 0.5 * (1.0 + torch.erf(input_tensor / torch.sqrt(2.0)))
	return input_tesnsor*cdf

torch.nn.ELU(alpha=1.0,inplace=False)

def elu(x,alpha=1.0,inplace=False):
    return max(0,x)+min(0,alpha∗(exp(x)−1))

α是超引數,預設為1.0

torch.nn.LeakyReLU(negative_slope=0.01,inplace=False)

def LeakyReLU(x,negative_slope=0.01,inplace=False):
    return max(0,x)+negative_slope∗min(0,x)

其中 negative_slope是超引數,控制x為負數時斜率的角度,預設為1e-2

torch.nn.PReLU(num_parameters=1,init=0.25)

def PReLU(x,num_parameters=1,init=0.25):
    return max(0,x)+init∗min(0,x)

其中a 是一個可學習的引數,當不帶引數呼叫時,即nn.PReLU(),在所有的輸入通道上使用同一個a,當帶引數呼叫時,即nn.PReLU(nChannels),在每一個通道上學習一個單獨的a。

注意:當為了獲得好的performance學習一個a時,不要使用weight decay。

num_parameters:要學習的a的個數,預設1

init:a的初始值,預設0.25

torch.nn.ReLU(inplace=False)

CNN中最常用ReLu。

def ReLU(x,inplace=False):
    return max(0,x)

torch.nn.ReLU6(inplace=False)

def ReLU6(x,inplace=False):
    return min(max(0,x),6)

torch.nn.SELU(inplace=False)

def SELU(x,inplace=False):
    alpha=1.6732632423543772848170429916717
	scale=1.0507009873554804934193349852946
    return scale∗(max(0,*x*)+min(0,alpha∗(exp(x)−1)))

torch.nn.CELU(alpha=1.0,inplace=False)

def CELU(x,alpha=1.0,inplace=False):
    return max(0,x)+min(0,alpha∗(exp(x/alpha)−1))

其中α 預設為1.0

torch.nn.Sigmoid

def Sigmoid(x):
    return 1/(np.exp(-x)+1)

torch.nn.LogSigmoid

def LogSigmoid(x):
    return np.log(1/(np.exp(-x)+1))

torch.nn.Tanh

def Tanh(x):
    return (np.exp(x)-np.exp(-x))/(np.exp(x)+np.exp(-x))

torch.nn.Tanhshrink

def Tanhshrink(x):
    return x-(np.exp(x)-np.exp(-x))/(np.exp(x)+np.exp(-x))

torch.nn.Softplus(beta=1,threshold=20)

該函數可以看作是ReLu的平滑近似。

def Softplus(x,beta=1,threshold=20):
    return np.log(1+np.exp(beta*x))/beta

torch.nn.Softshrink(lambd=0.5)

λ的值預設設定為0.5

def Softshrink(x,lambd=0.5):
    if x>lambd:return x-lambd
    elif x<-lambd:return x+lambd
    else:return 0

nn.Softmax

m = nn.Softmax(dim=1)
input = torch.randn(2, 3)
output = m(input)

參考資料

Pytorch啟用函數及優缺點比較

PyTorch快速入門教學二(線性迴歸以及logistic迴歸)

Pytorch全連線網路

pytorch系列之nn.Sequential講解

以上就是Pytorch模型定義與深度學習自查手冊的詳細內容,更多關於Pytorch深度學習模型定義的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com