pytorch 小試牛刀

#PyTorch的核心是兩個主要特徵:
# 一個n維張量,類似於numpy,但可以在GPU上運行
# 搭建和訓練神經網絡時的自動微分/求導機制

# 熱身: Numpy
# 在介紹PyTorch之前,本章節將首先使用numpy實現網絡。 Numpy提供了一個n維數組對象,
# 以及許多用於操作這些數組的 函數。Numpy是用於科學計算的通用框架;它對計算圖、
# 深度學習和梯度一無所知。然而,我們可以很容易地使用NumPy,手動實現網絡的 前向和反向傳播,
# 來擬合隨機數據:

# -*- coding: utf-8 -*-
import numpy as np

# N是批量大小; D_in是輸入維度;
# 49/5000 H是隱藏的維度; D_out是輸出維度。
N, D_in, H, D_out = 64, 1000, 100, 10

# 創建隨機輸入和輸出數據
x = np.random.randn(N, D_in)
y = np.random.randn(N, D_out)

# 隨機初始化權重
w1 = np.random.randn(D_in, H)
w2 = np.random.randn(H, D_out)

learning_rate = 1e-6
for t in range(500):
    # 前向傳遞:計算預測值y
    h = x.dot(w1)
    h_relu = np.maximum(h, 0)
    y_pred = h_relu.dot(w2)

    # 計算和打印損失loss
    loss = np.square(y_pred - y).sum()
    print(t, loss)

    # 反向傳播,計算w1和w2對loss的梯度
    grad_y_pred = 2.0 * (y_pred - y)
    grad_w2 = h_relu.T.dot(grad_y_pred)
    grad_h_relu = grad_y_pred.dot(w2.T)
    grad_h = grad_h_relu.copy()
    grad_h[h < 0] = 0
    grad_w1 = x.T.dot(grad_h)

    # 更新權重
    w1 -= learning_rate * grad_w1
    w2 -= learning_rate * grad_w2
    
# PyTorch:張量
# Numpy是一個很棒的框架,但它不能利用GPU來加速其數值計算。 對於現代深度神經網絡,
# GPU通常提供50倍或更高的加速,所以,numpy不能滿足當代深度學習的需求。

# 在這裏,先介紹最基本的PyTorch概念:
# 張量(Tensor):PyTorch的tensor在概念上與numpy的array相同: tensor是一個n維數組,
# PyTorch提供了許多函數用於操作這些張量。任何希望使用NumPy執行的計算也可以使用PyTorch的tensor
# 來完成,可以認爲它們是科學計算的通用工具。
# 與Numpy不同,PyTorch可以利用GPU加速其數值計算。要在GPU上運行Tensor,在構造張量使用device
# 參數把tensor建立在GPU上。
# 在這裏,本章使用tensors將隨機數據上訓練一個兩層的網絡。和前面NumPy的例子類似,
# 我們使用PyTorch的tensor,手動在網絡中實現前向傳播和反向傳播:

# -*- coding: utf-8 -*-
import torch

dtype = torch.float
device = torch.device("cpu")
# device = torch.device(“cuda:0”)#取消註釋以在GPU上運行

# N是批量大小; D_in是輸入維度;
# H是隱藏的維度; D_out是輸出維度。
N, D_in, H, D_out = 64, 1000, 100, 10

#創建隨機輸入和輸出數據
x = torch.randn(N, D_in, device=device, dtype=dtype)
y = torch.randn(N, D_out, device=device, dtype=dtype)

# 隨機初始化權重
w1 = torch.randn(D_in, H, device=device, dtype=dtype)
w2 = torch.randn(H, D_out, device=device, dtype=dtype)

learning_rate = 1e-6
for t in range(500):
    # 前向傳遞:計算預測y
    h = x.mm(w1)
    h_relu = h.clamp(min=0)
    y_pred = h_relu.mm(w2)

    # 計算和打印損失
    loss = (y_pred - y).pow(2).sum().item()
    print(t, loss)

    # Backprop計算w1和w2相對於損耗的梯度
    grad_y_pred = 2.0 * (y_pred - y)
    grad_w2 = h_relu.t().mm(grad_y_pred)
    grad_h_relu = grad_y_pred.mm(w2.t()) #給w2 和 h_relu都計算梯度
    grad_h = grad_h_relu.clone()
    grad_h[h < 0] = 0
    grad_w1 = x.t().mm(grad_h)

    # 使用梯度下降更新權重
    w1 -= learning_rate * grad_w1
    w2 -= learning_rate * grad_w2

