『PyTorch』第四彈_通過LeNet初識pytorch神經網絡_上


總結一下相關概念:

  • torch.Tensor - 一個近似多維數組的數據結構
  • autograd.Variable - 改變Tensor並且記錄下來操作的歷史記錄。和Tensor擁有相同的API,以及backward()的一些API。同時包含着和張量相關的梯度
  • nn.Module - 神經網絡模塊,便捷的數據封裝,能夠將運算移往GPU,還包括一些輸入輸出的東西
  • nn.Parameter - 一種變量(Variable),當將任何值賦予Module時自動注冊為一個參數
  • autograd.Function - 實現了使用自動求導方法的前饋和后饋的定義。每個Variable的操作都會生成至少一個獨立的Function節點,與生成了Variable的函數相連之后記錄下操作歷史

導入庫:

# Author : Hellcat
# Time   : 2018/2/10

import torch as t
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
from torch.autograd import Variable

 torch.nn:網絡層

torch.nn.functional:激活函數、池化函數歸於此模塊

pytorch中的網絡層是class,而tensorflow

print(t.nn.Conv2d)
<class 'torch.nn.modules.conv.Conv2d'>
print(tf.nn.conv2d)
<function conv2d at 0x000001A33CC44510>

 

網絡主體:

net網絡要使用class並繼承父類才行,因而有一些自帶的方法

 net.parameters():返回全部的參數值,迭代器

net.named_parameters():返回參數名稱和值,迭代器

net.參數名:就是參數變量,Variable,可以直接查看data和grad等等

 

class Net(nn.Module):
    def __init__(self):
        # nn.Module子類的函數必須在構造函數中執行父類的構造函數
        # 等價於nn.Model.__init__(self)
        super(Net,self).__init__()

        # 輸入1通道,輸出6通道,卷積核5*5
        self.conv1 = nn.Conv2d(1, 6, 5)
        # 定義卷積層:輸入6張特征圖,輸出16張特征圖,卷積核5x5
        self.conv2 = nn.Conv2d(6,16,5)
        # 定義全連接層:線性連接(y = Wx + b),16*5*5個節點連接到120個節點上
        self.fc1 = nn.Linear(16*5*5,120)
        # 定義全連接層:線性連接(y = Wx + b),120個節點連接到84個節點上
        self.fc2 = nn.Linear(120,84)
        # 定義全連接層:線性連接(y = Wx + b),84個節點連接到10個節點上
        self.fc3 = nn.Linear(84,10)

    # 定義向前傳播函數,並自動生成向后傳播函數(autograd)
    def forward(self,x):
        # 輸入x->conv1->relu->2x2窗口的最大池化->更新到x
        x = F.max_pool2d(F.relu(self.conv1(x)),(2,2))
        # 輸入x->conv2->relu->2x2窗口的最大池化->更新到x
        x = F.max_pool2d(F.relu(self.conv2(x)),2)
        # view函數將張量x變形成一維向量形式,總特征數不變,為全連接層做准備
        x = x.view(x.size()[0], -1)
        # 輸入x->fc1->relu,更新到x
        x = F.relu(self.fc1(x))
        # 輸入x->fc2->relu,更新到x
        x = F.relu(self.fc2(x))
        # 輸入x->fc3,更新到x
        x = self.fc3(x)
        return x


if __name__ == "__main__":

    net = Net()

 

展示網絡參數:

# #########查看參數#########
    print(net)
    """
    Net(
    (conv1): Conv2d (1, 6, kernel_size=(5, 5), stride=(1, 1))
    (conv2): Conv2d (6, 16, kernel_size=(5, 5), stride=(1, 1))
    (fc1): Linear(in_features=400, out_features=120)
    (fc2): Linear(in_features=120, out_features=84)
    (fc3): Linear(in_features=84, out_features=10)
    )
    """

    # 返回參數值:順序和下面的named一致
    params = list(net.parameters())
    print(len(params))
    """
    10
    """

    # net.named_parameters(): ((參數名稱,參數屬性),……)
    for name, parameters in net.named_parameters():
        print(name, ":", parameters.size())
        """
        conv1.weight : torch.Size([6, 1, 5, 5])
        conv1.bias : torch.Size([6])
        conv2.weight : torch.Size([16, 6, 5, 5])
        conv2.bias : torch.Size([16])
        fc1.weight : torch.Size([120, 400])
        fc1.bias : torch.Size([120])
        fc2.weight : torch.Size([84, 120])
        fc2.bias : torch.Size([84])
        fc3.weight : torch.Size([10, 84])
        fc3.bias : torch.Size([10])
        """

 

模擬單次向前&向后傳播:

# #########網絡傳播過程模擬#########
    # 輸入如果沒有batch數,則少一維度,Tensor,unsqueeze()可以為張量擴維
    input_ = Variable(t.randn(1, 1, 32, 32))
    out = net(input_)
    print(out.size())
    """
    torch.Size([1, 10])
    """
    # net.zero_grad()
    # 輸出值為10個標量(一個向量),所以需要指定每個標量梯度的權重
    # out.backward(t.ones(1,10))

注意: torch.nn 只接受小批量的數據

整個torch.nn包只接受那種小批量樣本的數據,而非單個樣本。 例如,nn.Conv2d能夠結構一個四維的TensornSamples x nChannels x Height x Width。

如果你拿的是單個樣本,使用input.unsqueeze(0)來加一個假維度就可以了

維度是[batch,channel,height,width]。

 

Loss函數構建

 # #########Loss設計#########
    target = Variable(t.arange(0,10))
    # Loss需要先實例化,然后是callable的實例
    loss_fn = nn.MSELoss()  # 均方誤差
    loss = loss_fn(out, target)
    print(loss)

    net.zero_grad()
    print("反向傳播之前:", net.conv1.bias.grad)
    loss.backward()
    print("反向傳播之后:", net.conv1.bias.grad)

反向傳播之前: None


反向傳播之后: Variable containing:
        -0.1330
        -0.0888
        -0.0101
        -0.0186
         0.0462
         0.0317
       [torch.FloatTensor of size 6]

 

優化器構建

# #########優化器設計#########
    print(net.parameters())
    """
    <generator object Module.parameters at 0x0000021B525BE888>
    """
    # 初始化優化器
    optimizer = optim.SGD(net.parameters(), lr=0.01)

    optimizer.zero_grad()  # 效果等同net.zero_grad()

    output = net(input_)
    loss = loss_fn(output, target)

    loss.backward()
    print("反向傳播之前:", net.conv1.bias.data)
    optimizer.step()
    print("反向傳播之后:", net.conv1.bias.data)

 反向傳播之前:
    -0.1702
     0.1192
     0.1349
     0.1307
    -0.0141
    -0.0558
  [torch.FloatTensor of size 6]


反向傳播之后:
    -0.1689
     0.1201
     0.1350
     0.1309
    -0.0146
    -0.0561
  [torch.FloatTensor of size 6]

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM