3.3 線性迴歸的簡潔實現 ---動手學深度學習——pytorch1.10

學了本文你能學到什麼?僅供學習,如有疑問,請留言。。。

注:紅色是小結,     紫色是重點,能像被課文一樣背誦,初次系統性的學習,請多多指點

 

目錄

 

3.3 線性迴歸的簡潔實現

3.3.1 生成數據集

3.3.2 讀取數據

 3.3.3 定義模型

3.3.4 初始化模型參數

3.3.5 定義損失函數

3.3.6 定義優化算法

3.3.7 訓練模型

 


 

3.3 線性迴歸的簡潔實現
 

小結
使用PyTorch可以更簡潔地實現模型。
torch.utils.data模塊提供了有關數據處理的工具,
torch.nn模塊定義了大量神經網絡的層,
torch.nn.init模塊定義了各種初始化方法,
torch.optim模塊提供了很多常用的優化算法。


3.3.1 生成數據集

import torch
import numpy as np

#features是訓練數據特徵,labels是標籤。
num_inputs = 2
num_examples = 1000
true_w = [2, -3.4]
true_b = 4.2
features = torch.tensor(np.random.normal(0, 1, (num_examples, num_inputs)), dtype=torch.float)
labels = true_w[0] * features[:, 0] + true_w[1] * features[:, 1] + true_b
labels += torch.tensor(np.random.normal(0, 0.01, size=labels.size()), dtype=torch.float)

 

#3.3.2 讀取數據


# PyTorch提供了data包來讀取數據。由於data常用作變量名,我們將導入的data模塊用Data代替。
# 在每一次迭代中,我們將隨機讀取包含10個數據樣本的小批量。
import torch.utils.data as Data

batch_size = 10
# 將訓練數據的特徵和標籤組合
dataset = Data.TensorDataset(features, labels)
# 隨機讀取小批量
data_iter = Data.DataLoader(dataset, batch_size, shuffle=True)

# 3.3.3 定義模型


PyTorch提供了大量預定義的層,這使我們只需關注使用哪些層來構造模型。
下面將介紹如何使用PyTorch更簡潔地定義線性迴歸。

導入torch.nn模塊。實際上,“nn”是neural networks(神經網絡)的縮寫。顧名思義,該模塊定義了大量神經網絡的層
在實際使用中,最常見的做法是繼承nn.Module,撰寫自己的網絡/層。

一個nn.Module實例應該包含一些層以及返回輸出的前向傳播(forward)方法。
下面先來看看如何用nn.Module實現一個線性迴歸模型。
"""
import torch.nn as nn

class LinearNet(nn.Module):
    def __init__(self, n_feature):
        super(LinearNet, self).__init__()
        self.linear = nn.Linear(n_feature, 1)
    # forward 定義前向傳播
    def forward(self, x):
        y = self.linear(x)
        return y

net = LinearNet(num_inputs)
# print(net) # 使用print可以打印出網絡的結構
"""
LinearNet(
  (linear): Linear(in_features=2, out_features=1, bias=True)
)

nn.Sequential來更加方便地搭建網絡,
Sequential是一個有序的容器,網絡層將按照在傳入Sequential的順序依次被添加到計算圖中。

# 寫法一
net = nn.Sequential(
    nn.Linear(num_inputs, 1)
    # 此處還可以傳入其他層
    )
# 寫法二
net = nn.Sequential()
net.add_module('linear', nn.Linear(num_inputs, 1))
# net.add_module ......
# 寫法三
from collections import OrderedDict
net = nn.Sequential(OrderedDict([
          ('linear', nn.Linear(num_inputs, 1))
          # ......
        ]))

print(net)
print(net[0])

可以通過net.parameters()來查看模型所有的可學習參數,此函數將返回一個生成器。
for param in net.parameters():
    print(param)

"""
# 注意:torch.nn僅支持輸入一個batch的樣本不支持單個樣本輸入,如果只有單個樣本,可使用input.unsqueeze(0)來添加一維。

#3.3.4 初始化模型參數

 


"""
在使用net前,我們需要初始化模型參數,如線性迴歸模型中的權重和偏差。
PyTorch在init模塊中提供了多種參數初始化方法。這裏的init是initializer的縮寫形式。
我們通過init.normal_將權重參數每個元素初始化爲隨機採樣於均值爲0、標準差爲0.01的正態分佈。偏差會初始化爲零。
"""
from torch.nn import init
# init.normal_(net[0].weight, mean=0, std=0.01)
init.normal_(net.linear.weight, mean=0, std=0.01)
# init.constant_(net[0].bias, val=0)
init.constant_(net.linear.bias, val=0)

#3.3.5 定義損失函數


"""
PyTorch在nn模塊中提供了各種損失函數,這些損失函數可看作是一種特殊的層,PyTorch也將這些損失函數實現爲nn.Module的子類。
我們現在使用它提供的均方誤差損失作爲模型的損失函數。
"""
loss = nn.MSELoss()

 

#3.3.6 定義優化算法

 

"""

同樣,我們也無須自己實現小批量隨機梯度下降算法。
torch.optim模塊提供了很多常用的優化算法比如SGD、Adam和RMSProp等。
下面我們創建一個用於優化net所有參數的優化器實例,並指定學習率爲0.03的小批量隨機梯度下降(SGD)爲優化算法。

"""
import  torch.optim as optim

optimizer = optim.SGD(net.parameters(), lr=0.03)
print(optimizer)

"""
我們還可以爲不同子網絡設置不同的學習率,這在finetune時經常用到。例:
optimizer =optim.SGD([
                # 如果對某個參數不指定學習率,就使用最外層的默認學習率
                {'params': net.subnet1.parameters()}, # lr=0.03
                {'params': net.subnet2.parameters(), 'lr': 0.01}
            ], lr=0.03)

有時候我們不想讓學習率固定成一個常數,那如何調整學習率呢?
主要有兩種做法。一種是修改optimizer.param_groups中對應的學習率,
另一種是更簡單也是較爲推薦的做法——新建優化器,
由於optimizer十分輕量級,構建開銷很小,故而可以構建新的optimizer。

但是後者對於使用動量的優化器(如Adam),會丟失動量等狀態信息,可能會造成損失函數的收斂出現震盪等情況。

# 調整學習率
for param_group in optimizer.param_groups:
    param_group['lr'] *= 0.1 # 學習率爲之前的0.1倍
"""

#3.3.7 訓練模型

 

"""
在使用Gluon訓練模型時,我們通過調用optim實例的step函數來迭代模型參數。
按照小批量隨機梯度下降的定義,我們在step函數中指明批量大小,從而對批量中樣本梯度求平均。
"""
num_epochs = 3
for epoch in range(1, num_epochs + 1):
    for X, y in data_iter:
        output = net(X)
        l = loss(output, y.view(-1, 1))
        optimizer.zero_grad() # 梯度清零,等價於net.zero_grad()
        l.backward()
        optimizer.step()
    print('epoch %d, loss: %f' % (epoch, l.item()))
"""
下面我們分別比較學到的模型參數和真實的模型參數。我們從net獲得需要的層,並訪問其權重(weight)和偏差(bias)
學到的參數和真實的參數很接近。
"""
dense = net.linear
print(true_w, dense.weight)
print(true_b, dense.bias)

 

本文參考鏈接:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章