deeplearning4j-examples icon indicating copy to clipboard operation
deeplearning4j-examples copied to clipboard

Example showing standard linear algebra decompositions and solver

Open lessthanoptimal opened this issue 4 years ago • 11 comments

Issue Description

I'm in the process of adding ND4J to a Java linear algebra benchmark but I'm having trouble adding decompositions like, Cholesky, QR, SVD, Eigen, ... etc or solving for square or rectangular systems. Could examples be added for these operations? I was able to find example code for matrix multiplication and element-wise operations just fine. I can see the JavaDoc for these operations but it's fairly opaque. Thanks.

lessthanoptimal avatar Sep 29 '20 03:09 lessthanoptimal

/cc @rcorbish

saudet avatar Sep 29 '20 03:09 saudet

bump. I'll be updating the benchmark soon and would like to include this library. Thanks

lessthanoptimal avatar Oct 21 '20 16:10 lessthanoptimal

@lessthanoptimal all the docs has been gathered under Deeplearning4J (DL4J). API: https://deeplearning4j.org/api/latest/ "Guide": https://deeplearning4j.konduit.ai/operation-namespaces/linalg

It's a bit underwhelming, but the API isn't too hard to figure out through the use of the guide (even though it might not be the best documented guide it shows the methods).

As you can see Cholesky, QR, SVD (svd) & more exists in the linalg guide. Not sure if actually eigen exists (see: https://github.com/eclipse/deeplearning4j/issues/6764)

Lundez avatar Jan 19 '21 07:01 Lundez

I'm working on this now and even after looking at those links I would consider this to be excessively difficult. So let's turn this discussion into documentation for ND4J. Could someone (maybe @Lundez ) provide simple code example for how to compute a Cholesky decomposition.

To make this easier for your users I would add these simple examples to https://deeplearning4j.konduit.ai/operation-namespaces/linalg . Right now, by looking at the functions in Cholesky, I can see where I specify the inputs, get the outputs, but I don't see a function which screams "compute" or know if the inputs are modified or not, as they are in some implementations of Cholesky.

lessthanoptimal avatar Jan 30 '21 18:01 lessthanoptimal

@lessthanoptimal hi again, I'll take a look later this week to confirm how it's done.

I know nd4j & benchmarking is not always the easiest where the result could be optimized sometimes by using r-major rather than c-major and so on on top of the usual JVM optimizations with GC / warm-up etc. I think it makes sense to use the default operations while benchmarking, because the benchmark should be how a user uses it and not a professional ND4J-user, right? 😄

Lundez avatar Feb 01 '21 08:02 Lundez

@lessthanoptimal Hi,

Sorry for taking such time, but been busy at work (recently joined a new team). 😅

Anyhow, ND4J is not always the clearest, they use Executioners to execute operations on the INDArrays, at least when it comes to transformations such as Cosine Distance, SVD & Cholesky. All of these implement XYZOp which in turn implements BaseOp and further Op.

In the Transforms they've got some wrappers for common usecases, such as cosineSim to make it simpler to use. Unfortunately Cholesky is not included and as such you need to call the executioner yourself.

val someMatrix = Nd4j.createFromArray(arrayOf(
            arrayOf(19f,-3f,-3f),
            arrayOf(-3f,19f,15f),
            arrayOf(-3f,15f,13f),
        ))

val choleskyOp = Cholesky(someMatrix)
val choleskyDecomposition = Nd4j.getExecutioner().exec(choleskyOp).toList()
println(choleskyDecomposition)

Please note that this is in Kotlin and not Java, so some minor updates might be required. The toList() is added to make the print nicer (Array/[] is not pretty 😅)


Finally, ND4J has started adding a new API through the SameDiff with their SDVariable's. I haven't wrapped my head around it really, but my feeling is that the INDArray is still as relevant as ever and that the SDVariable is more to be used for Neural Networks & integration with tensorflow.

I hope this was helpful 😄

Lundez avatar Feb 06 '21 10:02 Lundez

Thanks! I've got more of it filled out with a bunch of educated guesses. There's a numerical stability test (which needs to be fixed) that should tell me if I coded it up correctly. As you mentioned before, the only ops I couldn't figure out was Eigenvalue Decomposition. That means ND4J will get dinged in the summary plots.

Do you know if there's any way to programically get the library's version? I'm hard coding it by hand right now.

lessthanoptimal avatar Feb 16 '21 19:02 lessthanoptimal

Do you know if there's any way to programically get the library's version?

What do you mean? I always use gradle to build/include libraries. I found the latest version through https://mvnrepository.com/artifact/org.nd4j/nd4j-native I guess I've hard-coded it also, not sure how else you'd do it?

Lundez avatar Feb 17 '21 08:02 Lundez

Some libraries provide a way to get the version at runtime from the jar. In EJML I use this library that I wrote that autogenerates the code from Gradle

https://github.com/lessthanoptimal/gversion-plugin

Having said that, I guess I could write some Gradle code to dump the version of all its dependencies at compile time instead of trying to determine it at runtime.

lessthanoptimal avatar Feb 18 '21 03:02 lessthanoptimal

@lessthanoptimal I believe this is what VersionCheck.getVersions() is for: https://github.com/eclipse/deeplearning4j/blob/master/nd4j/nd4j-backends/nd4j-api-parent/nd4j-api/src/main/java/org/nd4j/versioncheck/VersionCheck.java#L271

saudet avatar Feb 18 '21 03:02 saudet

Working on the benchmark again and just posted new results, but needed to leave out ND4J since it's still incomplete. Anyone know how to do ~cholesky~ inverse of a SPD matrix or eigenvalue decompositions? I think that's all that's missing now.

lessthanoptimal avatar Jan 06 '22 00:01 lessthanoptimal