日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Pytorch学习(二)—— nn模块

發布時間:2024/3/12 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Pytorch学习(二)—— nn模块 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

torch.nn

  • nn.Module
  • 常用的神經網絡相關層
  • 損失函數
  • 優化器
  • 模型初始化策略
  • nn和autograd
    • nn.functional
    • nn和autograd的關系
  • hooks簡介
  • 模型保存
  • GPU計算

Pytorch nn模塊提供了創建和訓練神經網絡的各種工具,其專門為深度學習設計,核心的數據結構是Module。Module是一個抽象的概念,既可以表示神經網絡中的某個層,也可以表示一個包含很多層的神經網絡。

nn.Module

nn.Module基類構造函數:

def __init__(self):self.training = Trueself._parameters = OrderedDict()self._buffers = OrderedDict()self._backward_hooks = OrderedDict()self._forward_hooks = OrderedDict()self._forward_pre_hooks = OrderedDict()self._state_dict_hooks = OrderedDict()self._load_state_dict_pre_hooks = OrderedDict()self._modules = OrderedDict()

其中對部分屬性的解釋如下:

  • training: 對于一些在訓練和測試階段采用策略不同的層如Dropout和BathNorm,通過training值決定前向傳播策略。
  • _parameters: 用來保存用戶直接設置的parameter。
  • _buffers: 緩存。
  • *_hooks: 存儲管理hooks函數,用來提取中間變量。
  • _modules: 子module。

實際使用中,最常見的做法是繼承nn.Module來撰寫自定義的網絡層,需要注意以下幾點:

  • 自定義層必須繼承nn.Module,并且在其構造函數中需要調用nn.Module的構造函數。
  • 必須在構造函數__init__中定義可學習參數。
  • 使用forward函數實現前向傳播過程。
  • 無須寫反向傳播函數,nn.Module能夠利用autograd自動實現反向傳播。
  • Moudle中的可學習參數可以通過named_parameters()或者parameters()返回迭代器。

借助nn.Moudle實現簡單的全連接層和多層感知機網絡:

# -*- coding: utf-8 -*- # create on 2021-06-29 # author: yangimport torch from torch import nn# 全連接層 class Linear(nn.Module):def __init__(self, in_features, out_features):super(Linear, self).__init__() # or nn.Module.__init__(self)self.w = nn.Parameter(torch.randn(in_features, out_features))self.b = nn.Parameter(torch.randn(out_features))def forward(self, x):x = x.mm(self.w)return x + self.b.expand_as(x)# 多層感知機 class Perceptron(nn.Module):def __init__(self, in_features, hidden_features, out_features):nn.Module.__init__(self)self.layer1 = Linear(in_features, hidden_features)self.layer2 = Linear(hidden_features, out_features)def forward(self, x):x = self.layer1(x)x = torch.sigmoid(x)return self.layer2(x)if __name__ == '__main__':layer = Linear(4, 3)for name, parameter in layer.named_parameters():print(name, parameter)preceptron = Perceptron(3, 4, 1)for name, parameter in preceptron.named_parameters():print(name, parameter)

常用的神經網絡相關層

nn模塊中已經封裝好了許多神經網絡相關層,包括卷積、池化、激活等,實際使用時可借助ModuleList和Sequential簡化網絡構建過程:

# Sequential # eg1: net1 = nn.Sequential() net1.add_module('conv', nn.Conv2d(3, 3, 3)) net1.add_module('batchnorm', nn.BatchNorm2d(3)) net1.add_module('relu', nn.ReLU())# eg2: net2 = nn.Sequential(nn.Conv2d(3, 3, 3),nn.BatchNorm2d(3),nn.ReLU()) # eg3: from collections import OrderedDict net3 = nn.Sequential(OrderedDict([('conv1', nn.Conv2d(3, 3, 3)),('batchnorm', nn.BatchNorm2d(3)),('relu', nn.ReLU())]))# ModelList modelist = nn.ModuleList([nn.Conv2d(3, 4), nn.BatchNorm2d(3), nn.ReLU()])

損失函數

深度學習中要用到各種各樣的損失函數,這些損失函數可以看作是一些特殊的layer,Pytorch將這些損失函數實現為nn.Module的子類。

以交叉熵損失CrossEntropyLoss為例:

# Loss Function score = torch.randn(3, 2) label = torch.Tensor([1, 0, 1]).long() criterion = nn.CrossEntropyLoss() loss = criterion(score, label)

優化器

