動手深度學習4-線性迴歸的pytorch簡潔實現

本節利用pytorch中的模塊,生成一個更加簡潔的代碼來實現一樣的功能python

導入一樣導入以前的包或者模塊
%matplotlib inline
import torch
from IPython import display
from matplotlib import pyplot as plt
import numpy as np
import random
生成數據集
num_inputs =2   ## 特徵數量
num_examples=1000   # 樣本量
true_w=[2,-3.4]  # 真實的權重係數
true_b=4.2  # 真實的偏置量
features = torch.randn(num_examples,num_inputs,dtype=torch.float32)   # 生成隨機的特徵
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.float32)  #在標籤上加上隨機噪聲項
經過pytorch讀取數據

pytotch 提供了data包來讀取數據。因爲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)
for X,y in data_iter:
    print(X,y)
    break
tensor([[ 1.9769,  1.5576],
        [-0.4743,  0.8653],
        [ 0.2641,  1.9682],
        [-2.3385,  0.3753],
        [ 0.3972, -0.6515],
        [ 1.1317, -0.2586],
        [ 1.6896,  1.0102],
        [-0.6803,  0.7734],
        [-0.3525, -0.7764],
        [ 0.3199,  0.9397]]) tensor([ 2.8727,  0.3198, -1.9711, -1.7576,  7.2187,  7.3517,  4.1360,  0.2171,
         6.1193,  1.6434])
定義模型
  • 從上一節從零開始的實現中,咱們須要定義模型參數,並使用他們一步步描述模型是怎樣計算的。當模型結果變得複雜時,這些步驟變得更加繁瑣。其實pytorch提供了大量的預約義的層,這使我, 只須要關注使用哪些層來構造模型。下面介紹pytorch更加簡潔的定義線性迴歸。網絡

  • 首先導入torch.nn 模塊,實際上,nn是neural network的縮寫。該模塊定義了大量神經網絡的層,以前使用過的autograd,而nn就是利用autograd來定義模型。
  • nn的核心數據結構是Module,它是一個抽象概念,既能夠表示神經網絡中的某個層,也能夠表示包含不少層的神經網絡。
  • 在實際使用中,經過會繼承torch.Module,撰寫本身的網絡/層。一個nn.Module實例應該包含一些曾以及返回輸出的前向傳播(forward)方法.數據結構

from torch import nn

class LinearNet(nn.Module):
    def __init__(self,n_features):
        super(LinearNet,self).__init__()
        self.linear = nn.Linear(n_features,1)   # 這裏的1是指out_features
    def forward(self,x):
        y = self.linear(x)
        return y
net = LinearNet(num_inputs)  # 輸入特維度爲2,輸出結果維度爲1
print(net)
LinearNet(
  (linear): Linear(in_features=2, out_features=1, bias=True)
)

事實上,咱們還能夠用nn.Sequential來更加方便的搭建網絡,Sequential是一個有序的容器,網絡層將按照在傳入的Sequential的順序依次被添加到計算圖中。dom

# 寫法1
net= nn.Sequential(nn.Linear(num_inputs,1)
                  # 此處還能夠傳入其餘的層
                  )
# 寫法2
net = nn.Sequential()
net.add_module('linear',nn.Linear(num_inputs,1))
# net.add_module .....


# 寫法3

from collections import OrderedDict

net = nn.Sequential(
OrderedDict([
    ('linear',nn.Linear(num_inputs,1))
    # 其餘的層
    
])
)

print(net)
print(net[0])
Sequential(
  (linear): Linear(in_features=2, out_features=1, bias=True)
)
Linear(in_features=2, out_features=1, bias=True)
for param in net.parameters():
        print(param)
Parameter containing:
tensor([[-0.4229, -0.0282]], requires_grad=True)
Parameter containing:
tensor([0.0852], requires_grad=True)

做爲一個單層神經網絡,線性迴歸輸出層中的神經元和輸入層中各輸入完成全鏈接,所以線性迴歸的輸出層有叫做全鏈接層函數

初始化模型

在使用net前,咱們須要初始化模型參數,如線性迴歸模型中的權重和誤差。pytorch在init模型中提供了多種參數初始化方法。這裏的init是initializer的縮寫形式。咱們經過init.normal_將權重參數每一個元素初始化爲隨機採樣的均值爲0,標準差爲0.01的正態分佈。誤差會初始化爲0工具

from torch.nn import init
init.normal_(net[0].weight,mean=0,std=0.01)
init.constant_(net[0].bias,val=0)
# 該寫法與後面的三種寫法才能夠使用,若是使用一開始的寫法,net[0].weight 因改成net.linear.weight bias亦然。
#由於net[0]這樣的寫法只有當net是ModuleList或者Sequential實例時才能夠。
#
Parameter containing:
tensor([0.], requires_grad=True)
定義損失函數
# pytorch在nn模塊中提供了各類損失函數,這些損失函數能夠看作是一種特殊的層,pytorch也將這些損失函數實現爲nn.Module的子類。這裏咱們使用
# pytorch提供的均方偏差損失做爲模型的損失函數
loss = nn.MSELoss()
定義優化算法

一樣咱們也無需本身實現小批量隨機梯度降低算法,torch.optim 模塊提供了不少經常使用的優化算法,SGD,Adam,RMSPorp等。下面咱們建立了一個用於優化net全部參數的優化器實例,並指定學習率爲0.03的小批量隨機梯度降低(SGD)爲優化算法。學習

import torch.optim as optim
optimizer = optim.SGD(net.parameters(),lr=0.03)
print(optimizer)
SGD (
Parameter Group 0
    dampening: 0
    lr: 0.03
    momentum: 0
    nesterov: False
    weight_decay: 0
)

咱們能夠爲不一樣的子網絡設置不一樣的學習率,這在finetune時常常用到。優化

optimizer = optim.SGD(
[
    {'params':net.subset1.parameters()},  # lr 默認用最外層的學習率
    {'params':net.subset2.parameters(),'lr':0.01}
],
    lr= 0.03
)
訓練模型

在使用pytorch訓練模型時,咱們經過調用optim實例的step函數來迭代模型參數。按照小批量隨機梯度降低的定義,咱們在step函數中指明批量大小
從而而批量中中樣本梯度求平均ui

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()))
epoch 1 loss: 0.000286
epoch 2 loss: 0.000199
epoch 3 loss: 0.000072

下面咱們分別比較學到的模型參數和真實的模型參數。咱們從net得到的須要的層,並訪問其權重(weight)和誤差(bias)。學到的參數和真實的參數很接近

dense=net[0]
print(true_w,dense.weight)
print(true_b,dense.bias)
[2, -3.4] Parameter containing:
tensor([[ 2.0010, -3.3996]], requires_grad=True)
4.2 Parameter containing:
tensor([4.2005], requires_grad=True)
小結
  • 使用pytorch能夠更加簡潔的實現模型
  • torch.utils.data 模塊提供了有關數據處理的工具,torch.nn 模塊定義了大量神經網絡的層,torch.nn.init 模塊定義了各類初始化的方法,torch.optim模塊提供了模型參數初始化的各類方法
相關文章
相關標籤/搜索