張量的建立與使用方法

Acapplella發表於2021-08-19

張量的建立及其基本型別

1.張量(Tensor)函式建立方法

  張量最基本的建立方法和Numpy中建立Array的格式一樣,都是建立函式(序列)的格式:張量建立函式: torch.tensor()

import torch 

# 通過列表建立張量
t = torch.tensor([1,2])

# 通過元組建立張量
t = torch.tensor((1,2))

import numpy as np

a = np.array((1,2))
# 通過陣列建立張量
t1 = torch.tensor(a)
"""
輸出結果為 tensor([1,2],dtype=torch.int32)
Point: 通過上述返回結果,我們發現張量也有dtype型別
"""

2.張量的型別

  張量和陣列類似,都有dtype方法,可返回張量型別.我們發現,整數型的陣列預設建立int32(整型)型別,而張量預設建立int64(長整型)型別。相對的,建立浮點型陣列時,張量預設是float32(單精度浮點型),而Array則是預設float64(雙精度浮點型)。除了數值型張量,常用的常量型別還有布林型張量,也就是構成張量的各個元素都是布林型別的張量。

3.張量型別的轉化

  • 張量型別的隱式轉化
      和NumPy中的Array相同,當張量各元素屬於不同型別時,系統會自動進行隱式轉化。
# 為了保證資料精度,傾向於統一轉化成資料精度比較高的
# 浮點型和整數型的隱式轉化
torch.tensor([1.1,2])

# 布林型和數值型的隱式轉化
torch.tensor([True,2.0])
  • 張量型別的轉化方法
      當然,我們還可以使用.float(),.int()等方法對張量型別進行轉化。
t = torch.tensor([1,2])

# 轉化為預設浮點型(32位)
t.float()

# 轉化為雙精度浮點型
t.double()

# 轉化為16位整數
t.short()

張量的維度及形變

  張量作為一組數的結構化表示,也同樣有維度的概念,簡單理解,向量就是一維的陣列,而矩陣則是二維的陣列,以此類推,在張量中,我們還可以定義更高維度的陣列。當然,張量的高維陣列和Numpy中的高維Array概念類似。

1.建立高維張量

  • 用簡單序列建立一維陣列
      包含"簡單"元素的序列可建立一維陣列。
t1 = torch([1,2])
t1 

# 使用ndim屬性檢視張量的維度
t1.ndim

# 使用shape檢視形狀
t1.shape

# 和size函式相同
t1.size()

注:和Numpy不同,PyTorch中的size方法返回結果和shape屬性返回結果一致。

此外,還需要注意有兩個常用的函式/方法,用來檢視張量的形狀。

# 返回有幾個(N-1)維元素
len(t1)

# 返回總共有幾個數
t1.numel()
  • 用"序列"的"序列"建立二維陣列
    以此類推,我們還可以用形狀相同的序列組成一個新的序列,進而將其轉化為二維張量
# 用list的list建立二維陣列
t2 = torch([[1,2],[3,4]])
  • 零維張量
    在PyTorch中,還有一類特殊的張量,被稱為零維張量。該型別只包含一個元素,但又不是單獨一個數。
t0 = torch.tensor([1])  # 這個仍然是一維張量
t0 = torch.tensor(1)    # 這個是零維張量

理解零維張量:
目前我們可以將零維張量視為擁有張量屬性的單獨的一個數。(例如: 張量可以存在GPU上,但Python的原生數值物件不行,但零維張量就可以,儘管是零維。)從學術名稱來說,Python中單獨的一個數是scalars(標量),而零維的張量則是tensor。

  • 高維張量
      一般來說,三維及三維以上的張量,我們就將其稱為高維張量。當然,在高維張量中,最常見的還是三維張量,我們可以將其理解為二維陣列或矩陣的集合。
a1 = np.array([[1,2,2],[3,4,4]])
a2 = np.array([[5,6,6],[7,8,8]])
t3 = torch.tensor([a1,a2])
t3.shape   # 結果為torch.Size([2,2,3])   包含兩個兩行三列的矩陣

當然,N維張量的建立方法,我們可以先建立M個N-1維的陣列,然後將其拼成一個N維的張量。關於更高維度的張量,我們將在後續遇到時再進行講解。在張量的學習過程中,三維張量就已經足夠。

2.張量的形變

  張量作為數字的結構化集合,其結構也是根據需求靈活調整的。