# 自動求導
# PyTorch:張量和自動求導
# 1在上面的例子中,需要手動實現神經網絡的前向和後向 傳遞。手動實現反向傳遞對於小型雙層網絡來說
# 並不是什麼大問 題,但對於大型複雜網絡來說很快就會變得非常繁瑣。
# 2但是可以使用自動微分來自動計算神經網絡中的後向傳遞。 PyTorch中的 autograd包提供了這個功能。
# 當使用autograd時,網絡前向傳播將定義一個計算圖;圖中的節點是tensor,邊是函數, 這些函數是
# 輸出tensor到輸入tensor的映射。這張計算圖使得在網絡中反向傳播時梯度的計算十分簡單。
# 3這聽起來很複雜,在實踐中使用起來非常簡單。 如果我們想計算某些的tensor的梯度,我們只需要在
# 建立這個tensor時加入這麼一句:requires_grad=True。這個tensor上的任何PyTorch的操作都將構造
# 一個計算圖,從而允許我們稍後在圖中執行反向傳播。如果這個tensor x的requires_grad=True,那麼
# 反向傳播之後x.grad將會是另一個張量,其爲x關於某個標量值的梯度。
# 4有時可能希望防止PyTorch在requires_grad=True的張量執行某些操作時構建計算圖;例如,在訓練神
# 經網絡時,我們通常不希望通過權重更新步驟進行反向傳播。在這種情況下,我們可以使用
# torch.no_grad()上下文管理器來防止構造計算圖。
# 5下面我們使用PyTorch的Tensors和autograd來實現我們的兩層的神經網絡;我們不再需要手動執行網絡
# 的反向傳播:
# -*- coding: utf-8 -*-
import torch

dtype = torch.float
device = torch.device("cpu")
# device = torch.device(“cuda:0”)#取消註釋以在GPU上運行

# N是批量大小; D_in是輸入維度;
# H是隱藏的維度; D_out是輸出維度。
N, D_in, H, D_out = 64, 1000, 100, 10

# 創建隨機Tensors以保持輸入和輸出。
# 設置requires_grad = False表示我們不需要計算漸變
# 在向後傳球期間對於這些Tensors。
x = torch.randn(N, D_in, device=device, dtype=dtype)
y = torch.randn(N, D_out, device=device, dtype=dtype)

# 爲權重創建隨機Tensors。
# 設置requires_grad = True表示我們想要計算漸變
# 在向後傳球期間尊重這些張貼。
w1 = torch.randn(D_in, H, device=device, dtype=dtype, requires_grad=True)
w2 = torch.randn(H, D_out, device=device, dtype=dtype, requires_grad=True)

learning_rate = 1e-6
for t in range(500):
    # 前向傳播:使用tensors上的操作計算預測值y; 
      # 由於w1和w2有requires_grad=True,涉及這些張量的操作將讓PyTorch構建計算圖,
    # 從而允許自動計算梯度。由於我們不再手工實現反向傳播,所以不需要保留中間值的引用。
    y_pred = x.mm(w1).clamp(min=0).mm(w2)

    # 使用Tensors上的操作計算和打印丟失。
    # loss是一個形狀爲()的張量
    # loss.item() 得到這個張量對應的python數值
    loss = (y_pred - y).pow(2).sum()
    print(t, loss.item())

    # 使用autograd計算反向傳播。這個調用將計算loss對所有requires_grad=True的tensor的梯度。
    # 這次調用後,w1.grad和w2.grad將分別是loss對w1和w2的梯度張量。
    loss.backward()

    # 使用梯度下降更新權重。對於這一步,我們只想對w1和w2的值進行原地改變;不想爲更新階段構建計算圖,
    # 所以我們使用torch.no_grad()上下文管理器防止PyTorch爲更新構建計算圖
    with torch.no_grad():
        w1 -= learning_rate * w1.grad
        w2 -= learning_rate * w2.grad

        # 反向傳播後手動將梯度設置爲零
        w1.grad.zero_()
        w2.grad.zero_()

