1. 程式人生 > 其它 >線性迴歸的簡潔實現

線性迴歸的簡潔實現

前言:

簡潔實現:使用深度學習開源框架達到目的

一、生成資料集

#線性迴歸的簡潔實現就是使用pytorch內建的一些模組來實現
import numpy as np
import torch
from torch.utils import data #從torch.utils中匯入關於data處理的模組
from d2l import torch as d2l
true_w = torch.tensor([2, -3.4])#構造w
true_b = 4.2#構造b
features, labels = d2l.synthetic_data(true_w, true_b, 1000)#synthetic_data生成資料集函式

在這裡,我們通過true_w和true_b生成有1000個數據的資料集(也就是說,)

二、讀取資料集

1、呼叫框架中現有的API來讀取資料

2、將featureslabels作為API的引數傳遞,並在例項化資料迭代器物件時指定batch_size

# is_train=True:表示希望資料迭代器物件在每個迭代週期內打亂資料

# data_arrays:表示可以傳入多個矩陣,即是將features和labels作為引數,data_arrays相當於一個API
def load_array(data_arrays, batch_size, is_train=True):  #@save
    """構造一個PyTorch資料迭代器。"""
    #TensorDateset:把輸入的兩類資料進行一一對應;
    #DataLoader:重新排序
    dataset = data.TensorDataset(*data_arrays)#*可以對list解開入參,因為features和labels作為API引數傳遞
    
    return data.DataLoader(dataset, batch_size, shuffle=is_train)#每次隨機挑選batch_size個樣本,shuffle意思是要不要打亂順序
# 讀取10個樣本

batch_size = 10
data_iter = load_array((features, labels), batch_size)
# 不能直接從data_iter中獲得資料

next(iter(data_iter))#將data_iter用iter()函式轉為迭代器,再使用next()函式從迭代器中獲取資料

#輸出結果

[tensor([[-0.5143, -1.0371],
         [ 0.0254, -0.1204],
         [ 0.1787,  0.2586],
         [-0.6284,  0.7571],
         [-0.3744,  0.5989],
         [ 0.1679, -1.5357],
         [-0.6135, -1.2744],
         [ 0.3798, -0.8941],
         [-1.6691, -0.6110],
         [ 0.0555, -0.3930]]),
 tensor([[6.7026],
         [4.6815],
         [3.6661],
         [0.3918],
         [1.4045],
         [9.7481],
         [7.2834],
         [7.9958],
         [2.9436],
         [5.6409]])]

  

三、定義模型

1、使用框架的預定義好的層,即我們只需關注使用哪些層來構造模型,而不必關注層的實現細節

2、實現步驟:

首先定義一個模型變數net,它是一個Sequential類的例項

Sequential類為串聯在一起的多個層定義了一個容器。當給定輸入資料,Sequential例項將資料傳入到第一層,然後將第一層的輸出作為第二層的輸入,依此類推

3、Pytorch中,全連線層在Linear類中定義。Linear中,第一個變數為輸入特徵形狀,第二個變數為輸出特徵形狀

# `nn` 是神經網路的縮寫
from torch import nn

# Linear中,第一個指定輸入特徵數,第二個指定輸出數
net = nn.Sequential(nn.Linear(2, 1))#輸入維度是2,輸出維度是1;
#nn.Linear(2,1)可以理解為線性迴歸就是簡單的單層神經網路,將其放在一個Sequential中

  

四、初始化模型引數

1、在使用net前,需要初始化模型引數,如在此需要初始化權重與偏置

2、在這裡,我們指定每個權重引數應該從均值為0、標準差為0.01的正態分佈中隨機取樣,偏置引數將初始化為零

# net[0]:表示使用網路中的第一個圖層


# 權重引數從均值為0,標準差為0.01的正態分佈中隨機取樣
print(net[0].weight.data)
net[0].weight.data.normal_(0, 0.01)#normal_(0, 0.01)的意思是使用正態分佈替換data的值,均值為0、標準差為0.01
print(net[0].weight.data)

#偏置引數初始化為0
print(net[0].bias.data)
net[0].bias.data.fill_(0)#bias偏差
print(net[0].bias.data)

#輸出函式

tensor([[ 0.0080, -0.0021]])
tensor([[-0.0073,  0.0137]])
tensor([0.])
tensor([0.])

  

五、定義損失函式

1、計算均方誤差使用的是MSELoss類,也稱為平方L2範數

2、預設情況下,他返回所有樣本損失的平均值

# 平方L2範數,返回所有樣本損失的平均值
loss = nn.MSELoss()

  

六、定義優化演算法——梯度下降優化演算法

# net.parameters()常用於做模組引數
# SGD隨機梯度下降求解


trainer = torch.optim.SGD(net.parameters(), lr=0.03)#net.parameters()包括w和b

  

七、訓練

1、在每個迭代週期裡,我們將完整遍歷一次資料集

2、在每個迭代週期裡,會不停地從中獲取一個小批量的輸入和相應的標籤,對於每一個小批量,操作如下:

  • 通過呼叫net(X)生成預測並計算損失l(正向傳播)。
  • 通過進行反向傳播來計算梯度。
  • 通過呼叫優化器來更新模型引數。
num_epochs = 3#迭代三個週期
for epoch in range(num_epochs):
    for X, y in data_iter:
        l = loss(net(X), y)#loss是損失函式
        
        trainer.zero_grad()#trainer優化器,先把梯度清零
        l.backward()#等價於l.sum().backward()——求和之後算梯度
        trainer.step()#呼叫優化演算法進行模型更新
    
    l = loss(net(features), labels)
    print(f'epoch {epoch + 1}, loss {l:f}')


#輸出結果

epoch 1, loss 0.000215
epoch 2, loss 0.000107
epoch 3, loss 0.000108

3、比較生成資料集的真實引數和通過有限資料訓練獲得的模型引數

w = net[0].weight.data

print('w的估計誤差:', true_w - w.reshape(true_w.shape))
b = net[0].bias.data
print('b的估計誤差:', true_b - b)

#輸出結果

w的估計誤差: tensor([ 5.0187e-05, -1.9765e-04])
b的估計誤差: tensor([0.0008])