PyTorch——Tensor的相關概念及操作


Tensor的概念

說起張量(tensor)就不得不說他和scalar、vertor、matrix之間的關系了,直接上圖:

標量(scalar):只有大小概念,沒有方向的概念。通過一個具體的數值就能表達完整。比如:重量、溫度、長度、提及、時間、熱量等都數據標量。

向量(vector):物理學上也叫矢量,指由大小和方向共同決定的量(跟「標量」相區別)。向量主要有2個維度:大小、方向。比如:力、速度等

矩陣(matrix):(學過線性代數的都知道,可參見之前的線代筆記

張量(tensor):一個多維數組,它是標量、向量、矩陣的高位擴展 

當下主流的深度網絡學習框架是PyTorch和Tensorflow。

對於這兩個框架而言,我只想用一句代碼來闡述我心中的雜亂: 

Import torch as tf               

但是,我還是選擇了PyTorch( ^_^ /\  ~_~ )

tensor,是PyTorch中最基礎的數據類型,也是進行數據存儲和運算的基本單元。

數組array這個概念,數組是類似於列表的高階對象,是有序的元素序列。

Tensor在PyTorch的地位相當於Array在Numpy中地位。

實質上Pytorch將Numpy的Array包裝成Tensor,為其定義了各種各樣的運算方法和函數

以至於處理tensor的時候,覺得自己在調用Numpy和Pandas這兩個包處理。

Tensor的屬性

每一個tensor都有三個屬性:torch.dtype,torch.device,torch.layout.

torch.dtype

Pytorch擁有12個不同的數據類型。

 tensor類型 相關代碼

>>> float_tensor = torch.ones(1, dtype=torch.float) >>> double_tensor = torch.ones(1, dtype=torch.double) >>> complex_float_tensor = torch.ones(1, dtype=torch.complex64) >>> complex_double_tensor = torch.ones(1, dtype=torch.complex128) >>> int_tensor = torch.ones(1, dtype=torch.int) >>> long_tensor = torch.ones(1, dtype=torch.long) >>> uint_tensor = torch.ones(1, dtype=torch.uint8) >>> double_tensor = torch.ones(1, dtype=torch.double) >>> bool_tensor = torch.ones(1, dtype=torch.bool) >>> long_zerodim = torch.tensor(1, dtype=torch.long) >>> int_zerodim = torch.tensor(1, dtype=torch.int) >>> torch.add(5, 5).dtype torch.int64 >>> (int_tensor + 5).dtype torch.int32 >>> (int_tensor + long_zerodim).dtype torch.int32 >>> (long_tensor + int_tensor).dtype torch.int64 >>> (bool_tensor + long_tensor).dtype torch.int64 >>> (bool_tensor + uint_tensor).dtype torch.uint8 >>> (float_tensor + double_tensor).dtype torch.float64 >>> (complex_float_tensor + complex_double_tensor).dtype torch.complex128 >>> (bool_tensor + int_tensor).dtype torch.int32 >>> torch.add(long_tensor, float_tensor).dtype torch.float32

torch.device

 由於pytorch可以在Gpu上運行tensor的相關操作。

torch.device是一個對象,表示正在或將要分配 torch.tensor的設備。

torch.device一半可選的內容有 cpu,cuda或者一些設備類型的可選設備序號

>>> torch.device('cuda:0') device(type='cuda', index=0) >>> torch.device('cpu') device(type='cpu') >>> torch.device('cuda') # current cuda device device(type='cuda')
>>> torch.device('cuda', 0) device(type='cuda', index=0) >>> torch.device('cpu', 0) device(type='cpu', index=0)

torch.layout

torch.layout 是表示 torch.tensor 的內存布局的對象。目前,torch.tensor支持torch.strided(密集張量)和sparse_coo(稀疏的COO張量)。

 

stride()方法其實指的就是,tensor每個維度變化1在實際物理存儲空間變化的大小。

>>> x = torch.tensor([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]) >>> x.stride() (5, 1) >>> x.t().stride() (1, 5)

 Tensor的創建與訪問

Tensor的創建方式

  • 可以根據數據、元組、NumPy的ndarray、標量和其他類型,來構建tensor。方法有:torch.tensor()、torch.ones()、torch.zeros()、torch.from_array()...
  • 也可以從一些分布中采樣構建新的張量:torch.arange()、torch.range()、torch.rand()、torch.randn()、torch.normal()...
  • 當然也有一些比較特殊的搭建:torch.eye()用於構建一個對角矩陣

Tensor的訪問方式

  • 當tensor是標量或者一維數據的時候,可以使用torch.item()訪問
  • 當tensor是多維數據的時候,可以使用索引的方式,用法類似於a[:,0,0]
  • 當然我們也可以使用掩膜的方式,固定的訪問一些我們想要的數據。
X = torch.randn((2,3))
mask = torch.randn((2,3))>0
X1 = X[mask]
X2 = torch.masked_select(X,mask)

  •  還有條件選擇這種不錯的方式,也是一個值得推薦的方式。
x = torch.randn(1, 3)
y = torch.randn(1, 3)
z = torch.where(x>y,x,y)

Tensor的簡單操作

常用數學運算

  • torch.add():加法
  • torch.mul():乘法
  • torch.div():除法
  • torch.abs():tensor內每個元素取絕對值
  • torch.round():tensor內每個元素取整數部分
  • torch.frac():tensor內每個元素取小數部分
  • torch.log():tensor內每個元素取對數
  • torch.pow():tensor內每個元素取冪函數
  • torch.exp():tensor內每個元素取指數
  • torch.sigmoid():tensor內每個元素取sigmoid函數值
  • torch.mean():tensor所有元素的均值
  • torch.norm():tensor所有元素的范數值
  • torch.prod():tensor所有元素積
  • torch.sum():tensor所有元素和
  • torch.max():tensor所有元素最大值
  • torch.min():tensor所有元素最小值

注意:例如add()這類函數一般都是會返回一直tensor值的,但是add_()這類加了下划線的方法是在tensor的原空間處理的,會覆蓋之前的值

同樣也可以是用以下方式直接處理

  1. 加 tensor1 + tensor2;
  2. 減 tensor1 - tensor2;
  3. 乘 tensor1 * tensor2;
  4. 除 tensor1 / tensor2;
  5. 內積 tensor1 @ tensor2;
  6. 冪運算 tensor1 ** n

線性代數運算

  • torch.dot():向量內積運算
  • torch.mv():矩陣與向量的乘法
  • torch.mm():矩陣乘法
  • torch.eig():方陣的特征值和特征向量
  • torch.inverse():方陣的逆
  • torch.ger():兩個向量的張量積

Tensor連接、分片、變形

  • torch.cat():多個tensor的拼接
  • torch.reshape()\torch.view():返回一個張量,其數據和元素數量與輸入相同,但具有指定的形狀
  • torch.transpose()\torch.t():指定tensor的兩個維度進行轉置,torch.t()方法只適用與二維tensor
  • torch.squeeze()/unsqueeze():tensor對於張量中大小為1的維度的壓縮與擴張
  • torch.permute():返回維度排列后的原始張量輸入的視圖。

說到計算就不得不說,tensor 的一種計算機制,BroadCasting。在一定條件下,他會使維度不同、維度大小同的tensor完成數學計算

以A+B為例,Broadcasting的過程如下: 從A,B的最后一個維度開始匹配長度,如果該維度長度一致,則匹配前一個維度。如果某個維度的長度不一致,並且兩者長度都>1,那么維度不匹配,無法進行運算,如果有一個長度維1,那么就對該維度進行擴展(廣播),擴展后的兩個維度長度一致。依次類推直到第一個維度。如果兩個張量維度不同,則在第0維進行升維並做廣播。

粗略的來說,就是利用squeeze()方法使低維的數據升到高維的數據,再利用cat()方法拼接成同樣的大小。(前提是,該維度長度為1,或者沒有維度才可以)

下面這張圖就可以很清晰的表達BroadCasting的效果。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM