1. 程式人生 > 其它 >Tensor:Pytorch神經網路界的Numpy

Tensor:Pytorch神經網路界的Numpy

摘要:Tensor,它可以是0維、一維以及多維的陣列,你可以將它看作為神經網路界的Numpy,它與Numpy相似,二者可以共享記憶體,且之間的轉換非常方便。

本文分享自華為雲社群《Tensor:Pytorch神經網路界的Numpy》,作者: 擇城終老 。

Tensor

Tensor,它可以是0維、一維以及多維的陣列,你可以將它看作為神經網路界的Numpy,它與Numpy相似,二者可以共享記憶體,且之間的轉換非常方便。

但它們也不相同,最大的區別就是Numpy會把ndarray放在CPU中進行加速運算,而由Torch產生的Tensor會放在GPU中進行加速運算。

對於Tensor,從介面劃分,我們大致可分為2類:

  1. torch.function:如torch.sum、torch.add等。
  2. tensor.function:如tensor.view、tensor.add等。

而從是否修改自身來劃分,會分為如下2類:

  1. 不修改自身資料,如x.add(y),x的資料不變,返回一個新的Tensor。
  2. 修改自身資料,如x.add_(y),運算結果存在x中,x被修改。

簡單的理解就是方法名帶不帶下劃線的問題。

現在,我們來實現2個數組對應位置相加,看看其效果就近如何:

import torch

x = torch.tensor([1, 2])
y = torch.tensor([3, 4])
print(x 
+ y) print(x.add(y)) print(x) print(x.add_(y)) print(x)

執行之後,效果如下:

下面,我們來正式講解Tensor的使用方式。

建立Tensor

與Numpy一樣,建立Tensor也有很多的方法,可以自身的函式進行生成,也可以通過列表或者ndarray進行轉換,同樣也可以指定維度等。具體方法如下表(陣列即張量):

這裡需要注意Tensor有大寫的方法也有小寫的方法,具體效果我們先來看看程式碼:

import torch

t1 = torch.tensor(1)
t2 = torch.Tensor(1)
print("值{0},型別{1}
".format(t1, t1.type())) print("值{0},型別{1}".format(t2, t2.type()))

執行之後,效果如下:

其他示例如下:

import torch
import numpy as np

t1 = torch.zeros(1, 2)
print(t1)
t2 = torch.arange(4)
print(t2)
t3 = torch.linspace(10, 5, 6)
print(t3)
nd = np.array([1, 2, 3, 4])
t4 = torch.from_numpy(nd)
print(t4)

其他例子基本與上面基本差不多,這裡不在贅述。

修改Tensor維度

同樣的與Numpy一樣,Tensor一樣有維度的修改函式,具體的方法如下表所示:

示例程式碼如下所示:

import torch

t1 = torch.Tensor([[1, 2]])
print(t1)
print(t1.size())
print(t1.dim())
print(t1.view(2, 1))
print(t1.view(-1))
print(torch.unsqueeze(t1, 0))
print(t1.numel())

執行之後,效果如下:

擷取元素

當然,我們建立Tensor張量,是為了使用裡面的資料,那麼就不可避免的需要獲取資料進行處理,具體擷取元素的方式如表:

示例程式碼如下所示:

import torch

# 設定隨機數種子,保證每次執行結果一致
torch.manual_seed(100)
t1 = torch.randn(2, 3)
# 列印t1
print(t1)
# 輸出第0行資料
print(t1[0, :])
# 輸出t1大於0的資料
print(torch.masked_select(t1, t1 > 0))
# 輸出t1大於0的資料索引
print(torch.nonzero(t1))
# 獲取第一列第一個值,第二列第二個值,第三列第二個值為第1行的值
# 獲取第二列的第二個值,第二列第二個值,第三列第二個值為第2行的值
index = torch.LongTensor([[0, 1, 1], [1, 1, 1]])
# 取0表示以行為索引
a = torch.gather(t1, 0, index)
print(a)
# 反操作填0
z = torch.zeros(2, 3)
print(z.scatter_(1, index, a))

執行之後,效果如下:

我們a = torch.gather(t1, 0, index)對其做了一個圖解,方便大家理解。如下圖所示:

當然,我們直接有公司計算,因為這麼多資料標線實在不好看,這裡博主列出轉換公司供大家參考:

當dim=0時,out[i,j]=input[index[i,j]][j]
當dim=1時,out[i,j]=input[i][index[i][j]]

簡單的數學運算

與Numpy一樣,Tensor也支援數學運算。這裡,博主列出了常用的數學運算函式,方便大家參考:

需要注意的是,上面表格所有的函式操作均會建立新的Tensor,如果不需要建立新的,使用這些函式的下劃線"_"版本。

示例如下:

t = torch.Tensor([[1, 2]])
t1 = torch.Tensor([[3], [4]])
t2 = torch.Tensor([5, 6])
# t+0.1*(t1/t2)
print(torch.addcdiv(t, 0.1, t1, t2))
# t+0.1*(t1*t2)
print(torch.addcmul(t, 0.1, t1, t2))
print(torch.pow(t,3))
print(torch.neg(t))

執行之後,效果如下:

上面的這些函式都很好理解,只有一個函式相信沒接觸機器學習的時候,不大容易理解。也就是sigmoid()啟用函式,它的公式如下:

歸併操作

簡單的理解,就是對張量進行歸併或者說合計等操作,這類操作的輸入輸出維度一般並不相同,而且往往是輸入大於輸出維度。而Tensor的歸併函式如下表所示:

示例程式碼如下所示:

t = torch.Tensor([[1, 2]])
t1 = torch.Tensor([[3], [4]])
t2 = torch.Tensor([5, 6])
# t+0.1*(t1/t2)
print(torch.addcdiv(t, 0.1, t1, t2))
# t+0.1*(t1*t2)
print(torch.addcmul(t, 0.1, t1, t2))
print(torch.pow(t,3))
print(torch.neg(t))

執行之後,效果如下:

需要注意的是,sum函式求和之後,dim的元素個數為1,所以要被去掉,如果要保留這個維度,則應當keepdim=True,預設為False。

比較操作

在量化交易中,我們一般會對股價進行比較。而Tensor張量同樣也支援比較的操作,一般是進行逐元素比較。具體函式如下表:

示例程式碼如下所示:

t = torch.Tensor([[1, 2]])
t1 = torch.Tensor([[3], [4]])
t2 = torch.Tensor([5, 6])
# t+0.1*(t1/t2)
print(torch.addcdiv(t, 0.1, t1, t2))
# t+0.1*(t1*t2)
print(torch.addcmul(t, 0.1, t1, t2))
print(torch.pow(t,3))
print(torch.neg(t))

執行之後,輸出如下:

矩陣運算

機器學習與深度學習中,存在大量的矩陣運算。與Numpy一樣常用的矩陣運算一樣,一種是逐元素相乘,一種是點積乘法。函式如下表所示:

這裡有3個主要的點積計算需要區分,dot()函式只能計算1維張量,mm()函式只能計算二維的張量,bmm只能計算三維的矩陣張量。示例如下:

# 計算1維點積
a = torch.Tensor([1, 2])
b = torch.Tensor([3, 4])
print(torch.dot(a, b))
# 計算2維點積
a = torch.randint(10, (2, 3))
b = torch.randint(6, (3, 4))
print(torch.mm(a, b))
# 計算3維點積
a = torch.randint(10, (2, 2, 3))
b = torch.randint(6, (2, 3, 4))
print(torch.bmm(a, b))

執行之後,輸出如下:

點選關注,第一時間瞭解華為雲新鮮技術~