Question: Constructing a sparse matrix
See original GitHub issueHow can I make a function like this work with autograd, given that assignment is forbidden?
def func(a, b): # a and b are scalars
m = np.zeros((10, 10))
m[5,7] = a
m[3,6] = b
return m
Issue Analytics
- State:
- Created 6 years ago
- Comments:9 (6 by maintainers)
Top Results From Across the Web
Sparse Matrix and its representations | Set 1 (Using Arrays ...
Representing a sparse matrix by a 2D array leads to wastage of lots of memory as zeroes in the matrix are of no...
Read more >A Gentle Introduction to Sparse Matrices for Machine Learning
The sparse matrix is represented using three one-dimensional arrays for the non-zero values, the extents of the rows, and the column indexes. ...
Read more >Sparse matrix - Wikipedia
In numerical analysis and scientific computing, a sparse matrix or sparse array is a matrix in which most of the elements are zero....
Read more >Create sparse matrix - MATLAB sparse - MathWorks
If any of the inputs i,j or m,n are larger than 2^31-1 for 32-bit platforms, or 2^48-1 on 64-bit platforms, then the sparse...
Read more >Creating sparse matrix from dense matrix without initializing ...
Basically a sparse matrix is created from arrays of row coordinates, column coordinates, and corresponding values. There are variations for ...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Here are two ways to do it. Because
func
is a linear map, you can implement it in a sparse matrix form treatinga
andb
as coefficients on fixed basis elements:If the indices (5, 7) and (3, 6) are really constants (or you’re going to call
func
many times with the same values for those indices) you can make that more efficient with staged evaluation, so that the basis elements aren’t re-allocated on every invocation.Another way to do it is to write your own primitive, which is probably both more straightforward and more performant:
Inside a primitive, there are no autograd boxed values; everything is raw numpy, so you’re back in the world you’re used to. You have to define any vjp’s you need for your primitives, though.
When writing custom primitives,
check_grads
is your friend!Side notes: of course, you only need to do this if you’re going to differentiate through
func
. Assignment into autograd’s ArrayNodes is not supported, but when you’re usingautograd.numpy
, ArrayNodes are only created as necessary during tracing, i.e. when anautograd.numpy
function gets an ArrayNode as one of its arguments; otherwise, it’s just raw numpy as usual. In fact, the kind of assignment you wrote might work anyway, sincem
is being created as a zeros matrix and won’t be an ArrayNode, though whena
orb
is an ArrayNode, the assignment would have to turn it into an array with dtype object and things might get weird.If you are differentiating with respect to
a
andb
directly, rather than them being some intermediates in the computation, you can also get them both at once (without redoing the forward pass or backward pass) usingmultigrad
, which is in convenience_wrappers.py. Check out that file, since there is a lot of functionality in there.You can also do the same thing manually by writing a function that takes an
(a, b)
tuple argument instead of separate arguments (since autograd will happily differentiate with respect to a tuple argument).