这是一个可以复现的问题。
归根结底在于
torch不支持Sparse与Sparse的矩阵乘法(mm)。
也不支持Dense 与 Sparse的矩阵乘法。
只支持Sparse与Dense的矩阵乘法。
torch.mm是消边的矩阵乘法,mm= matrix multiply。
而torch.mul是同形矩阵的element-wise点乘。
所谓sparse是指torch.sparse.FloatTensor,torch.sparse.LongTensor等。
dense是指普通的torch.FloatTensor,torch.LongTensor等。
sparse可以通过to_dense()转为dense类型。
同样的dense也有to_sparse()方法。
不妨来做个实验。
import numpy as np
from scipy import sparse
import torch
def coo2torchsparse(A):
"""Convert scipy.sparse.coo_matrix to torch.sparse.FloatTensor by qq"""
if not sparse.issparse(A):
raise TypeError('input matrix should be scipy.sparse')
if not sparse.isspmatrix_coo(A):
A = A.tocoo()
v = torch.FloatTensor(A.data)
i = torch.LongTensor([A.row, A.col])
shape = torch.Size(A.shape)
res = torch.sparse.FloatTensor(i,v,shape)
return res
a=sparse.coo_matrix(np.zeros((3,5)))
b=sparse.coo_matrix(np.zeros((5,4)))
c=coo2torchsparse(a)
d=coo2torchsparse(b)
print(torch.typename(c),c.shape)
print(torch.typename(d),d.shape)
>输出
torch.sparse.FloatTensor torch.Size([3, 5])
torch.sparse.FloatTensor torch.Size([5, 4])
此时我们知道c和d都是sparse类型。
来验证他们能不能乘法。
可以选择的函数很多。
torch.mm(c,d) #等价于torch.matmul(c,d)
torch.sparse.mm(c,d)
torch._sparse_mm(c,d)
c.mm(d)
上述4条式子均报错RuntimeError: sparse tensors do not have strides
.
torch.mm(c.to_dense(),d)
torch.sparse.mm(c.to_dense(),d)
torch._sparse_mm(c.to_dense(),d)
c.to_dense().mm(d)
上述4条式子均报错RuntimeError: sparse tensors do not have strides
.
torch.mm(c,d.to_dense())
torch.sparse.mm(c,d.to_dense())
torch._sparse_mm(c,d.to_dense())
c.mm(d.to_dense())
上述4条式子均可正常运行。
至此我们知道了截止torch 1.6.0版本,只支持torch.mm(S,D)。
mm(S,S)或者 mm(D,S)都是不合法的。
事实上我们还得感谢这个进步。
翻阅github的issue可以看到,在2018年的时候就连这都没能支持。
https://github.com/pytorch/pytorch/issues/10043#issuecomment-442625201
害。