1. 程式人生 > 其它 >[課堂筆記][pytorch學習][1]pytorch的tensor是什麼?如何使用cuda?和簡單的神經網路實現

[課堂筆記][pytorch學習][1]pytorch的tensor是什麼?如何使用cuda?和簡單的神經網路實現

課程地址:https://www.bilibili.com/video/BV12741177Cu

第一節課課程筆記:

PyTorch與其他框架的對比

- PyTorch:動態計算圖Dynamic Computation Graph - Tensorflow:靜態計算圖Static Computation Graph

什麼是PyTorch?

PyTorch是一個基於Python的科學計算庫,它有以下特點:

  • 類似於NumPy,但是它可以使用GPU
  • 可以用它定義深度學習模型,可以靈活地進行深度學習模型的訓練和使用

Tensors

Tensor類似與NumPy的ndarray,唯一的區別是Tensor可以在GPU上加速運算。

tensor舉例:

1.in-place加法

y.add_(x)
輸出:
tensor([[ 1.1866,  0.0035, -0.7225],
        [ 0.8220,  0.9750,  0.8406],
        [ 1.2857,  0.5896,  0.6168],
        [ 0.8559,  0.7026,  2.2498],
        [ 0.2741, -0.4248,  0.2826]])
#任何in-place的運算都會以``_``結尾。 舉例來說:``x.copy_(y)``, ``x.t_()``, 會改變 ``x``。

2.如果你有一個只有一個元素的tensor,使用.item()

方法可以把裡面的value變成Python數值。

x = torch.randn(1)
輸出x:
tensor([-1.1493])
x.item()
輸出x:
-1.1493233442306519

3.Torch Tensor和NumPy array會共享記憶體,所以改變其中一項也會改變另一項。

a = torch.ones(5)
輸出a:
tensor([1., 1., 1., 1., 1.])
b = a.numpy()
輸出b:
array([1., 1., 1., 1., 1.], dtype=float32)

改變numpy array裡面的值。
b[1] = 2
輸出a:
tensor([
1., 2., 1., 1., 1.])
#所有CPU上的Tensor都支援轉成numpy或者從numpy轉成Tensor。
#numpy不能在GPU上計算,但是tensor可以。

4.使用.to方法,Tensor可以被移動到別的device上。例如:移到CUDA

#一般在程式碼中都會這樣寫
if torch.cuda.is_available():
    device = torch.device("cuda")

Tensor和autograd

PyTorch的一個重要功能就是autograd,也就是說只要定義了forward pass(前向神經網路),計算了loss之後,PyTorch可以自動求導計算模型所有引數的梯度。

一個PyTorch的Tensor表示計算圖中的一個節點。如果x是一個Tensor並且x.requires_grad=True那麼x.grad是另一個儲存著x當前梯度(相對於一個scalar,常常是loss)的向量。

使用PyTorch中nn這個庫來構建一個簡單的神經網路。 用PyTorch autograd來構建計算圖和計算gradients, 然後PyTorch會幫我們自動計算gradient。

import torch.nn as nn

N, D_in, H, D_out = 64, 1000, 100, 10

# 隨機建立一些訓練資料
x = torch.randn(N, D_in)
y = torch.randn(N, D_out)

model = torch.nn.Sequential(
    torch.nn.Linear(D_in, H, bias=False), # w_1 * x + b_1
    torch.nn.ReLU(),
    torch.nn.Linear(H, D_out, bias=False),
)

torch.nn.init.normal_(model[0].weight)
torch.nn.init.normal_(model[2].weight)

# model = model.cuda()

loss_fn = nn.MSELoss(reduction='sum')

learning_rate = 1e-6
for it in range(500):
    # Forward pass
    y_pred = model(x) # model.forward() 
    
    # compute loss
    loss = loss_fn(y_pred, y) # computation graph
    print(it, loss.item())
    
    # Backward pass
    loss.backward()
    
    # update weights of w1 and w2
    with torch.no_grad():
        for param in model.parameters(): # param (tensor, grad)
            param -= learning_rate * param.grad
            
    model.zero_grad()

optim

不手動更新模型的weights,而是使用optim這個包來幫助我們更新引數。 optim這個package提供了各種不同的模型優化方法,包括SGD+momentum, RMSProp, Adam等等。

optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
optimizer.zero_grad()
    # Backward pass
    loss.backward()
    
    # update model parameters
    optimizer.step()

自定義 nn Modules

我們可以定義一個模型,這個模型繼承自nn.Module類。如果需要定義一個比Sequential模型更加複雜的模型,就需要定義nn.Module模型。

class TwoLayerNet(torch.nn.Module):
    def __init__(self, D_in, H, D_out):
        super(TwoLayerNet, self).__init__()
        # define the model architecture
        self.linear1 = torch.nn.Linear(D_in, H, bias=False)
        self.linear2 = torch.nn.Linear(H, D_out, bias=False)
    
    def forward(self, x):
        y_pred = self.linear2(self.linear1(x).clamp(min=0))
        return y_pred