# PyTorch:定義新的自動求導函數
# 1在底層,每一個原始的自動求導運算實際上是兩個在Tensor上運行的函數。其中,forward函數計算從
# 輸入Tensors獲得的輸出Tensors。而backward函數接收輸出Tensors對於某個標量值的梯度,並且計算
# 輸入Tensors相對於該相同標量值的梯度。
# 2在PyTorch中,我們可以很容易地通過定義torch.autograd.Function的子類並實現forward和backward
# 函數,來定義自己的自動求導運算。之後我們就可以使用這個新的自動梯度運算符了。然後,我們可以通過
# 構造一個實例並像調用函數一樣,傳入包含輸入數據的tensor調用它,這樣來使用新的自動求導運算。
# 3這個例子中,我們自定義一個自動求導函數來展示ReLU的非線性。並用它實現我們的兩層網絡:
import torch
class MyReLU(torch.autograd.Function):
    """
    我們可以通過建立torch.autograd的子類來實現我們自定義的autograd函數,
    並完成張量的正向和反向傳播。
    """
    @staticmethod
    def forward(ctx, x):
        """
        在正向傳播中,我們接收到一個上下文對象和一個包含輸入的張量;
        我們必須返回一個包含輸出的張量,
        並且我們可以使用上下文對象來緩存對象,以便在反向傳播中使用。
        """
        ctx.save_for_backward(x)
        return x.clamp(min=0)

    @staticmethod
    def backward(ctx, grad_output):
        """
        在反向傳播中,我們接收到上下文對象和一個張量,
        其包含了相對於正向傳播過程中產生的輸出的損失的梯度。
        我們可以從上下文對象中檢索緩存的數據,
        並且必須計算並返回與正向傳播的輸入相關的損失的梯度。
        """
        x, = ctx.saved_tensors
        grad_x = grad_output.clone()
        grad_x[x < 0] = 0
        return grad_x

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

# N是批大小; D_in 是輸入維度;
# H 是隱藏層維度; D_out 是輸出維度
N, D_in, H, D_out = 64, 1000, 100, 10

# 產生輸入和輸出的隨機張量
x = torch.randn(N, D_in, device=device)
y = torch.randn(N, D_out, device=device)

# 產生隨機權重的張量
w1 = torch.randn(D_in, H, device=device, requires_grad=True)
w2 = torch.randn(H, D_out, device=device, requires_grad=True)

learning_rate = 1e-6
for t in range(500):
    # 正向傳播:使用張量上的操作來計算輸出值y;
    # 我們通過調用 MyReLU.apply 函數來使用自定義的ReLU
    y_pred = MyReLU.apply(x.mm(w1)).mm(w2)

    # 計算並輸出loss
    loss = (y_pred - y).pow(2).sum()
    print(t, loss.item())

    # 使用autograd計算反向傳播過程。
    loss.backward()

    with torch.no_grad():
        # 用梯度下降更新權重
        w1 -= learning_rate * w1.grad
        w2 -= learning_rate * w2.grad

        # 在反向傳播之後手動清零梯度
        w1.grad.zero_()
        w2.grad.zero_()

# TensorFlow:靜態圖
# 1PyTorch自動求導看起來非常像TensorFlow:這兩個框架中,我們都定義計算圖,使用自動微分來計算
# 梯度。兩者最大的不同就是TensorFlow的計算圖是靜態的,而PyTorch使用動態的計算圖。
# 2在TensorFlow中,我們定義計算圖一次,然後重複執行這個相同的圖,可能會提供不同的輸入數據。
# 而在PyTorch中,每一個前向通道定義一個新的計算圖。
# 3靜態圖的好處在於你可以預先對圖進行優化。例如,一個框架可能要融合一些圖的運算來提升效率,
# 或者產生一個策略來將圖分佈到多個GPU或機器上。如果重複使用相同的圖,那麼在重複運行同一個
# 圖時,,前期潛在的代價高昂的預先優化的消耗就會被分攤開。
# 4靜態圖和動態圖的一個區別是控制流。對於一些模型,我們希望對每個數據點執行不同的計算。例如,
# 一個遞歸神經網絡可能對於每個數據點執行不同的時間步數,這個展開(unrolling)可以作爲一個循環
# 來實現。對於一個靜態圖,循環結構要作爲圖的一部分。因此,TensorFlow提供了運算符(例如tf.scan
# )來把循環嵌入到圖當中。對於動態圖來說,情況更加簡單:既然我們爲每個例子即時創建圖,我們可以
# 使用普通的命令式控制流來爲每個輸入執行不同的計算。
# 爲了與上面的PyTorch自動梯度實例做對比,我們使用TensorFlow來擬合一個簡單的2層網絡:
import tensorflow as tf
import numpy as np

# 首先我們建立計算圖(computational graph)

