|  | .. currentmodule:: torch.sparse | 
|  |  | 
|  | .. _sparse-docs: | 
|  |  | 
|  | torch.sparse | 
|  | ============ | 
|  |  | 
|  | .. warning:: | 
|  |  | 
|  | This API is in beta and may change in the near future. | 
|  |  | 
|  | Torch supports sparse tensors in COO(rdinate) format, which can | 
|  | efficiently store and process tensors for which the majority of elements | 
|  | are zeros. | 
|  |  | 
|  | A sparse tensor is represented as a pair of dense tensors: a tensor | 
|  | of values and a 2D tensor of indices.  A sparse tensor can be constructed | 
|  | by providing these two tensors, as well as the size of the sparse tensor | 
|  | (which cannot be inferred from these tensors!)  Suppose we want to define | 
|  | a sparse tensor with the entry 3 at location (0, 2), entry 4 at | 
|  | location (1, 0), and entry 5 at location (1, 2).  We would then write: | 
|  |  | 
|  | >>> i = torch.LongTensor([[0, 1, 1], | 
|  | [2, 0, 2]]) | 
|  | >>> v = torch.FloatTensor([3, 4, 5]) | 
|  | >>> torch.sparse.FloatTensor(i, v, torch.Size([2,3])).to_dense() | 
|  | 0  0  3 | 
|  | 4  0  5 | 
|  | [torch.FloatTensor of size 2x3] | 
|  |  | 
|  | Note that the input to LongTensor is NOT a list of index tuples.  If you want | 
|  | to write your indices this way, you should transpose before passing them to | 
|  | the sparse constructor: | 
|  |  | 
|  | >>> i = torch.LongTensor([[0, 2], [1, 0], [1, 2]]) | 
|  | >>> v = torch.FloatTensor([3,      4,      5    ]) | 
|  | >>> torch.sparse.FloatTensor(i.t(), v, torch.Size([2,3])).to_dense() | 
|  | 0  0  3 | 
|  | 4  0  5 | 
|  | [torch.FloatTensor of size 2x3] | 
|  |  | 
|  | You can also construct hybrid sparse tensors, where only the first n | 
|  | dimensions are sparse, and the rest of the dimensions are dense. | 
|  |  | 
|  | >>> i = torch.LongTensor([[2, 4]]) | 
|  | >>> v = torch.FloatTensor([[1, 3], [5, 7]]) | 
|  | >>> torch.sparse.FloatTensor(i, v).to_dense() | 
|  | 0  0 | 
|  | 0  0 | 
|  | 1  3 | 
|  | 0  0 | 
|  | 5  7 | 
|  | [torch.FloatTensor of size 5x2] | 
|  |  | 
|  | An empty sparse tensor can be constructed by specifying its size: | 
|  |  | 
|  | >>> torch.sparse.FloatTensor(2, 3) | 
|  | SparseFloatTensor of size 2x3 with indices: | 
|  | [torch.LongTensor with no dimension] | 
|  | and values: | 
|  | [torch.FloatTensor with no dimension] | 
|  |  | 
|  | SparseTensor has the following invariants: | 
|  | 1. sparse_dim + dense_dim = len(SparseTensor.shape) | 
|  | 2. SparseTensor._indices().shape = (sparse_dim, nnz) | 
|  | 3. SparseTensor._values().shape = (nnz, SparseTensor.shape[sparse_dim:]) | 
|  |  | 
|  | Since SparseTensor._indices() is always a 2D tensor, the smallest sparse_dim = 1. | 
|  | Therefore, representation of a SparseTensor of sparse_dim = 0 is simply a dense tensor. | 
|  |  | 
|  | .. note:: | 
|  |  | 
|  | Our sparse tensor format permits *uncoalesced* sparse tensors, where | 
|  | there may be duplicate coordinates in the indices; in this case, | 
|  | the interpretation is that the value at that index is the sum of all | 
|  | duplicate value entries. Uncoalesced tensors permit us to implement | 
|  | certain operators more efficiently. | 
|  |  | 
|  | For the most part, you shouldn't have to care whether or not a | 
|  | sparse tensor is coalesced or not, as most operations will work | 
|  | identically given a coalesced or uncoalesced sparse tensor. | 
|  | However, there are two cases in which you may need to care. | 
|  |  | 
|  | First, if you repeatedly perform an operation that can produce | 
|  | duplicate entries (e.g., :func:`torch.sparse.FloatTensor.add`), you | 
|  | should occasionally coalesce your sparse tensors to prevent | 
|  | them from growing too large. | 
|  |  | 
|  | Second, some operators will produce different values depending on | 
|  | whether or not they are coalesced or not (e.g., | 
|  | :func:`torch.sparse.FloatTensor._values` and | 
|  | :func:`torch.sparse.FloatTensor._indices`, as well as | 
|  | :func:`torch.Tensor.sparse_mask`).  These operators are | 
|  | prefixed by an underscore to indicate that they reveal internal | 
|  | implementation details and should be used with care, since code | 
|  | that works with coalesced sparse tensors may not work with | 
|  | uncoalesced sparse tensors; generally speaking, it is safest | 
|  | to explicitly coalesce before working with these operators. | 
|  |  | 
|  | For example, suppose that we wanted to implement an operator | 
|  | by operating directly on :func:`torch.sparse.FloatTensor._values`. | 
|  | Multiplication by a scalar can be implemented in the obvious way, | 
|  | as multiplication distributes over addition; however, square root | 
|  | cannot be implemented directly, since ``sqrt(a + b) != sqrt(a) + | 
|  | sqrt(b)`` (which is what would be computed if you were given an | 
|  | uncoalesced tensor.) | 
|  |  | 
|  | .. class:: FloatTensor() | 
|  |  | 
|  | .. method:: add | 
|  | .. method:: add_ | 
|  | .. method:: clone | 
|  | .. method:: dim | 
|  | .. method:: div | 
|  | .. method:: div_ | 
|  | .. method:: get_device | 
|  | .. method:: hspmm | 
|  | .. method:: mm | 
|  | .. method:: mul | 
|  | .. method:: mul_ | 
|  | .. method:: narrow_copy | 
|  | .. method:: resizeAs_ | 
|  | .. method:: size | 
|  | .. method:: spadd | 
|  | .. method:: spmm | 
|  | .. method:: sspaddmm | 
|  | .. method:: sspmm | 
|  | .. method:: sub | 
|  | .. method:: sub_ | 
|  | .. method:: t_ | 
|  | .. method:: to_dense | 
|  | .. method:: transpose | 
|  | .. method:: transpose_ | 
|  | .. method:: zero_ | 
|  | .. method:: coalesce | 
|  | .. method:: is_coalesced | 
|  | .. method:: _indices | 
|  | .. method:: _values | 
|  | .. method:: _nnz | 
|  |  | 
|  | Functions | 
|  | ---------------------------------- | 
|  |  | 
|  | .. autofunction:: torch.sparse.addmm | 
|  | .. autofunction:: torch.sparse.mm | 
|  | .. autofunction:: torch.sparse.sum |