2.3 核心資料結構——Tensor
張量初認識
經過前兩小節的鋪墊,大家一定對pytorch有了初步認識,本小節就展開講pytorch的核心資料結構——Tensor(張量)。Tensor 中文被翻譯為張量。張量在不同學科中有不同的意義,在深度學習中張量表示的是一個多維陣列,它是標量、向量、矩陣的拓展。標量是零維張量,向量是一維張量,矩陣是二維張量,一個RGB圖像的陣列就是一個三維張量,第一維是圖像的高,第二維是圖像的寬,第三維是圖像的顏色通道。
在pytorch中,有兩個張量的相關概念極其容易混淆,分別是torch.Tensor和torch.tensor。其實,通過命名規範,可知道torch.Tensor是Python的一個類, torch.tensor是Python的一個函數。通常我們調用torch.tensor進行創建張量,而不直接調用torch.Tensor類進行創建。為了進一步區分兩者,我們來看看它們代碼實現。
torch.Tensor:類定義與torch/_tensor.py#L80,它繼承torch._C._TensorBase,這裡看到_C就知道要接觸C++代碼了。
跳轉到torch/C/\_init__.pyi #L839 可以看到:
# Defined in torch/csrc/autograd/python_variable.cpp
class _TensorBase(metaclass=_TensorMeta):
requires_grad: _bool
shape: Size
Copy
張量的定義和底層C++實現是在python_variable.cpp代碼中,感興趣的朋友可以進一步探究。
torch.tensor:pytorch的一個函數,用於將資料變為張量形式的資料,例如list, tuple, NumPy ndarray, scalar等。
同樣,torch.tensor的底層實現也是C++代碼,具體實現位於torch_C_VariableFunctions.pyi文件。如2.1節所述,.pyi檔用於Python類型檢查,而其底層實現在對應的C++代碼中。
後續將不再區分Tensor和tensor,主要用小寫tensor表示張量這個資料類型(資料結構)。
張量的作用
tensor之于pytorch等同于ndarray之於numpy,它是pytorch中最核心的資料結構,用於表達各類資料,如輸入資料、模型的參數、模型的特徵圖、模型的輸出等。這裡邊有一個很重要的資料,就是模型的參數。對於模型的參數,我們需要更新它們,而更新操作需要記錄梯度,梯度的記錄功能正是被張量所實現的(求梯度是autograd實現的)。
張量的歷史演變
講tensor結構之前,還需要介紹一小段歷史,那就是Variable與Tensor。在0.4.0版本之前,Tensor需要經過Variable的包裝才能實現自動求導。從0.4.0版本開始,torch.Tensor與torch.autograd.Variable合併,torch.Tensor擁有了跟蹤歷史操作的功能。雖然Variable仍可用,但Variable返回值已經是一個Tensor(原來返回值是Variable),所以今後無需再用Variable包裝Tensor。
雖然Variable的概念已經被摒棄,但是瞭解其資料結構對理解Tensor還是有幫助的。Variable不僅能對Tensor包裝,而且能記錄生成Tensor的運算(這是自動求導的關鍵)。在Variable類中包含5個屬性:data,grad,grad_fn,is_leaf,requires_grad
- data: 保存的是具體資料,即被包裝的Tensor;
- grad: 對應於data的梯度,形狀與data一致;
- grad_fn: 記錄創建該Tensor時用到的Function,該Function在反向傳播計算中使用,因此是自動求導的關鍵;
- requires_grad: 指示是否計算梯度;
- is_leaf: 指示節點是否為葉子節點,為葉子結點時,反向傳播結束,其梯度仍會保存,非葉子結點的梯度被釋放,以節省記憶體。
從Variable的主要屬性中可以發現,除了data外,grad,grad_fn,is_leaf和requires_grad都是為計算梯度服務,所以Variable在torch.autogard包中自然不難理解。
但是我們的資料載體是tensor,每次需要自動求導,都要用Variable包裝,這明顯太過繁瑣,於是PyTorch從0.4.0版將torch.Tensor與torch.autograd.Variable合併。
張量的結構
tensor是一個類,我們先來認識它有哪些屬性,再去觀察它有哪些方法函數可使用。
Tensor主要有以下八個主要屬性,data,dtype,shape,device,grad,grad_fn,is_leaf,requires_grad。
- data:多維陣列,最核心的屬性,其他屬性都是為其服務的;
- dtype:多維陣列的資料類型,tensor資料類型如下,常用到的三種已經用紅框標注出來;
- shape:多維陣列的形狀;
- device: tensor所在的設備,cpu或cuda;
- grad,grad_fn,is_leaf和requires_grad就與Variable一樣,都是梯度計算中所用到的。
張量的屬性還有很多,大家可以通過Pycharm的debug功能進行查看
更多關於張量的概念背景,請查看官方文檔,下一小節,我們進行張量的操作介紹。
留言列表