PyTorch教程-1:PyTorch中的Tensor基礎

筆者PyTorch的全部簡單教程請訪問:http://www.lxweimin.com/nb/48831659

PyTorch教程-1:PyTorch中的Tensor基礎

首先,引入PyTorch的模塊:

import torch

設置運算資源

使用 torch.cuda.is_available() 來判斷設備上的GPU是否可用,如果可用則返回True,使用 torch.device() 則可以參數指定計算資源:

  • 參數為"cpu"表示使用CPU計算

  • 參數為"cuda"表示使用GPU計算,默認會使用第一塊GPU,即"cuda:0"

  • 對于多GPU的設備,可以通過設置"cuda:N"來指定使用第幾塊GPU,第一塊GPU是"cuda:0"

    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    
    print(device)
    

    cuda
    

創建張量(tensors)

Pytorch中的基本數據類型是tensors(張量),和numpy中的ndarrays是非常相似的,而且可以互相轉換,只是numpy中的多維數組只能在CPU上進行運算,而tensor則是PyTorch中設計的一種可以用于GPU高速運算的數據類型。

和numpy相似,PyTorch中也有很多方法來創建張量,這些方法的統一的幾個常用參數為:

  • 前N個參數依次傳入整數:張量的維度
  • dtype:數據類型,默認為torch.float32
    參數 數據類型
    torch.int 32位整數(等同于torch.int32)
    torch.int8, torch.int16, torch.int32, torch.int64 8位、16位、32位、64位整數
    torch.float 32位浮點數(等同于torch.float32)
    torch.float16, torch.float32, torch.float64 16位、32位、64位浮點數
    torch.double 64位浮點數(等同于torch.float64)
  • device:張量的目標存儲設備,默認為CPU

創建張量的常用方法有:

  • torch.tensor:直接從數據創建,比如可以傳入(多維)list

  • torch.empty:創建一個空的tensor

  • torch.rand:創建一個0-1之間隨機數的tensor

  • torch.ones:創建全1的tensor

  • torch.zeros:創建全0的tensor

    一些例子:

    x = torch.tensor([1,2,3])
    y = torch.rand(2,2,dtype=torch.float)
    z = torch.ones(2,2,dtype=torch.int,device=device)
    print(x)
    print(y)
    print(z)
    

    tensor([1, 2, 3])
    tensor([[0.4366, 0.6651],
            [0.9753, 0.7331]])
    tensor([[1, 1],
            [1, 1]], device='cuda:0', dtype=torch.int32)
    
  • torch.full:這個方法和上述方法擁有不同的參數設置,其將前N個用于指定維數的參數換成:第一個參數為tuple指定維數,第二個參數為指定的值,創建一個該維度大小的全是指定值的tensor,但是同樣有dtypedevice等參數

    x=torch.full((2,3),1.2,dtype=torch.float)
    print(x)
    

    tensor([[1.2000, 1.2000, 1.2000],
            [1.2000, 1.2000, 1.2000]])
    

基于已有的張量創建新的張量,可以使用new_系列的方法,和上面的方法類似,new_系列的方法在原有的方法前加上new_,是一個tensor實例的成員方法,傳入的參數和上述一致,如果沒有指定的參數(指dtypedevice等參數)則繼承原來的張量,但是維度信息必須傳入

```python
x = torch.rand(4,3,dtype=torch.float16,device=device)
y = x.new_ones(x.size(),dtype=torch.int16)
print(x)
print(y)
```

------

```
tensor([[0.5366, 0.9004, 0.8706],
        [0.9712, 0.2258, 0.4180],
        [0.7842, 0.9976, 0.4412],
        [0.5376, 0.7261, 0.4844]], device='cuda:0', dtype=torch.float16)
tensor([[1, 1, 1],
        [1, 1, 1],
        [1, 1, 1],
        [1, 1, 1]], device='cuda:0', dtype=torch.int16)
```

new_系列的方法有:

  • torch.new_tensor
  • torch.new_empty
  • torch.new_ones
  • torch.new_zeros
  • torch.new_full

張量的運算

基本運算的幾種方式

張量之間的基本運算有幾種不同的表達方式,這里以加法運算為例,列舉一下幾種不同方式,比如兩個張量xy

  • 使用運算符運算:x+y

  • 使用torch的方法:torch.add(x,y)

  • 使用torch的方法時,傳入out參數來設置結果的賦值對象:torch.add(x,y,out=z)

  • 使用_結尾的方法,完成類似于+=的操作:y.add_(x)

    x = torch.rand(3,2)
    y = torch.rand(3,2)
    
    z = x+y # method 1
    z = torch.add(x,y)  # method 2
    torch.add(x,y,out=z)    # method 3
    y.add_(x)   # method 4
    

常用的一些操作

