torch竟然没有from scipy这种方法。。。。
真的是。。
idx , LongTensor, shape=(2,nnz)
val , FloatTensor, shape=(nnz)
shp, tuple,
s = torch.sparse.Tensor(idx,val,shp)
也可以直接传入一个dense tensor
a=torch.FloatTensor([1,2,3])
s=torch.sparse.FloatTensor(a)
to_sparse() , to_dense() 互转
a=torch.FloatTensor([1,2,3])
s= a.to_sparse()
a_ = s.to_dense()
torch.isclose(a,a_)
a=torch.FloatTensor([1,2,3])
s=torch.sparse.FloatTensor(a)
#这两个都是方法,不是属性。
idx = s.indices()
val = s.values()
#这个是属性
shp = s.shape
a.is_sparse , bool,每个Tensor都有的属性。
现在只有to_sparse_csr()
a=torch.FloatTensor([[1,0,3],[2,0,1],[0,1,0]])
c=a.to_sparse_csr()
print(c)
>tensor(crow_indices=tensor([0, 2, 4, 5]),
col_indices=tensor([0, 2, 0, 2, 1]),
values=tensor([1., 3., 2., 1., 1.]), size=(3, 3), nnz=5,
layout=torch.sparse_csr)
暂不支持to_sparse_coo
已经有人提issue了
https://github.com/pytorch/pytorch/issues/67654
然后这个人一直在努力实现csr_to_coo,花了一年时间…
https://github.com/pytorch/pytorch/pull/66774
我今天(22.01.17)看了一眼,最近一个commit是9天前(22.01.08)…
看了一下repo已经有这个函数了。
https://github.com/pytorch/pytorch/blob/67941c8a94e1731c1f33f37915d210ec244be589/torch/_tensor.py
tensor.to_sparse_coo()
但是服务器上的torch 1.10.1,这个功能还是没有实现。
‘Tensor’ object has no attribute ‘to_sparse_coo’
module ‘torch’ has no attribute ‘to_sparse_coo’
module ‘torch’ has no attribute ‘_convert_indices_from_csr_to_coo’
sparse只能跟scalar做四则运算。
加法支持scala或者同型矩阵。
同型矩阵仅支持Dense + Sparse。
add(sparse, dense) is not supported. Use add(dense, sparse) instead.
乘法只支持scala
mul(sparse, dense) is not supported
mul(dense, sparse) is not supported
除法只支持scala
RuntimeError: Sparse division requires a scalar or zero-dim dense tensor divisor (got shape [3, 3] for divisor)
经过个人测试,文档没写,但是支持**运算符。
而且sparse上的 幂运算,会自动将 inf 置为0。
a=torch.FloatTensor([1,0,2])
s=a.to_sparse()
s_ = s ** -1
print(s_)
>tensor(indices=tensor([[0, 2]]),
values=tensor([1.0000, 0.5000]),
size=(3,), nnz=2, layout=torch.sparse_coo)
#sparse上的幂运算自动重置inf
print(s_.to_dense())
>tensor([1.0000, 0.0000, 0.5000])
#做dense上的幂运算会出现inf
print(a**-1)
>tensor([1.0000, inf, 0.5000])
sparse库有自己的操作符。
直接对sparse tensor用torch operator会报错。
a=torch.FloatTensor([1,2,3])
s=a.to_sparse()
torch.sum(a) #正常
torch.sum(s) #报错
NotImplementedError: Could not run ‘aten::sum.IntList_out’ with arguments from the ‘SparseCPU’ backend. This could be because the operator doesn’t exist for this backend, or was omitted during the selective/custom build process (if using custom build).
If you are a Facebook employee using PyTorch on mobile, please visit https://fburl.com/ptmfixes for possible resolutions. ‘aten::sum.IntList_out’ is only available for these backends: [CPU, CUDA, Meta, BackendSelect, Python, Named, Conjugate, Negative, ADInplaceOrView, AutogradOther, AutogradCPU, AutogradCUDA, AutogradXLA, AutogradLazy, AutogradXPU, AutogradMLC, AutogradHPU, AutogradNestedTensor, AutogradPrivateUse1, AutogradPrivateUse2, AutogradPrivateUse3, Tracer, UNKNOWN_TENSOR_TYPE_ID, Autocast, Batched, VmapMode].
换成专用操作符就可以了
a=torch.FloatTensor([1,2,3])
s=a.to_sparse()
torch.sum(a) #正常
torch.sparse.sum(s) #正常
所以我们需要在使用的时候先判断一下
if x.is_sparse:
out = torch.sparse.sum(x)
else:
out = torch.sum(x)
问题来了,torch为什么不在torch.sum()里面自己集成一下判断???
直接让torch.sum支持sparse不行吗???
支持的操作符
torch.sparse.sum
torch.sparse.mm
torch.sparse.addmm
torch.sparse.softmax
torch.sparse.log_softmax
注意,sparse不支持mean
!!!
什么反人类设计。
可以自己写一个sparse_mean()
也不是很难啊。。。torch干嘛不搞。
coo 如果 出现重复的索引,默认累加该索引处的值
import scipy
import numpy as np
A = scipy.sparse.coo_matrix(
[[1., 0., 3.],
[2., 1., 1.],
[0., 1., 1.]])
row,col = A.row,A.col
val =A.data
#在坐标(1,1)处添加9
row2 = np.hstack([row,np.array(1)])
col2 = np.hstack([col,np.array(1)])
val2 = np.hstack([vals,np.array(9)])
A2 = scipy.sparse.coo_matrix((val2,(row2,col2)))
print(A2.A)
[[ 1. 0. 3.]
[ 2. 10. 1.]
[ 0. 1. 1.]]