pytorch學習筆記2

注:本文是筆者結合自己閱讀和使用pytorch的經驗,又系統學習了一遍https://github.com/chenyuntc/pytorch-book的過程中,將自己認爲有必要掌握和記住的知識整理成的學習筆記,並非系統的教程,主要目的是爲了方便自己梳理、記憶知識,以及方便有相同需求的讀者查閱某些知識。

逐元素操作

1、在pytorch中,不僅僅針對逐元素的操作,tensor的計算往往具有兩種形式,比如torch.mul(a, b)與a.mul(b)二者是等價的

2、記住這些逐元素運算對應的符號:

絕對值 / 平方根 / 取模 / 求冪 / 乘法 / 除法 / 以e爲底求指數 / 取ln / 向上取整 / 向下取整 / 四捨五入 / 取整數部分 / 取小數部分 / 正弦 / 餘弦 

abs / sqrt / fmod / pow / mul / div / exp / log / ceil / floor / round / trunc / frac / sin / cos

3、mul和div表示的是逐元素乘或逐元素除,不要把mul和矩陣乘搞混了;mul和div在pytorch中被重載爲了*和/,也就是說*和/表示的是逐元素乘或者逐元素除,不要把*和矩陣乘搞混了;另外,mul和div要求參與運算的要麼是形狀完全一致的兩個tensor,要麼是前者是一個tensor,而後者是一個數字

4、取對數只有torch.log(),torch.log2(),torch.log10(),其他底可以換底公式換出來;求指數exp默認以e爲底,但是torch.pow很靈活,假如a = torch.tensor([1,2,3]),既可以torch.pow(a,2)表示tensor([1^2,2^2,3^2]),也可以torch.pow(2,a)表示tensor([2^1,2^2,2^3])。

5、逐元素操作還有torch.sigmoid和torch.tanh等激活函數,但是這些激活函數在torch.nn中也存在

歸併操作

1、記住這些歸併操作對應的符號:

均值 / 求和 / 中位數 / 衆數 / 範數 / 歐式距離 /  標準差 / 方差

mean / sum / median / mode / norm / dist / std / var

2、使用歸併操作的時候需要考慮兩個參數,dim和keep_dim,當這兩個參數都被設置的時候,輸出的形狀如下:

假設輸入形狀爲(m, n, k),那麼根據不同的dim和keep_dim得到的tensor形狀如下表

  keep_dim=True keep_dim=False
dim=0 (1, n, k) (n, k)
dim=1 (m, 1, k) (m, k)
dim=2 (m, n, 1) (m, n)

 

3、如果不指定dim,那麼得到的會是一個只有一個元素的tensor,比如tensor(100);如果不指定keep_dim,keep_dim默認爲False

4、對於dim的理解:假設輸入的tensor A形狀爲(m, n, k),假設做的是求和操作,且指定dim=1,根據2,得到的tensor B的形狀是(m, k),A和B滿足B_[i, j] = \sum_{t=0}^{n}A_[i, k, j]

In [1]: a = t.arange(24)
In [2]: b = a.view(2, 3, 4)
In [3]: b
Out[3]: tensor([[[ 0,  1,  2,  3],
                 [ 4,  5,  6,  7],
                 [ 8,  9, 10, 11]],

                [[12, 13, 14, 15],
                 [16, 17, 18, 19],
                 [20, 21, 22, 23]]])
In [4]: c = t.sum(b, dim=1)
In [5]: c, c.size()
Out[5]: (tensor([[12, 15, 18, 21],
                 [48, 51, 54, 57]]), torch.Size([2, 4]))

比較操作

1、gt(大於)/  lt(小於)/  ge(大於等於)/ le(小於等於)/ eq(等於)/ ne(不等於),這些分別被重載爲了> / < / >= / <= / == / !=,需要注意的是前面提到過的一點,兩個tensor通過比較操作得到的是一個ByteTensor(即dtype=torch.uint8),這種tensor是可以以mask的方式直接作爲同形狀tensor的索引的

2、torch.max和torch.min的使用,以torch.max爲例,根據參數不同共有三種用法