一些張量的重要操作列在下邊:

  • 獲取張量的形狀:使用 Tensor.size() 或者 Tensor.shape 獲取張量的形狀,返回的是一個tuple

  • 獲取張量的維數:使用 Tensor.dim() 獲取張量的維數

  • 切片操作:tensors的切片操作和numpy完全一致。(筆者另有一篇詳細介紹關于numpy和list的索引、切片操作的文章,請移步:http://www.lxweimin.com/p/dd166725a2c3

  • 改變形狀:使用Tensor.view方法可以改變一個張量的形狀,使用參數 -1 表示該維度的大小取決于其他維度

    x = torch.rand(4,6)
    print(x.size())
    y = x.view(2,12)
    print(y.size())
    z = x.view(8,-1)
    print(z.size())
    

    torch.Size([4, 6])
    torch.Size([2, 12])
    torch.Size([8, 3])
    
  • 從單元素的張量提出該單獨元素的值:對于只包含一個元素的Tensor,使用 Tensor.item() 獲取該元素

    x = torch.rand(1)
    print(x)
    print(x.item())
    

    tensor([0.5759])
    0.5759033560752869
    

其他的操作

Tensor還有很多各種各樣的操作、方法、屬性等,參考完整的列表:
https://pytorch.org/docs/stable/torch.html

Tensor與其他數據類型的轉換

PyTorch的Tensor與Numpy的ndarray之間的轉換

假設 tensor_x 是一個Tensor,ndarray_y 是一個ndarray:

  • Tensorndarray:使用 Tensor.numpy() 將一個tensor轉換成一個numpyndarray對象

    tensor_x = torch.rand(2,3)
    print(type(tensor_x))
    ndarray_y = tensor_x.numpy()
    print(type(ndarray_y))
    

    <class 'torch.Tensor'>
    <class 'numpy.ndarray'>
    
  • ndarrayTensor:使用 torch.from_numpy(ndarray) 將一個ndarray轉換成tensor

    ndarray_y = np.ones((2,3))
    print(type(ndarray_y))
    tensor_x = torch.from_numpy(ndarray_y)
    print(type(tensor_x))
    

    <class 'numpy.ndarray'>
    <class 'torch.Tensor'>
    

PyTorch的Tensor與Python的list之間的轉換

  • listTensor:使用torch.tensor或者torch.Tensor均可:

    list_a = [[1,2,3],[4,5,6]]
    tensor_x = torch.tensor(list_a)
    tensor_y = torch.Tensor(list_a)
    print(type(tensor_x))
    print(type(tensor_y))
    

    <class 'torch.Tensor'>
    <class 'torch.Tensor'>
    
  • Tensorlist:只能先轉換成numpy數組,再通過numpy數組的tolist方法轉換成list,沒有直接轉換的方法

    list_b = tensor_x.numpy().tolist()
    print(type(list_b))
    

    <class 'list'>
    

將變量分配到GPU計算資源

我們已經知道如何設置計算資源,比如使用如下代碼返回一個可用的設備(即優先使用GPU),如何將一個Tensor分配到對應的計算資源呢?有兩種常用的方法:

  • 在創建Tensor時設置device參數將創建的變量直接發送到對應的設備,device參數默認為"cpu"

    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    x = torch.rand(4,3,device=device)
    print(x)
    

    tensor([[0.1092, 0.7485, 0.1401],
            [0.2976, 0.3415, 0.6248],
            [0.7625, 0.6632, 0.7994],
            [0.8400, 0.1557, 0.6348]], device='cuda:0')
    
  • 使用tensor.to(device)方法將該tensor發送到目標設備,to方法接收的第一個參數為一個指定目標設備的字符串,第二個參數可以設置數據類型,默認為tensor原本的數據類型

    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    x = torch.rand(4,3,device=device)
    y = x.to("cpu")
    print(y)
    print(y.device)
    z = x.to("cpu",torch.double)
    print(z)
    print(z.device)
    print(z.dtype)
    

    tensor([[0.3537, 0.3610, 0.1814],
            [0.8401, 0.1496, 0.6197],
            [0.7640, 0.5794, 0.1897],
            [0.6594, 0.3619, 0.3482]])
    cpu
    tensor([[0.3537, 0.3610, 0.1814],
            [0.8401, 0.1496, 0.6197],
            [0.7640, 0.5794, 0.1897],
            [0.6594, 0.3619, 0.3482]], dtype=torch.float64)
    cpu
    torch.float64
    

需要注意的是,兩個張量之間如果發生運算,必須保證兩個張量在統一運算資源下,否則會報錯,所以有時需要通過上述方法進行調整。比如如下的代碼驗證了這一點:

x = torch.rand(3,2,device="cpu")
y = torch.rand(3,2,device="cuda")
try:
    z = x + y
except RuntimeError as e:
    print("Meet error because the two tensors aren't at the same device: \n{}".format(e))

Meet error because the two tensors aren't at the same device: 
Expected all tensors to be on the same device, but found at least two devices, cuda:0 and cpu!
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容