在深度學習中,軸,指的就是張量的層級,一般通過參數axis/dim來設定。很多張量的運算、神經網絡的構建,都會涉及到軸,但到底取哪個軸,卻不是那麼容易把握。
下面會針對軸/axis/dim,基于 Pytorch 的代碼和實例,嘗試去理清張量運算中軸/axis/dim的設定。
軸的概念對于一個張量,它的shape有幾維,就對應有幾個軸,也就對應着張量的層級,最直觀的可以通過看最前面的方括号數量來判斷。
import torch
a = torch.Tensor([[1,2,3], [4,5,6]])
b = torch.Tensor([[7,8,9], [10,11,12]])
c = torch.Tensor([[[1,2,3], [4,5,6]], [[7,8,9], [10,11,12]]])
print(a.shape)
# torch.Size([2, 3])
上面的張量 a 和 b,都對應兩個軸。axis/dim=0 對應 shape [2, 3] 中的2,axis/dim=1 對應 shape [2, 3] 中的3,而張量 c 有三個軸。
張量運算時對軸參數的設定非常常見,在 Numpy 中一般是參數axis,在 Pytorch 中一般是參數dim,但它們含義是一樣的。
軸的使用在做張量的拼接操作時,axis/dim設定了哪個軸,那對應的軸在拼接之後張量數會發生變化
>> torch.cat((a,b), dim=0)
tensor([[ 1., 2., 3.],
[ 4., 5., 6.],
[ 7., 8., 9.],
[10., 11., 12.]])
>> torch.cat((a,b), dim=1)
tensor([[ 1., 2., 3., 7., 8., 9.],
[ 4., 5., 6., 10., 11., 12.]])
對于上面torch中的cat操作,當設定dim=0時,兩個維度是(2,3)的張量合并成了一個(4,3)的張量,在第0維,張量數從2變成了4,第1維沒有變化;當設定dim=1時,在第1維,張量數從3變成了6,第0維沒有變化。
在做張量的運算操作時,axis/dim設定了哪個軸,就會遍曆這個軸去做運算,其他軸順序不變
>> torch.softmax(a, dim=0)
tensor([[0.0474, 0.0474, 0.0474],
[0.9526, 0.9526, 0.9526]])
>> torch.softmax(a, dim=1)
tensor([[0.0900, 0.2447, 0.6652],
[0.0900, 0.2447, 0.6652]])
對于上面torch中的 softmax 操作,當設定 dim=0 時,就是其他軸不變,單次遍曆 dim=0 軸的所有元素去做運算,上例中就相當于分别取了張量a中的第0列、第1列、第2列去做計算。
換一個角度,假設用for循環去遍曆一個張量,那運算中設定的dim就是被放在最内層的for循環,其它的軸保持正常的順序。
可以用下面的例子作為驗證,這裡tensor c 的shape 是 (m,n,p),用for循環去計算 torch.softmax(c, dim=1)
# for循環計算方式
c = torch.Tensor([[[1,2,3], [4,5,6]], [[7,8,9], [10,11,12]]]) # shape (2,2,3)
m,n,p = c.shape
res = torch.zeros((m,n,p))
for i in range(m):
for j in range(p):
res[i,:,j] = torch.softmax(torch.tensor([c[i,k,j] for k in range(n)]), dim=0) #這裡對應最内層的for循環
# 庫函數設定軸計算方式
res1 = torch.softmax(c, dim=1)
print(res.equal(res1)) # True
axis/dim使用小總結:
實際上,第一條拼接操作也可以用第二條去理解,但拼接的軸張量數會發生變化更好理解和記憶。
軸的實例其實一個軸設定的變化,會帶來很大的差異,最典型的就是 BatchNorm 和 LayerNorm 了。
BatchNorm 和 LayerNorm 是針對數據的不同軸去做norm,假設輸入數據的維度是(N,C,H,W),分别對應batch數,核數,高,寬,BatchNorm 就對應dim=0,LayerNorm 就對應dim=1,在不考慮移動平均等具體細節問題時,兩者在形式上可以統一,隻有一個dim參數的差别。
Pytorch 的實現(簡化版)如下:
class Norm(nn.Module):
def __init__(self, num_features, variance_epsilon=1e-12):
super(Norm, self).__init__()
self.gamma = nn.Parameter(torch.ones(num_features))
self.beta = nn.Parameter(torch.zeros(num_features))
self.variance_epsilon = variance_epsilon # 一個很小的常數,防止除0
def forward(self, x, dim):
u = x.mean(dim, keepdim=True)
s = (x - u).pow(2).mean(dim, keepdim=True)
x_norm = (x - u) / torch.sqrt(s self.variance_epsilon)
return self.gamma * x_norm self.beta
當然,不僅僅是在深度學習裡面,在 Numpy,Pandas中,軸的設定都經常會遇到,但它們都是相通的,希望本文能幫你更好的理解它 —> 軸。
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!