(1) torch.max(tensor)       返回的是隻含一個元素的tensor,這個元素是輸入tensor中最大的元素

(2)torch.max(tensor, dim)      返回指定維上較大的數,以及其所在下標;torch.max在這種輸入和上一種輸入放在一起看,可以看做是一個歸併操作,只是多返回一個較大數所在的下標

(2)torch.max(tensor, tensor)      要求輸入的兩個tensor同形狀,輸出也是同形狀的,輸出的每個位置對應的是兩個tensor中那個位置上較大的數

In [1]: a = t.randn(2, 3)
In [2]: a
Out[2]: tensor([[ 1.0437,  0.6610, -0.1947],
                [-1.7523,  1.7876,  0.6388]])
In [3]: b = t.randn(2, 3)
Out[3]: tensor([[-0.3039,  1.0680, -0.2654],
                [ 0.5515, -1.3597, -0.8332]])
In [4]: t.max(a)
Out[4]: tensor(1.7876)
In [5]: t.max(a, dim=1) # 注意輸出是一個元組,分別是較大的數和所在的下標
Out[5]: (tensor([1.0437, 1.7876]), tensor([0, 1]))
In [6]: t.max(a, b)
Out[6]: tensor([[ 1.0437,  1.0680, -0.1947],
                [ 0.5515,  1.7876,  0.6388]])

3、torch.topk(input, k, dim=None, largest=True, sorted=True)

參數

input(Tensor)

k(int)

dim(int):假設輸入的tensor A形狀是(m, n, p),且dim=1,做topk之後得到的tensor B的形狀是(m, k, p),其中B[i,:,j]中的k個元素是A[i,:,j]中n個元素中挑出的前k個;不指定dim時,dim默認爲最後一維

largest(Boolean):默認爲True,爲True表示取前k大,爲False表示取前k小

sorted(Boolean):默認爲True,假設挑出的是前k大,爲True時這k個元素按從大到小的順序排序,爲False時只是保證是前k大,並不一定有序

輸出:輸出一個tuple,裏面是兩個tensor,前一個tensor是topk的元素,後一個tensor是topk的下標,這兩個tensor是同形狀的。假設輸入的tensor形狀爲(p, q, m),k=K,dim=1,largest和sorted爲True,那麼輸出的這兩個tensor形狀均爲(p, K, m)。

In [1]: a = t.randn(2, 3)
In [2]: a
Out[2]: tensor([[ 0.5339,  0.2233,  2.5735],
                [-2.0343, -1.5293, -0.1112]])
In [3]: b = t.topk(a, k=2, dim=1)
In [4]: b
Out[4]: (tensor([[ 2.5735,  0.5339],
                 [-0.1112, -1.5293]]), 
        tensor([[2, 0],
                [2, 1]]))
In [5]: c = t.topk(a, k=1, dim=0)
In [6]: c
Out[6]: ( tensor([[0.5339, 0.2233, 2.5735]]), tensor([[0, 0, 0]]) )

4、torch.sort(input, dim=-1, descending=False)

參數

input(Tensor)

dim(int):假設輸入的tensor A的形狀爲(m, n, p),且dim=1,那麼排序後的得到的tensor B中,B[i, :, j]是排序後的A[i, :, j],不顯式指定時dim默認爲最後一維

descending(Boolean):默認爲False,爲False時元素升序排列,否則降序排列

輸出:輸出一個tuple,裏面有兩個tensor,前一個是排序的結果,後一個是排序後tensor對應排序前的下標,兩個tensor是同形狀的。假設輸入tensor的形狀爲(m, n, p),則輸出的兩個tensor都是(m, n, p)的。

In [1]: a = t.randn(2, 3)
In [2]: a
Out[2]: tensor([[-0.1060, -0.2755,  1.2596],
                [ 1.2688,  0.1467, -0.4233]])
In [3]: t.sort(a, dim=0)
Out[3]: (tensor([[-0.1060, -0.2755, -0.4233],
                 [ 1.2688,  0.1467,  1.2596]]),
         tensor([[0, 0, 1],
                 [1, 1, 0]]))
