<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 4.2 模型參數的訪問、初始化和共享 在3.3節(線性回歸的簡潔實現)中,我們通過`init`模塊來初始化模型的參數。我們也介紹了訪問模型參數的簡單方法。本節將深入講解如何訪問和初始化模型參數,以及如何在多個層之間共享同一份模型參數。 我們先定義一個與上一節中相同的含單隱藏層的多層感知機。我們依然使用默認方式初始化它的參數,并做一次前向計算。與之前不同的是,在這里我們從`nn`中導入了`init`模塊,它包含了多種模型初始化方法。 ``` python import torch from torch import nn from torch.nn import init net = nn.Sequential(nn.Linear(4, 3), nn.ReLU(), nn.Linear(3, 1)) # pytorch已進行默認初始化 print(net) X = torch.rand(2, 4) Y = net(X).sum() ``` 輸出: ``` Sequential( (0): Linear(in_features=4, out_features=3, bias=True) (1): ReLU() (2): Linear(in_features=3, out_features=1, bias=True) ) ``` ## 4.2.1 訪問模型參數 回憶一下上一節中提到的`Sequential`類與`Module`類的繼承關系。對于`Sequential`實例中含模型參數的層,我們可以通過`Module`類的`parameters()`或者`named_parameters`方法來訪問所有參數(以迭代器的形式返回),后者除了返回參數`Tensor`外還會返回其名字。下面,訪問多層感知機`net`的所有參數: ``` python print(type(net.named_parameters())) for name, param in net.named_parameters(): print(name, param.size()) ``` 輸出: ``` <class 'generator'> 0.weight torch.Size([3, 4]) 0.bias torch.Size([3]) 2.weight torch.Size([1, 3]) 2.bias torch.Size([1]) ``` 可見返回的名字自動加上了層數的索引作為前綴。 我們再來訪問`net`中單層的參數。對于使用`Sequential`類構造的神經網絡,我們可以通過方括號`[]`來訪問網絡的任一層。索引0表示隱藏層為`Sequential`實例最先添加的層。 ``` python for name, param in net[0].named_parameters(): print(name, param.size(), type(param)) ``` 輸出: ``` weight torch.Size([3, 4]) <class 'torch.nn.parameter.Parameter'> bias torch.Size([3]) <class 'torch.nn.parameter.Parameter'> ``` 因為這里是單層的所以沒有了層數索引的前綴。另外返回的`param`的類型為`torch.nn.parameter.Parameter`,其實這是`Tensor`的子類,和`Tensor`不同的是如果一個`Tensor`是`Parameter`,那么它會自動被添加到模型的參數列表里,來看下面這個例子。 ``` python class MyModel(nn.Module): def __init__(self, **kwargs): super(MyModel, self).__init__(**kwargs) self.weight1 = nn.Parameter(torch.rand(20, 20)) self.weight2 = torch.rand(20, 20) def forward(self, x): pass n = MyModel() for name, param in n.named_parameters(): print(name) ``` 輸出: ``` weight1 ``` 上面的代碼中`weight1`在參數列表中但是`weight2`卻沒在參數列表中。 因為`Parameter`是`Tensor`,即`Tensor`擁有的屬性它都有,比如可以根據`data`來訪問參數數值,用`grad`來訪問參數梯度。 ``` python weight_0 = list(net[0].parameters())[0] print(weight_0.data) print(weight_0.grad) # 反向傳播前梯度為None Y.backward() print(weight_0.grad) ``` 輸出: ``` tensor([[ 0.2719, -0.0898, -0.2462, 0.0655], [-0.4669, -0.2703, 0.3230, 0.2067], [-0.2708, 0.1171, -0.0995, 0.3913]]) None tensor([[-0.2281, -0.0653, -0.1646, -0.2569], [-0.1916, -0.0549, -0.1382, -0.2158], [ 0.0000, 0.0000, 0.0000, 0.0000]]) ``` ## 4.2.2 初始化模型參數 我們在3.15節(數值穩定性和模型初始化)中提到了PyTorch中`nn.Module`的模塊參數都采取了較為合理的初始化策略(不同類型的layer具體采樣的哪一種初始化方法的可參考[源代碼](https://github.com/pytorch/pytorch/tree/master/torch/nn/modules))。但我們經常需要使用其他方法來初始化權重。PyTorch的`init`模塊里提供了多種預設的初始化方法。在下面的例子中,我們將權重參數初始化成均值為0、標準差為0.01的正態分布隨機數,并依然將偏差參數清零。 ``` python for name, param in net.named_parameters(): if 'weight' in name: init.normal_(param, mean=0, std=0.01) print(name, param.data) ``` 輸出: ``` 0.weight tensor([[ 0.0030, 0.0094, 0.0070, -0.0010], [ 0.0001, 0.0039, 0.0105, -0.0126], [ 0.0105, -0.0135, -0.0047, -0.0006]]) 2.weight tensor([[-0.0074, 0.0051, 0.0066]]) ``` 下面使用常數來初始化權重參數。 ``` python for name, param in net.named_parameters(): if 'bias' in name: init.constant_(param, val=0) print(name, param.data) ``` 輸出: ``` 0.bias tensor([0., 0., 0.]) 2.bias tensor([0.]) ``` 如果只想對某個特定參數進行初始化,我們可以調用`Parameter`類的`initialize`函數,它與`Block`類提供的`initialize`函數的使用方法一致。下例中我們對隱藏層的權重使用Xavier隨機初始化方法。 ## 4.2.3 自定義初始化方法 有時候我們需要的初始化方法并沒有在`init`模塊中提供。這時,可以實現一個初始化方法,從而能夠像使用其他初始化方法那樣使用它。在這之前我們先來看看PyTorch是怎么實現這些初始化方法的,例如`torch.nn.init.normal_`: ``` python def normal_(tensor, mean=0, std=1): with torch.no_grad(): return tensor.normal_(mean, std) ``` 可以看到這就是一個inplace改變`Tensor`值的函數,而且這個過程是不記錄梯度的。 類似的我們來實現一個自定義的初始化方法。在下面的例子里,我們令權重有一半概率初始化為0,有另一半概率初始化為`$ [-10,-5] $`和`$ [5,10] $`兩個區間里均勻分布的隨機數。 ``` python def init_weight_(tensor): with torch.no_grad(): tensor.uniform_(-10, 10) tensor *= (tensor.abs() >= 5).float() for name, param in net.named_parameters(): if 'weight' in name: init_weight_(param) print(name, param.data) ``` 輸出: ``` 0.weight tensor([[ 7.0403, 0.0000, -9.4569, 7.0111], [-0.0000, -0.0000, 0.0000, 0.0000], [ 9.8063, -0.0000, 0.0000, -9.7993]]) 2.weight tensor([[-5.8198, 7.7558, -5.0293]]) ``` 此外,參考2.3.2節,我們還可以通過改變這些參數的`data`來改寫模型參數值同時不會影響梯度: ``` python for name, param in net.named_parameters(): if 'bias' in name: param.data += 1 print(name, param.data) ``` 輸出: ``` 0.bias tensor([1., 1., 1.]) 2.bias tensor([1.]) ``` ## 4.2.4 共享模型參數 在有些情況下,我們希望在多個層之間共享模型參數。4.1.3節提到了如何共享模型參數: `Module`類的`forward`函數里多次調用同一個層。此外,如果我們傳入`Sequential`的模塊是同一個`Module`實例的話參數也是共享的,下面來看一個例子: ``` python linear = nn.Linear(1, 1, bias=False) net = nn.Sequential(linear, linear) print(net) for name, param in net.named_parameters(): init.constant_(param, val=3) print(name, param.data) ``` 輸出: ``` Sequential( (0): Linear(in_features=1, out_features=1, bias=False) (1): Linear(in_features=1, out_features=1, bias=False) ) 0.weight tensor([[3.]]) ``` 在內存中,這兩個線性層其實一個對象: ``` python print(id(net[0]) == id(net[1])) print(id(net[0].weight) == id(net[1].weight)) ``` 輸出: ``` True True ``` 因為模型參數里包含了梯度,所以在反向傳播計算時,這些共享的參數的梯度是累加的: ``` python x = torch.ones(1, 1) y = net(x).sum() print(y) y.backward() print(net[0].weight.grad) # 單次梯度是3,兩次所以就是6 ``` 輸出: ``` tensor(9., grad_fn=<SumBackward0>) tensor([[6.]]) ``` ## 小結 * 有多種方法來訪問、初始化和共享模型參數。 * 可以自定義初始化方法。 ----------- > 注:本節與原書此節有一些不同,[原書傳送門](https://zh.d2l.ai/chapter_deep-learning-computation/parameters.html)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看