【PyTorch學習】分別使用Numpy和Tensor及Antograd實現機器學習

本文分別用Numpy、Tensor、autograd來實現同一個機器學習任務,比較它們之間的異同及各自優缺點,從而加深大家對PyTorch的理解。

一、使用Numpy實現機器學習

首先,我們用最原始的Numpy實現有關回歸的一個機器學習任務,不用PyTorch中的包或類。

主要步驟包括:

  1. 首先,給出一個數組x,然後基於表達式y=3x2+2,加上一些噪音數據到達另一組數據y。
  2. 然後,構建一個機器學習模型,學習表達式y=wx2+b的兩個參數w、b。利用數組x,y的數據爲訓練數據。
  3. 最後,採用梯度梯度下降法,通過多次迭代,學習到w、b的值。

以下爲實戰環節的具體步驟:
1)導入需要的庫

import numpy as np
from matplotlib import pyplot as plt
%matplotlib inline

2)生成輸入數據x及目標數據y

設置隨機數種子,即生成同一份數據,以便使用多種方法進行比較。

np.random.seed(666)
x = np.linspace(-1, 1, 100).reshape(100, 1)
y = 3 * np.power(x, 2) + 2 + 0.2 * np.random.rand(x.size).reshape(100, 1)

3)查看x、y數據分佈情況

# 繪圖
plt.scatter(x,y)
plt.show()

4)初始化權重參數

# 隨機初始化參數
w = np.random.rand(1,1)
b = np.random.rand(1,1)

5)訓練模型

定義損失函數,假設批量大小爲100:

對損失函數求導:

利用梯度下降法學習參數,學習率爲lr。

用代碼實現上面這些表達式:

lr = 0.001 # 學習率
for i in range(800):
    # 前向傳播
    y_pred = np.power(x, 2) * w + b
    # 定義損失函數
    loss = 0.5 * (y_pred - y) ** 2
    loss = loss.sum()
    # 計算梯度
    grad_w = np.sum((y_pred - y) * np.power(x, 2))
    grad_b = np.sum(y_pred - y)
    # 使用梯度下降法,是loss最小
    w -= lr * grad_w
    b -= lr * grad_b

6)可視化結果

plt.plot(x, y_pred, 'r-', label='predict')
plt.scatter(x, y, color='blue', marker='o', label='true')

plt.xlim(-1, 1)
plt.ylim(2, 6)
plt.legend()
plt.show()
print(w, b)

[[2.99850472]] [[2.0989827]]

從結果看來,學習效果還是還是比較理想的。

 

二、使用Tensor及Antograd實現機器學習

上節可以說是純手工完成一個機器學習任務,數據用Numpy表示,梯度及學習是自己定義並構建學習模型。這種方法適合於比較簡單的情況,如果稍微複雜一些,代碼量將幾何級增加。那是否有更方便的方法呢?

本節我們將使用PyTorch的一個自動求導的包——antograd,利用這個包及對應的Tensor,便可利用自動反向傳播來求梯度,無須手工計算梯度。

以下爲實戰環節的具體步驟:

1)導入需要的庫

import torch as t
from matplotlib import pyplot as plt
%matplotlib inline

2)生成訓練數據,並可視化數據分佈情況

# 隨機種子
torch.manual_seed(666)

# 生成x座標數據,x爲tensor,需要把x的形狀裝換爲100×1
x = torch.unsqueeze(torch.linspace(-1, 1, 100), dim=1)
# 生成y座標數據,y爲tensor,形狀爲100×1,另加上一些噪聲
y = 3 * x.pow(2) + 2 + 0.2 * torch.rand(x.size())

# 繪圖,把tensor數據轉換爲numpy數據
plt.scatter(x.numpy(), y.numpy())
plt.show()

3)初始化權重參數

# 隨機初始化參數,參數w,b爲需要學習的,故需requires_grad=True
w = torch.randn(1, 1, dtype = torch.float, requires_grad=True)
b = torch.zeros(1, 1, dtype = torch.float, requires_grad=True)

4)訓練模型

lr = 0.001 # 學習率
for i in range(800):
    # 前向傳播
    y_pred = x.pow(2).mm(w) + b
    # 定義損失函數
    loss = 0.5 * (y_pred - y) ** 2
    loss = loss.sum()
    # 自動計算梯度,梯度存放在grad屬性中
    loss.backward()
    # 手動更新參數,需要用torch.no_grad(),使上下文環境中切斷自動求導的計算
    with torch.no_grad():
        w -= lr * w.grad
        b -= lr * b.grad
        
        # 梯度清零
        w.grad.zero_()
        b.grad.zero_()

5)可視化訓練結果

plt.plot(x.numpy(), y_pred.detach().numpy(), 'r-', label='predict') # predict
plt.scatter(x.numpy(), y.numpy(), color='blue', marker='o', label='true') # true data

plt.xlim(-1, 1)
plt.ylim(2, 6)
plt.legend()
plt.show()
print(w, b)

tensor([[2.9578]], requires_grad=True) tensor([[2.0990]], requires_grad=True)

這個結果與使用Numpy實現機器學習差不多。

 

 

 

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