# N是批大小;D是輸入維度;
# H是隱藏層維度;D_out是輸出維度。
N, D_in, H, D_out = 64, 1000, 100, 10

# 爲輸入和目標數據創建placeholder;
# 當執行計算圖時,他們將會被真實的數據填充
x = tf.placeholder(tf.float32, shape=(None, D_in))
y = tf.placeholder(tf.float32, shape=(None, D_out))

# 爲權重創建Variable並用隨機數據初始化
# TensorFlow的Variable在執行計算圖時不會改變
w1 = tf.Variable(tf.random_normal((D_in, H)))
w2 = tf.Variable(tf.random_normal((H, D_out)))

# 前向傳播:使用TensorFlow的張量運算計算預測值y。
# 注意這段代碼實際上不執行任何數值運算;
# 它只是建立了我們稍後將執行的計算圖。
h = tf.matmul(x, w1)
h_relu = tf.maximum(h, tf.zeros(1))
y_pred = tf.matmul(h_relu, w2)

# 使用TensorFlow的張量運算損失(loss)
loss = tf.reduce_sum((y - y_pred) ** 2.0)

# 計算loss對於w1和w2的導數
grad_w1, grad_w2 = tf.gradients(loss, [w1, w2])

# 使用梯度下降更新權重。爲了實際更新權重,我們需要在執行計算圖時計算new_w1和new_w2。
# 注意,在TensorFlow中,更新權重值的行爲是計算圖的一部分;
# 但在PyTorch中,這發生在計算圖形之外。
learning_rate = 1e-6
new_w1 = w1.assign(w1 - learning_rate * grad_w1)
new_w2 = w2.assign(w2 - learning_rate * grad_w2)

# 現在我們搭建好了計算圖,所以我們開始一個TensorFlow的會話(session)來實際執行計算圖。
with tf.Session() as sess:

    # 運行一次計算圖來初始化Variable w1和w2
    sess.run(tf.global_variables_initializer())

    # 創建numpy數組來存儲輸入x和目標y的實際數據
    x_value = np.random.randn(N, D_in)
    y_value = np.random.randn(N, D_out)

    for _ in range(500):
        # 多次運行計算圖。每次執行時,我們都用feed_dict參數,
        # 將x_value綁定到x,將y_value綁定到y,
        # 每次執行圖形時我們都要計算損失、new_w1和new_w2;
        # 這些張量的值以numpy數組的形式返回。
        loss_value, _, _ = sess.run([loss, new_w1, new_w2], 
                                    feed_dict={x: x_value, y: y_value})
        print(loss_value)


# nn模塊
# PyTorch:nn
# 1計算圖和autograd是十分強大的工具,可以定義複雜的操作並自動求導;然而對於大規模的網絡,
# autograd太過於底層。 在構建神經網絡時,我們經常考慮將計算安排成層,其中一些具有可學習的參數,
# 它們將在學習過程中進行優化。
# 2TensorFlow裏,有類似Keras,TensorFlow-Slim和TFLearn這種封裝了底層計算圖的高度抽象的接口,
# 這使得構建網絡十分方便。
# 3在PyTorch中,包nn完成了同樣的功能。nn包中定義一組大致等價於層的模塊。一個模塊接受輸入的
# tesnor,計算輸出的tensor,而且 還保存了一些內部狀態比如需要學習的tensor的參數等。nn包中也
# 定義了一組損失函數(loss functions),用來訓練神經網絡。
# 這個例子中,我們用nn包實現兩層的網絡:
# -*- coding: utf-8 -*-
import torch

# N是批大小;D是輸入維度
# H是隱藏層維度;D_out是輸出維度
N, D_in, H, D_out = 64, 1000, 100, 10

#創建輸入和輸出隨機張量
x = torch.randn(N, D_in)
y = torch.randn(N, D_out)

# 使用nn包將我們的模型定義爲一系列的層。
# nn.Sequential是包含其他模塊的模塊,並按順序應用這些模塊來產生其輸出。
# 每個線性模塊使用線性函數從輸入計算輸出,並保存其內部的權重和偏差張量。
# 在構造模型之後,我們使用.to()方法將其移動到所需的設備。
model = torch.nn.Sequential(
    torch.nn.Linear(D_in, H),
    torch.nn.ReLU(),
    torch.nn.Linear(H, D_out),
)

# nn包還包含常用的損失函數的定義;
# 在這種情況下,我們將使用平均平方誤差(MSE)作爲我們的損失函數。
# 設置reduction='sum',表示我們計算的是平方誤差的“和”,而不是平均值;
# 這是爲了與前面我們手工計算損失的例子保持一致,
# 但是在實踐中,通過設置reduction='elementwise_mean'來使用均方誤差作爲損失更爲常見。
loss_fn = torch.nn.MSELoss(reduction='sum')

learning_rate = 1e-4
for t in range(500):
    # 前向傳播:通過向模型傳入x計算預測的y。
    # 模塊對象重載了__call__運算符,所以可以像函數那樣調用它們。
    # 這麼做相當於向模塊傳入了一個張量,然後它返回了一個輸出張量。
    y_pred = model(x)

     # 計算並打印損失。
     # 傳遞包含y的預測值和真實值的張量,損失函數返回包含損失的張量。
    loss = loss_fn(y_pred, y)
    print(t, loss.item())

    # 反向傳播之前清零梯度
    model.zero_grad()

    # 反向傳播:計算模型的損失對所有可學習參數的導數(梯度)。
    # 在內部,每個模塊的參數存儲在requires_grad=True的張量中,
    # 因此這個調用將計算模型中所有可學習參數的梯度。
    loss.backward()

    # 使用梯度下降更新權重。
    # 每個參數都是張量,所以我們可以像我們以前那樣可以得到它的數值和梯度
    with torch.no_grad():
        for param in model.parameters():
            param -= learning_rate * param.grad


 # PyTorch:optim
 # 到目前爲止,我們已經通過手動改變包含可學習參數的張量來更新模型的權重。對於隨機梯度
 # 下降(SGD/stochastic gradient descent)等簡單的優化算法來說,這不是一個很大的負擔,
 # 但在實踐中,我們經常使用AdaGrad、RMSProp、Adam等更復雜的優化器來訓練神經網絡。
import torch

# N是批大小;D是輸入維度
# H是隱藏層維度;D_out是輸出維度
N, D_in, H, D_out = 64, 1000, 100, 10

# 產生隨機輸入和輸出張量
x = torch.randn(N, D_in)
y = torch.randn(N, D_out)

# 使用nn包定義模型和損失函數
model = torch.nn.Sequential(
          torch.nn.Linear(D_in, H),
          torch.nn.ReLU(),
          torch.nn.Linear(H, D_out),
        )
loss_fn = torch.nn.MSELoss(reduction='sum')

# 使用optim包定義優化器(Optimizer)。Optimizer將會爲我們更新模型的權重。
# 這裏我們使用Adam優化方法;optim包還包含了許多別的優化算法。
# Adam構造函數的第一個參數告訴優化器應該更新哪些張量。
learning_rate = 1e-4
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)

for t in range(500):

    # 前向傳播:通過像模型輸入x計算預測的y
    y_pred = model(x)

    # 計算並打印loss
    loss = loss_fn(y_pred, y)
    print(t, loss.item())

    # 在反向傳播之前,使用optimizer將它要更新的所有張量的梯度清零(這些張量是模型可學習的權重)
    optimizer.zero_grad()

    # 反向傳播:根據模型的參數計算loss的梯度
    loss.backward()

    # 調用Optimizer的step函數使它所有參數更新
    optimizer.step()
 

 # PyTorch:自定義nn模塊
 # 有時候需要指定比現有模塊序列更復雜的模型;對於這些情況,可以通過繼承nn.Module並定義forward
 # 函數,這個forward函數可以 使用其他模塊或者其他的自動求導運算來接收輸入tensor,產生輸出
 # tensor。
 # 在這個例子中,我們用自定義Module的子類構建兩層網絡:
import torch

class TwoLayerNet(torch.nn.Module):
    def __init__(self, D_in, H, D_out):
        """
        在構造函數中,我們實例化了兩個nn.Linear模塊,並將它們作爲成員變量。
        """
        super(TwoLayerNet, self).__init__()
        self.linear1 = torch.nn.Linear(D_in, H)
        self.linear2 = torch.nn.Linear(H, D_out)

    def forward(self, x):
        """
        在前向傳播的函數中,我們接收一個輸入的張量,也必須返回一個輸出張量。
        我們可以使用構造函數中定義的模塊以及張量上的任意的(可微分的)操作。
        """
        h_relu = self.linear1(x).clamp(min=0)
        y_pred = self.linear2(h_relu)
        return y_pred

