首頁 > 軟體

Python反向傳播實現線性迴歸步驟詳細講解

2022-10-20 14:02:53

1. 匯入包

我們這次的任務是隨機生成一些離散的點,然後用直線(y = w *x + b )去擬合

首先看一下我們需要匯入的包有

torch 包為我們生成張量,可以使用反向傳播

matplotlib.pyplot 包幫助我們繪製曲線,實現視覺化

2. 生成資料

這裡我們通過rand隨機生成資料,因為生成的資料在0~1之間,這裡我們擴大10倍。

我們設定的batch_size,也就是資料的個數為20個,所以這裡會產生維度是(20,1)個訓練樣本

我們假設大概的迴歸是 y = 2 * x + 3 的,為了保證損失不一直為0 ,這裡我們新增一點噪音

最後返回x作為輸入,y作為真實值label

rand [0,1]均勻分佈

如果想要每次產生的亂數是一樣的,可以在程式碼的前面設定一下亂數種子

3. 訓練資料

首先,我們要建立的模型是線性的y = w * x + b ,所以我們需要先初始化w ,b

使用randn 標準正態分佈隨機初始化權重w,將偏置b初始化為0

為什麼將權重w隨機初始化?

  • 首先,為了抑制過擬合,提高模型的泛化能力,我們可以採用權重衰減來抑制權重w的大小。因為權重過大,對應的輸入x的特徵就越重要,但是如果對應x是噪音的話,那麼系統就會陷入過擬閤中。所以我們希望得到的模型曲線是一條光滑的,對輸入不敏感的曲線,所以w越小越好
  • 那這樣為什麼不直接把權重初始化為0,或者說很小很小的數位呢。因為,w太小的話,那麼在反向傳播的時候,由於我們習慣學習率lr 設定很小,那在更新w的時候基本就不更新了。而不把權重設定為0,是因為無論訓練多久,在更新權重的時候,所有權重都會被更新成相同的值,這樣多層隱藏層就沒有意義了。嚴格來說,是為了瓦解權重的對稱結構

接下來可以訓練我們的模型了

1. 將輸入的特徵x和對應真實值label y通過zip函數打包。將輸入x經過模型 w *x + b 的預測輸出預測值y

2. 計算損失函數loss,因為之前將w、b都是設定成會計算梯度的,那麼loss.backward() 會自動計算w和b的梯度。用w的值data,減去梯度的值grad.data 乘上 學習率lr完成一次更新

3. 當w、b梯度不為零的話,要清零。這裡有兩種解釋,第一種是每次計算完梯度後,值會和之前計算的梯度值進行累加,而我們只是需要當前這步的梯度值,所有我們需要將之前的值清零。第二種是,因為梯度的累加,那麼相當於實現一個很大的batch訓練。假如一個epoch裡面,梯度不進行清零的話,相當於把所有的樣本求和後在進行梯度下降,而不是我們原先使用的針對單個樣本進行下降的SGD演演算法

4. 每100次迭代後,我們列印一下損失

4. 繪製影象

scatter 相當於離散點的繪圖

要繪製連續的影象,只需要給個定義域然後通過表示式 w * x +b 計算y就可以了,最後輸出一下w和b,看看是不是和我們設定的w = 2,b =3 接近

5. 程式碼

import torch
import matplotlib.pyplot as plt
def trainSet(batch_size = 20):   # 定義訓練集
    x = torch.rand(batch_size,1) * 10
    y = x * 2 + 3 + torch.randn(batch_size,1)   # y = x * 2  + 3(近似)
    return x,y
train_x, train_y = trainSet()   # 訓練集
w =torch.randn(1,requires_grad= True)
b = torch.zeros(1,requires_grad= True)
lr = 0.001
for epoch in range(1000):
    for x,y in zip(train_x,train_y):  # SGD演演算法,如果是BSGD的話,不需要這個for
        y_pred = w*x  + b
        loss = (y - y_pred).pow(2) / 2
        loss.backward()
        w.data -= w.grad.data * lr
        b.data -= b.grad.data * lr
        if w.data is not True:   # 梯度值不為零的話,要清零
            w.grad.data.zero_()   #  否則相當於一個大的batch訓練
        if b.data is not True:
            b.grad.data.zero_()
    if epoch % 100 ==0:
        print('loss:',loss.data)
plt.scatter(train_x,train_y)
x = torch.arange(0,11).view(-1,1)
y = x * w.data + b.data
plt.plot(x,y)
plt.show()
print(w.data,b.data)

輸出的影象

輸出的結果為

這裡可以看的最後的w = 1.9865和b = 2.9857 和我們設定的2,3是接近的

到此這篇關於Python反向傳播實現線性迴歸步驟詳細講解的文章就介紹到這了,更多相關Python線性迴歸內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com