[英]Multiply a 3d tensor with a 2d matrix using torch.matmul
我在 PyTorch 中有兩個張量, z
是 3d 形狀的張量(n_samples, n_features, n_views)
其中n_samples
是數據集中的樣本數, n_features
是每個樣本的特征數, n_views
是描述相同(n_samples, n_features)
特征矩陣但具有其他值的視圖。
我有另一個二維張量b
,形狀為(n_samples, n_views)
,其目的是在不同視圖中重新縮放樣本的所有特征。 換句話說,它封裝了同一樣本的每個視圖的特征的重要性。 例如:
import torch
z = torch.Tensor(([[2,3], [1,1], [4,5]],
[[2,2], [1,2], [7,7]],
[[2,3], [1,1], [4,5]],
[[2,3], [1,1], [4,5]]))
b = torch.Tensor(([1, 0],
[0, 1],
[0.2, 0.8],
[0.5, 0.5]))
print(z.shape, b.shape)
>>>torch.Size([4, 3, 2]) torch.Size([4, 2])
由於z
和b
之間的操作,我想獲得形狀為(n_samples, n_features)
的第三張量r
。 一種可能的解決方案是:
b = b.unsqueeze(1)
r = z * b
r = torch.sum(r, dim=-1)
print(r, r.shape)
>>>tensor([[2.0000, 1.0000, 4.0000],
[2.0000, 2.0000, 7.0000],
[2.8000, 1.0000, 4.8000],
[2.5000, 1.0000, 4.5000]]) torch.Size([4, 3])
是否可以使用torch.matmul()
實現相同的結果? 我曾多次嘗試置換兩個向量的尺寸,但無濟於事。
是的,這是可能的。 如果您在兩個操作中都有多個批量維度,則可以使用廣播。 在這種情況下,每個操作數的最后兩個維度被解釋為矩陣大小。 (我建議在文檔中查找它。)
因此,您需要為向量b
增加一個維度,以使它們成為nx 1
“矩陣”(列向量):
# original implementation
b1 = b.unsqueeze(1)
r1 = z * b1
r1 = torch.sum(r1, dim=-1)
print(r1.shape)
# using torch.matmul
r2 = torch.matmul(z, b.unsqueeze(2))[...,0]
print(r2.shape)
print((r1-r2).abs().sum()) # should be zero if we do the same operation
或者, torch.einsum
也使這變得非常簡單。
# using torch.einsum
r3 = torch.einsum('ijk,ik->ij', z, b)
print((r1-r3).abs().sum()) # should be zero if we do the same operation
einsum
是一個非常強大的操作,可以做很多事情:你可以置換張量維度,對它們求和,或者執行標量產品,所有這些都可以有或沒有廣播。 它源自物理學中最常用的愛因斯坦求和約定。 粗略的想法是,您為操作符的每個維度命名,然后使用這些名稱定義 output 的外觀。 我認為最好閱讀文檔。 在我們的例子中,我們有一個4 x 3 x 2
張量和一個4 x 2
張量。 所以我們稱第一個張量ijk
的維度。 這里i
和k
應該被認為與第二張量的維度相同,所以這個可以描述為ik
。 最后 output 應該清楚地是ij
(它必須是4 x 3
張量)。 從這個“簽名” ijk, ik -> ij
可以清楚地看出,維度i
被保留,並且維度k
必須“相加/相乘”(標量積)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.