# N是批大小; D_in 是輸入維度;
# H 是隱藏層維度; D_out 是輸出維度
N, D_in, H, D_out = 64, 1000, 100, 10

# 產生輸入和輸出的隨機張量
x = torch.randn(N, D_in)
y = torch.randn(N, D_out)

# 通過實例化上面定義的類來構建我們的模型。
model = TwoLayerNet(D_in, H, D_out)

# 構造損失函數和優化器。
# SGD構造函數中對model.parameters()的調用,
# 將包含模型的一部分,即兩個nn.Linear模塊的可學習參數。
loss_fn = torch.nn.MSELoss(reduction='sum')
optimizer = torch.optim.SGD(model.parameters(), lr=1e-4)
for t in range(500):
    # 前向傳播:通過向模型傳遞x計算預測值y
    y_pred = model(x)

    #計算並輸出loss
    loss = loss_fn(y_pred, y)
    print(t, loss.item())

    # 清零梯度,反向傳播,更新權重
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()


# PyTorch:控制流和權重共享
# 1作爲動態圖和權重共享的一個例子,我們實現了一個非常奇怪的模型:一個全連接的ReLU網絡,在每一次
# 前向傳播時,它的隱藏層的層數爲隨機1到4之間的數,這樣可以多次重用相同的權重來計算。
# 2因爲這個模型可以使用普通的Python流控制來實現循環,並且我們可以通過在定義轉發時多次重用同一個
# 模塊來實現最內層之間的權重共享。
# 我們利用Mudule的子類很容易實現這個模型:
import random
import torch

class DynamicNet(torch.nn.Module):
    def __init__(self, D_in, H, D_out):
        """
        在構造函數中,我們構造了三個nn.Linear實例,它們將在前向傳播時被使用。
        """
        super(DynamicNet, self).__init__()
        self.input_linear = torch.nn.Linear(D_in, H)
        self.middle_linear = torch.nn.Linear(H, H)
        self.output_linear = torch.nn.Linear(H, D_out)

    def forward(self, x):
        """
        對於模型的前向傳播,我們隨機選擇0、1、2、3,
        並重用了多次計算隱藏層的middle_linear模塊。
        由於每個前向傳播構建一個動態計算圖,
        我們可以在定義模型的前向傳播時使用常規Python控制流運算符,如循環或條件語句。
        在這裏,我們還看到,在定義計算圖形時多次重用同一個模塊是完全安全的。
        這是Lua Torch的一大改進,因爲Lua Torch中每個模塊只能使用一次。
        """
        h_relu = self.input_linear(x).clamp(min=0)
        for _ in range(random.randint(0, 3)):
            h_relu = self.middle_linear(h_relu).clamp(min=0)
        y_pred = self.output_linear(h_relu)
        return y_pred


# N是批大小;D是輸入維度
# H是隱藏層維度;D_out是輸出維度
N, D_in, H, D_out = 64, 1000, 100, 10

# 產生輸入和輸出隨機張量
x = torch.randn(N, D_in)
y = torch.randn(N, D_out)

# 實例化上面定義的類來構造我們的模型
model = DynamicNet(D_in, H, D_out)

# 構造我們的損失函數(loss function)和優化器(Optimizer)。
# 用平凡的隨機梯度下降訓練這個奇怪的模型是困難的,所以我們使用了momentum方法。
criterion = torch.nn.MSELoss(reduction='sum')
optimizer = torch.optim.SGD(model.parameters(), lr=1e-4, momentum=0.9)
for t in range(500):

    # 前向傳播:通過向模型傳入x計算預測的y。
    y_pred = model(x)

    # 計算並打印損失
    loss = criterion(y_pred, y)
    print(t, loss.item())

    # 清零梯度,反向傳播,更新權重 
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()



結果:
....
473 0.36836346983909607
474 0.38714009523391724
475 0.38550668954849243
476 0.17191095650196075
477 1.9847731590270996
478 0.5298959016799927
479 0.7367187738418579
480 1.2307839393615723
481 0.43006712198257446
482 0.6406421065330505
483 0.47744494676589966
484 0.5971325635910034
485 0.10514151304960251
486 0.4203549027442932
487 0.6698665022850037
488 0.5240647196769714
489 0.3876400589942932
490 0.5721966028213501
491 0.4274476170539856
492 0.7306835651397705
493 0.12239256501197815
494 0.11220799386501312
495 0.5246854424476624
496 0.08536854386329651
497 0.3004726767539978
498 0.3048897385597229
499 0.5388519763946533

 

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