In [4]: t.sort(a, dim=1)
Out[4]: (tensor([[-0.2755, -0.1060,  1.2596],
                 [-0.4233,  0.1467,  1.2688]]), 
         tensor([[1, 0, 2],
                 [2, 1, 0]]))

線性代數

1、矩陣轉置

對於一個2D的tensor A,A.t()得到其轉置,需要注意的是轉置後空間不再連續,需要調用.contiguous()方法令其連續

2、mm和bmm和matmul

(1) mm:兩個2D的tensor A和B相乘,其中A的形狀是(n, p),B的形狀是(p, m),輸出的形狀是(n, m)

(2) bmm:兩個3D的tensor A和B相乘,其中A的形狀是(batch_size, n, p),B的形狀是(batch_size, p, m),輸出的形狀是(batch_size , n, m),一個batch裏的每個矩陣對應相乘

(3) matmul:根據參與運算的兩個tensor A和B的形狀,有很多種情況,但記憶的時候可以分四類記:

①A和B都是1D的tensor(向量)時,返回的是向量的內積;

②A和B分別是2D的n*p和p*m的矩陣時,返回的矩陣乘法的結果(n*m的矩陣);

③A和B分別是3D的batch_size*n*p和batch_size*p*m的矩陣時,返回的是每個batch中對應矩陣相乘的結果(batch_size*n*m的矩陣)

④其餘情況均是A和B維數不等的情況,此時根據廣播法則來確定計算方法

廣播機制

1、廣播機制在pytorch和numpy中均是存在的,廣播機制指的是在下面的兩個條件成立時,會自動擴展一個向量進行運算:

(1)兩個tensor之間進行的操作是一個逐元素操作(當然,大於小於這類比較也算)

(2)兩個tensor的維度中尾部的幾個維度是一樣的,如果tensor A的形狀是(Adim1, Adim2, ..., AdimN),tensor B的形狀是(Bdim1, Bdim2, ..., BdimM),維度中尾部的幾個維度一致是指Adim(N-M+1)=Bdim1, Adim(N-M+2)=Bdim2, ..., AdimN=BdimM

In [1]: a = t.arange(24).view(2, 3, 4)
In [2]: a
Out[2]: tensor([[[ 0,  1,  2,  3],
                 [ 4,  5,  6,  7],
                 [ 8,  9, 10, 11]],

                [[12, 13, 14, 15],
                 [16, 17, 18, 19],
                 [20, 21, 22, 23]]])
In [3]: b = t.ones(4, dtype=t.int64)
In [4]: a + b
Out[4]: tensor([[[ 1,  2,  3,  4],
                 [ 5,  6,  7,  8],
                 [ 9, 10, 11, 12]],

                [[13, 14, 15, 16],
                 [17, 18, 19, 20],
                 [21, 22, 23, 24]]])

2、但是,在pytorch中,許多非逐元素的操作也是支持廣播機制的,比如上面提到的matmul操作:對於兩個參與運算的tensor A和B,如果他們的維數不相等(情況④),那麼首先在維數較短的tensor(假設是B)前面補1使得維數一致,然後把B擴展爲之前的幾份使得補1位置的形狀與tensor A一致,最後如果A和B符合的①②③中的任一條,那麼就可以進行運算

In [1]: a = t.randn(3, 4)
In [2]: b = t.randn(4)
In [3]: t.matmul(a, b).size()
Out[3]: torch.Size([3])
In [4]: a = t.randn(10, 3, 4)
In [5]: b = t.randn(4, 5)
In [6]: t.matmul(a, b)
Out[6]: torch.Size([10, 3, 5])
In [7]: a = t.randn(2, 10, 3, 4)
In [8]: b = t.randn(4, 5)
In [9]: t.matmul(a, b)
Out[9]: torch.Size([2, 10, 3, 5])

 

tensor和numpy對象轉換

1、如果a是numpy對象,可以用b = t.Tensor(a)或b = t.tensor(a)得到tensor,注意前者ab共享內存,後者是拷貝得到不共享內存

2、如果a是tensor對象,可以用b = a.numpy()得到numpy對象,此時ab共享內存

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章