1. 程式人生 > 實用技巧 >Pytorch | 詳解Pytorch科學計算包——Tensor

Pytorch | 詳解Pytorch科學計算包——Tensor

本文始發於個人公眾號:TechFlow,原創不易,求個關注

今天是Pytorch專題的第二篇,我們繼續來瞭解一下Pytorch中Tensor的用法。

上一篇文章當中我們簡單介紹了一下如何建立一個Tensor,今天我們繼續深入Tensor的其他用法

tensor操作

size()和shape

我們可以用size()函式或者直接呼叫tensor當中的shape屬性獲取一個tensor的大小,這兩者是等價的,一般情況下我們用前者多一些。

view

我們可以通過view改變一個tensor的shape,它會根據我們指定的shape返回一個新的tensor

需要注意的是,view返回的是原資料的一個引用

,也就是說我們改變原資料,view出來的結果會同樣發生變化。

在上面這個例子當中,我們把原tensor x中的[0, 1]的位置修改成了2,我們print y會發現y當中的元素同樣發生了變化。

numel

我們可以用numel獲取tenosr當中元素的數量:

squeeze和unsqueeze

我們可以用squeeze來減少tensor的維度,而使用unsqueeze來增加一個tenor的維度

其中unsqueeze接收一個引數,允許我們指定我們希望增加的維度。我們可以通過size明顯看到資料的變化:

squeeze是減少維度,相比之下沒有那麼多操作,它會自動將長度是1的維度消除,如果沒有一個維度長度是1,也就是說當前已經是最簡的形式,那麼什麼也不會變化。

也支援使用另一個陣列作為索引訪問資料:

Tensor索引

Tensor當中支援與Numpy陣列類似的索引操作,語法也非常相似。和Numpy一樣,索引得到的結果是原資料的引用,也就是說我們修改其中一個,另一個也會跟著發生變動。

它支援多維索引:

也支援切片:

也可以通過bool陣列獲取元素:

Tensor運算

Tensor當中有大量的運算api,我們只列舉其中最常用的幾種,剩下的使用頻率不高,大家可以用到的時候再去查閱相應的檔案。

加減乘除

Tensor當中支援好幾種運算的方法,我們以加法為例來瞭解一下。首先支援通過符號直接運算:

第二種方法是我們可以呼叫torch當中的函式,比如加法的函式就是add。

如果使用torch當中的函式進行計算的話,它還支援out引數,允許我們傳入一個tensor,它會將計算結果儲存tensor當中。

除此之外,它還允許我們進行inplace操作,也就是在原tensor值的基礎上直接修改,而不是通過函式值返回。和Numpy當中傳入inplace引數的設計不同,Tensor當中是通過api區分的,在原函式名下增加一個下劃線即是inplace的api,比如add的inplace方法是add_。

矩陣點乘

在機器學習領域當中,矩陣點乘是一個經常用到的操作。因為為了節省時間,我們通常會把樣本和特徵以及各類引數向量化,通過矩陣或者是向量點乘的形式來進行加權求和、線性變換等操作。所以矩陣點乘非常重要,必定會用到。

在Numpy當中我們通過dot函式來計算兩個矩陣之間的內積,而在Tensor當中做了嚴格的區分,只有一維的向量才可以使用dot計算點乘,多維的向量只能使用matmul計算矩陣的乘法。為了簡化,還可以使用mm來代替matmul。如果你學過TensorFlow的話,你會發現matmul是TensorFlow當中點乘的api,Pytorch當中沿用了這個命名。

可以看到,mm和matmul計算得到的結果是一致的。

型別轉換

在Numpy當中,我們通過astype方法轉換型別,而在Tensor當中將這個方法拆分,每一種型別都有自己的轉化函式

比如我們想要將tensor轉化成int型別,呼叫的是int()方法,想要轉化成float型別呼叫的是float()方法。呼叫這些方法之後,會返回一個新的tensor。

Tensor當中定義了7種CPU型別和8種GPU型別:

我們可以呼叫內建函式將它們互相轉化,這些轉換函式有:long(), half(), int(), float(), double(), byte(), char(), short()。我相信這些函式的含義大家應該都可以理解。

轉置與變形

Tensor當中的轉置操作和Numpy中不太相同,在Numpy當中,我們通過.T或者是transpose方法來進行矩陣的轉置。如果是高維陣列進行轉置,那麼Numpy會將它的維度完全翻轉。

而在Tensor當中區分了二維陣列和高維陣列,二維陣列的轉置使用的函式是t(),它的用法和.T一樣,會將二維陣列的兩個軸調換。

如果是高維陣列呼叫t函式會報錯,如果我們要變換高維陣列的形狀,可以呼叫transpose和permute兩個方法。先說transpose方法,它接收兩個int型引數,表示需要調換的兩個軸。比如一個形狀是[4, 3, 2]的矩陣,我們可以通過0,1,2表示它的所有軸,傳入兩個,指定想要調換的兩個軸:

而permute可以調換多個軸的位置,所以它接受的引數是一個int型的不定引數。我們傳入我們希望得到的軸的順序,Tensor會根據我們傳入的軸的順序對資料進行翻轉:

另外,t和transpose支援inplace操作,而permute不行,這也是他們顯著的區別之一。

裝置之間移動

我們可以通過device這個屬性看到tensor當前所在的裝置:

我們可以通過cuda函式將一個在CPU的tensor轉移到GPU,但是不推薦這麼幹。比較好的辦法是使用to方法來進行裝置轉移

將tensor轉移到GPU上進行計算可以利用GPU的併發效能提升計算的效率,這是Pytorch當中常用的手段。to方法不僅可以改變tensor的裝置,還可以同時變更tensor當中元素的型別:

總結

雖然tensor擁有許多額外的功能和計算函式,但是tensor的意義並不僅僅如此。最重要的是,它可以提升我們的計算速度。這當中的原理也很簡單,因為在Python的List當中,每一個元素其實都是一個物件。即使我們儲存的是一個int或者是float,Python都會將它們封裝成一個物件,這會帶來額外的開銷。如果只是少量的資料影響不大,如果是上百萬甚至是更大的量級,那麼兩者的差距就會非常大。另外一點就是tensor庫的底層也是C和C++,執行效率顯然Python更高。所以我們不能簡單地把它理解成一個計算包,對於深度學習來說,它並不僅僅只是計算。

Tensor當中還有許多其他的方法,這其中許多實用頻率很低加上篇幅的限制,我們不能一一窮盡,大家只需要對Tensor庫整體有一個映像,一些具體的使用方法和細節可以用到的時候再進行查詢。

本文基於滴滴雲GPU完成,租借滴滴雲GPU,使用滴滴雲AI大師碼2323,享受9折優惠。

如果喜歡本文,可以的話,請點個關注,給我一點鼓勵,也方便獲取更多文章。

本文使用 mdnice 排版