torch.optim中封裝了許多深度學習中常用的優化方法,所有的優化方法都繼承自基類optim.Optimizer,并實現了自己的優化步驟,以最基本的優化方法——隨機梯度下降法(SGD)舉例說明:

  • 首先需要定義模型結構
  • 選擇合適的優化方法
  • 設置學習率
  • from torch import optim# Optimizer class Net(nn.Module):def __init__(self):super(Net, self).__init__()self.features = nn.Sequential(nn.Conv2d(3, 6, 5),nn.ReLU(),nn.MaxPool2d(2, 2),nn.Conv2d(6, 16, 5),nn.ReLU(),nn.MaxPool2d(2, 2))self.classifier = nn.Sequential(nn.Linear(16 * 5 * 5, 120),nn.ReLU(),nn.Linear(120, 84),nn.ReLU(),nn.Linear(84, 10))def forward(self, x):x = self.features(x)x = x.view(-1, 16 * 5 * 5)x = self.classifier(x)return xnet = Net() # 默認采用學習率為0.01 optimizer = optim.SGD(params=net.parameters(), lr=0.01) optimizer.zero_grad()input = torch.randn(1, 3, 32, 32) output = net(input) output.backward(output)# 執行優化 optimizer.step()# 為不同子網絡設置不同的學習率 optimizer = optim.SGD([{'params': net.features.parameters()},{'params': net.classifier.parameters(), 'lr': 1e-2}], lr=1e-5)

    模型初始化策略

    深度學習中參數的初始化非常重要,良好的初始化能夠讓模型更快收斂,達到更好的性能。Pytorch中nn.Module模塊參數都采取了比較合理的初始化策略,我們也可以用自定義的初始化代替系統默認的初始化。nn.init模塊專門為初始化設計,并實現了常用的初始化策略。

    借助init實現xavier高斯初始化:

    from torch.nn import initlinear = nn.Linear(3, 4) torch.manual_seed(1) init.xavier_normal_(linear.weight) print(linear.weight.data)

    nn和autograd

    nn.functional

    在介紹nn和autograd之間的關系前,先來介紹nn中另一個很常用的模塊:nn.functional。nn中實現的大多數layer在functional中都有一個與之相對應的函數。nn.functional與nn.Module的主要區別在于:nn.Module實現的layer是一個特殊的類,由class Layer(nn.Module)定義,會自動提取可學習的參數;而nn.functional中的函數更像是純函數,由def function(input) 定義。

    當某一層有可學習參數時,如Conv,BathNorm等,最好使用nn.Module;由于激活、池化等層沒有可學習的參數,因此可以使用對應的functional函數替代,二者在性能上沒有太大的差異。在模型構建中,可以搭配使用nn.Module和nn.functional:

    from torch.nn import functional as F class Net(nn.Module):def __init__(self):super(Net, self).__init__()self.conv1 = nn.Conv2d(3, 6, 5)self.conv2 = nn.Conv2d(6, 16, 5)self.fc1 = nn.Linear(16 * 5 * 5, 120)self.fc2 = nn.Linear(120, 84)self.fc3 = nn.Linear(84, 100)def forward(self, x):x = F.max_pool2d(F.relu(self.conv1(x)), 2)x = F.max_pool2d(F.relu(self.conv2(x)), 2)x = x.view(-1, 16 * 5 * 5)x = F.relu(self.fc1(x))x = F.relu(self.fc2(x))x = self.fc3(x)return x

    有可學習參數的層,也可以使用functional代替,只不過實現起來較為煩瑣,需要手動定義參數:

    class MyLinear(nn.Module):def __init__(self):super(MyLinear, self).__init__()self.weight = nn.Parameter(torch.zeros(4, 3))self.bias = nn.Parameter(torch.zeros(4))def forward(self, x):x = F.linear(x, self.weight, self.bias)return x

    nn和autograd的關系

    nn是建立在autograd之上的模塊,主要的工作是實現前向傳播。nn.Module對輸入的Tensor進行的各種操作,本質上都用到了autograd技術。

    autograd.Function和nn.Module之間的區別如下:

    • autograd.Function利用Tensor對autograd技術的擴展,為autograd實現新的運算op
    • nn.functional是autograd操作的集合,是經過封裝的函數。
    • nn.Module利用autograd,對nn的功能進行擴展,構建網絡時,使用nn.Module作為基本元,nn.Module通常包裹autograd.Function作為真正實現的部分。 例如:
      nn.ReLU = nn.functional.relu()
      nn.functional.relu()類型為Function,再往下真正完成計算的部分通常使用C++實現。
    • 如果某個操作在autograd中尚未支持,則需要利用Function手動實現對應的前向傳播反向傳播

    hooks簡介

    hooks了解的不多,簡單認為是一種獲取模型中間結果(包括前向傳播的輸出和反向傳播的梯度)的方法,前向傳播的hooks函數有如下形式:hook(module, input, output) -> None,反向傳播則具有如下形式:hook(module, input, output) -> Tensor or None,hooks函數不應修改輸入和輸出,并且在使用后應當及時刪除,避免增加運行負載。

    from torchvision import modelsmodel = models.resnet34() features = torch.Tensor()def hooks(module, input, output):features.copy_(output.data)handle = model.layer8.register_forward_hook(hooks) output = model(input) handle.remove()

    模型保存

    在Pytorch中,所有Module對象都具有state_dict()函數,返回當前Module的所有狀態數據。將這些狀態數據保存后,下次是用模型時即可利用load_state_dict()函數將狀態加載進來。

    # save model torch.save(net.state_dict(), 'net.pth')# load model net2 = Net() net2.load_state_dict(torch.load('net.pth'))

    還有另外一種保存模型的方法:

    torch.save(net, 'net_all.pth') net2 = torch.load('net_all.pth')

    目前,pytorch提供了onnx借口,可將pth模型導出為onnx模型。

    GPU計算

    將Module放在GPU上運行:

  • 將模型所有參數轉存到GPU: model = model.cuda
  • 將輸入數據放到GPU:input = input.cuda()
  • Pytorch提供了兩種方式,可在多個GPU上并行計算,二者參數十分相似,通過device_ids指定在哪些GPU上進行優化,output_device指定輸出到那個GPU。不同之處在于nn.parallel.data_parallel直接利用多GPU并行計算得出結果,nn.DataParallel返回一個新的module,能夠自動在多GPU上進行并行加速。

    # GPU 并行計算 '''DataParallel并行的方式是將輸入一個batch的數據均分成多份,分別送到對應的GPU進行計算,然后將各個GPU得到的梯度相加。與Module相關的所有數據也會以淺拷貝的方式復制多份 ''' # method 1 new_net = nn.DataParallel(net, device_ids=[0, 1])# method 2 output = nn.parallel.data_parallel(net, input, device_ids=[0, 1])

    總結

    以上是生活随笔為你收集整理的Pytorch学习(二)—— nn模块的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。