2.1 flatten拉平: 將任意維度張量轉化為一維張量

t2 = torch.tensor([[1,2]
                  ,[3,4]])
t2.flatten()   # 把張量按行排列拉平

2.2 reshape方法: 任意變形

t1 = tensor([1.2])
# 轉化為兩行一列的張量
t1.reshape(2,1)
"""
結果為: tensor([[1],[2]])
注意: reshape過程中維度的變化: reshape轉化後的維度由該方法輸入的引數"個數"決定
"""

特殊張量的建立方法

  在很多數值科學計算的過程中,都會建立一些特殊取值的張量,用於模擬特殊取值的矩陣,如全0矩陣,對角矩陣等.因此,PyTorch中也存在很多建立特殊張量的函式。

1.特殊取值的張量的建立方法

  • 全0張量
torch.tensor([2,3])  # 建立全是0的兩行三列的矩陣

注: 由於zeros就已經確定的張量元素的取值,因此該函式傳入的引數實際上是決定了張量的形狀

  • 全1張量
torch.ones([2,3])
  • 單位矩陣
# 返回五行五列的單位矩陣,對角線元素全為1
torch.eyes(5)
  • 對角矩陣
    略有特殊的是,在PyTorch中,需要利用一維張量取建立對焦矩陣。
t1 = torch.tensor([1,2])
torch.dialog(t1)
"""
輸出結果為: tensor([[1,0],
                   [0,2]])
"""
  • rand: 服從0-1均勻分佈的張量
torch.rand(2,3)
  • randn: 服從標準正態分佈的張量
torch.randn(2,3)
  • normal: 服從指定正態分佈的張量
torch.normal(2,3,size=(2,2))  # 均值為2,標準差為3的張量
  • randint: 整數隨機取樣結果
torch.randint(1,10,[2,4]) # 在1-10之間隨機抽取整數,組成兩行四列的矩陣
  • arrange/linsapce: 生成數列
torch.arrange(5)     # 和range相同
"""
結果為:
     tensor([0,1,2,3,4])
"""

torch.arraneg(1,5,0.5)    # 從1到5(左閉右開),每隔0.5取值一次

torch.linspace(1,5,3)     # 從1到5(左右都包含),等距取3個數
  • empty: 生成位初始化的指定形狀矩陣
torch。empty(2,3)
  • full: 根據指定形狀,填充指定數值
torch.full([2,4],2)

2.建立指定形狀的陣列

當然我們還能根據指定物件的形狀進行數值填充,只需要在上述函式後面加上_like即可。

t1 = torch.tensor([1,2])
t2 = torch.tensor([[1,2],[3,4]])
torch.full_like(t1,2)    # 根據t1形狀,填充數值2
torch.randint_like(t2,1,10)
torch.zeros_like(t1)

Ponint: (1)更多_like函式,可查閱幫助文件
(2)需要注意一點的是,_like型別轉化需要注意轉化前後資料型別一致的問題;

torch.rand_like(t1)     # t1是整數,而轉化後將變成浮點數,此時程式碼將報錯 

張量和其他型別的轉化方法

  張量,陣列和列表是較為相似的三種型別物件,在實際操作過程中,經常會涉及三種物件的相互轉化,在此之前張量的建立過程中,我們看到torch.tensor函式可以直接將陣列或者列表轉化為張量,而我們也可以將張量轉化為陣列或者列表。另外,前文介紹了0維張量的概念,此處也將進一步給出零維張量和數值物件的轉化方法。

  • numpy方法: 張量轉化為陣列
t1.numpy()
# 當然也可以通過np.array函式直接轉化為array
np.array(t1)
  • tolist方法: 張量轉化為列表
t1.tolist()
  • list函式: 張量轉化為列表
list(t1)

需要注意的是,此時轉化的列表是由一個個零維張量構成的列表,而非張量的數值轉化成的列表。

  • .item()方法: 轉化為數值
      在很多情況下,我們需要將最終計算的結果張量轉化為單獨的數值進行輸出,此時需要使用.item方法來執行。
n = torch.tensor(1)
n.item()

張量的深拷貝

  Python中其他物件型別一樣,等號賦值操作實際上是淺拷貝,需要進行深拷貝,則需要使用clone方法。

s = torch.tensor([1,2])
t = s.clone()

相關文章