<?xml version="1.0" encoding="utf-8"?> 
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
 <title type="text">SHRIPHANI PALAKODETY: Posts tagged 'thin-svd'</title>
 <link rel="self" href="http://blog.shriphani.com/feeds/thin-svd.atom.xml" />
 <link href="http://blog.shriphani.com/tags/thin-svd.html" />
 <id>urn:http-blog-shriphani-com:-tags-thin-svd-html</id>
 <updated>2014-11-28T11:16:15Z</updated>
 <entry>
  <title type="text">Implementing Truncated Matrix Decompositions for Core.Matrix</title>
  <link rel="alternate" href="http://blog.shriphani.com/2014/11/28/implementing-truncated-matrix-decompositions-for-core-matrix/?utm_source=thin-svd&amp;utm_medium=Atom" />
  <id>urn:http-blog-shriphani-com:-2014-11-28-implementing-truncated-matrix-decompositions-for-core-matrix</id>
  <published>2014-11-28T11:16:15Z</published>
  <updated>2014-11-28T11:16:15Z</updated>
  <author>
   <name>SHRIPHANI PALAKODETY</name></author>
  <content type="html">&lt;html&gt;
&lt;p&gt;Eigendecompositions and Singular Value Decompositions appear in a variety of settings in machine learning and data mining. The eigendecomposition looks like so:&lt;/p&gt;

&lt;div&gt;$$ \mathbf{A}=\mathbf{Q}\mathbf{\Lambda}\mathbf{Q}^{-1} $$&lt;/div&gt;

&lt;p&gt;$ \mathbf{Q} $ contains the eigenvectors of $ \mathbf{A} $ and $ \mathbf{\Lambda} $ is a diagonal matrix containing the eigenvalues.&lt;/p&gt;

&lt;p&gt;The singular value decomposition looks like:&lt;/p&gt;

&lt;div&gt;$$ \mathbf{A} = \mathbf{U} \boldsymbol{\Sigma} \mathbf{V}^* $$&lt;/div&gt;

&lt;p&gt;$ \mathbf{U} $ contains the eigenvectors of the covariance matrix $ \mathbf{A}\mathbf{A^T} $. $ \mathbf{V} $ contains the eigenvectors of the gram matrix $ \mathbf{A^T}\mathbf{A} $.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;truncated&lt;/strong&gt; variants of these decompositions allow us to compute only a few eigenvalues(vectors) or singular values (vectors).&lt;/p&gt;

&lt;p&gt;This is important since (i) a lot of times, the smaller eigenvalues are discarded, and (ii) you don&amp;rsquo;t want to compute the entire decomposition and retain only a few of the rows and columns of the computed matrices each time.&lt;/p&gt;

&lt;p&gt;For core.matrix, I implemented these truncated decompositions in &lt;a href="http://github.com/shriphani/kublai"&gt;Kublai&lt;/a&gt;. Details below.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;For large matrices , on consumer grade hardware (like your laptop), it is near impossible to compute a full decomposition. If your algorithm performs a decomposition per iteration, then things get worse.&lt;/p&gt;

&lt;p&gt;The excellent &lt;a href="http://www.caam.rice.edu/software/ARPACK/"&gt;ARPACK library&lt;/a&gt; implements an efficient truncated SVD that is leveraged by several popular numerical libraries like the popular Python library &lt;a href="http://scikit-learn.org/stable/"&gt;scikit learn&lt;/a&gt; and &lt;a href="https://spark.apache.org/"&gt;Apache Spark&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ARPACK&amp;rsquo;s eigendecomposition is not tied to any particular matrix  library.&lt;/strong&gt; You only need to supply a routine that multiplies a vector  with the input matrix (which ARPACK uses for its  &lt;a href="http://en.wikipedia.org/wiki/Power_iteration"&gt;power-iteration&lt;/a&gt;  step).&lt;/p&gt;

&lt;p&gt;Clojure&amp;rsquo;s budding matrix library &lt;code&gt;core.matrix&lt;/code&gt; implements both the eigen and singular value decompositions but doesn&amp;rsquo;t contain a truncated version.&lt;/p&gt;

&lt;p&gt;In this post, I will describe how I used the ARPACK library to implement these truncated decompositions for &lt;code&gt;core.matrix&lt;/code&gt;. The resulting implementation is independent of the particular implementation of &lt;code&gt;core.matrix&lt;/code&gt; being used.&lt;/p&gt;

&lt;p&gt;While the details of the post are tied to &lt;code&gt;core.matrix&lt;/code&gt;, the lessons can be transferred to other numerical libraries in other languages.&lt;/p&gt;

&lt;p&gt;The excellent &lt;a href="https://github.com/fommil/netlib-java"&gt;netlib library&lt;/a&gt; provides a clean java interface to the ARPACK library (which is implemented in FORTRAN).&lt;/p&gt;

&lt;p&gt;I will assume that you have ARPACK installed on your machine. If so, netlib will be able to invoke ARPACK.&lt;/p&gt;

&lt;h3 id="truncated-eigendecomposition"&gt;Truncated Eigendecomposition:&lt;/h3&gt;

&lt;p&gt;There are a symmetric eigendecomposition that I have currently implemented (and a non-symmetric version is on the way).&lt;/p&gt;

&lt;p&gt;Invoking the truncated eigendecompositon routine is trival:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;
  &lt;p&gt;Call the  &lt;code&gt;&lt;a href="http://www.caam.rice.edu/software/ARPACK/UG/node136.html"&gt;DSAUPD&lt;/a&gt;&lt;/code&gt;  routine (for symmetric matrices. Use  &lt;a href="http://www.caam.rice.edu/software/ARPACK/UG/node137.html"&gt;DNEUPD&lt;/a&gt;  for the opposite)  till the &lt;code&gt;IDO&lt;/code&gt; flag is set to 99.&lt;/p&gt;&lt;/li&gt;
 &lt;li&gt;
  &lt;p&gt;Once this is done, the eigen vectors and values can be retrieved by  a call to  &lt;code&gt;&lt;a href="http://www.caam.rice.edu/software/ARPACK/UG/node40.html"&gt;DSEUPD&lt;/a&gt;&lt;/code&gt;.  The eigenpairs are returned in ascending order of eigenvalues.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;And that&amp;rsquo;s it. There are a few flags that tell you if there are fatal errors which you need to check that the docs for &lt;code&gt;DSAUPD&lt;/code&gt; and &lt;code&gt;DSEUPD&lt;/code&gt; contain.&lt;/p&gt;

&lt;h3 id="truncated-singular-value-decomposition"&gt;Truncated Singular Value Decomposition:&lt;/h3&gt;

&lt;p&gt;The truncated SVD can just invoke the eigendecomposition on the gram and covariance matrices. No ARPACK calls are needed here.&lt;/p&gt;

&lt;p&gt;The implementation for both the decompositions is available in this &lt;a href="https://github.com/shriphani/kublai"&gt;github repository&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id="usage"&gt;Usage&lt;/h3&gt;

&lt;p&gt;This module can be used in the following fashion:&lt;/p&gt;

&lt;p&gt;For computing symmetric eigendecompositions:&lt;/p&gt;

&lt;div class="brush: clojure"&gt;
 &lt;table class="sourcetable"&gt;
  &lt;tbody&gt;
   &lt;tr&gt;
    &lt;td class="linenos"&gt;
     &lt;div class="linenodiv"&gt;
      &lt;pre&gt; 1
 2
 3
 4
 5
 6
 7
 8
 9
10&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;
    &lt;td class="code"&gt;
     &lt;div class="source"&gt;
      &lt;pre&gt;&lt;span class="nv"&gt;user&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def &lt;/span&gt;&lt;span class="nv"&gt;M&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;matrix&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]]))&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="ss"&gt;&amp;#39;user/M&lt;/span&gt;
&lt;span class="nv"&gt;user&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;kublai.core&lt;/span&gt; &lt;span class="ss"&gt;:reload-all&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;nil&lt;/span&gt;
&lt;span class="nv"&gt;user&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;eigs&lt;/span&gt; &lt;span class="nv"&gt;M&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="ss"&gt;:symmetric&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;;; compute 2 eigenvectors for this matrix&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:Q&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mf"&gt;-0.22593827269074584&lt;/span&gt; &lt;span class="mf"&gt;-0.4432218615090191&lt;/span&gt; &lt;span class="mf"&gt;-0.5727878807113498&lt;/span&gt; &lt;span class="mf"&gt;-0.6514754961809404&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0.7253136654558885&lt;/span&gt; &lt;span class="mf"&gt;0.3184697313242928&lt;/span&gt; &lt;span class="mf"&gt;0.1424607347013554&lt;/span&gt; &lt;span class="mf"&gt;-0.5934661371986827&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;, &lt;span class="ss"&gt;:A&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mf"&gt;24.06253512439672&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt; &lt;span class="mf"&gt;-0.8054849155764637&lt;/span&gt;&lt;span class="p"&gt;]]}&lt;/span&gt;
&lt;span class="nv"&gt;user&amp;gt;&lt;/span&gt; 
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;For computing a truncated SVD:&lt;/p&gt;

&lt;div class="brush: clojure"&gt;
 &lt;table class="sourcetable"&gt;
  &lt;tbody&gt;
   &lt;tr&gt;
    &lt;td class="linenos"&gt;
     &lt;div class="linenodiv"&gt;
      &lt;pre&gt; 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;
    &lt;td class="code"&gt;
     &lt;div class="source"&gt;
      &lt;pre&gt;&lt;span class="nv"&gt;user&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def &lt;/span&gt;&lt;span class="nv"&gt;M&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;matrix&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;]]))&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="ss"&gt;&amp;#39;user/M&lt;/span&gt;
&lt;span class="nv"&gt;user&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;svd&lt;/span&gt; &lt;span class="nv"&gt;M&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:U&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mf"&gt;-0.13472212372225584&lt;/span&gt; &lt;span class="mf"&gt;0.8257420598345273&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;-0.3407576960799602&lt;/span&gt; &lt;span class="mf"&gt;0.4288172018031381&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;-0.5467932684376645&lt;/span&gt; &lt;span class="mf"&gt;0.03189234377176592&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;-0.7528288407953688&lt;/span&gt; &lt;span class="mf"&gt;-0.365032514259624&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;, &lt;span class="ss"&gt;:V*&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mf"&gt;0.4284123959267892&lt;/span&gt; &lt;span class="mf"&gt;0.4743725155726848&lt;/span&gt; &lt;span class="mf"&gt;0.5203326352185806&lt;/span&gt; &lt;span class="mf"&gt;0.5662927548644766&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0.7186534763126667&lt;/span&gt; &lt;span class="mf"&gt;0.27380780936493887&lt;/span&gt; &lt;span class="mf"&gt;-0.17103785758268963&lt;/span&gt; &lt;span class="mf"&gt;-0.6158835245304229&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;, &lt;span class="ss"&gt;:S&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mf"&gt;38.62265683187287&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt; &lt;span class="mf"&gt;2.0713230668787377&lt;/span&gt;&lt;span class="p"&gt;]]}&lt;/span&gt;
&lt;span class="nv"&gt;user&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;clojure.pprint/pprint&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;svd&lt;/span&gt; &lt;span class="nv"&gt;M&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:U&lt;/span&gt;
 &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mf"&gt;-0.13472212372225592&lt;/span&gt; &lt;span class="mf"&gt;-0.825742059834525&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;-0.34075769607996026&lt;/span&gt; &lt;span class="mf"&gt;-0.42881720180314464&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;-0.5467932684376648&lt;/span&gt; &lt;span class="mf"&gt;-0.03189234377175876&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;-0.7528288407953688&lt;/span&gt; &lt;span class="mf"&gt;0.3650325142596215&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;,
 &lt;span class="ss"&gt;:V*&lt;/span&gt;
 &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mf"&gt;-0.4284123959267895&lt;/span&gt;
   &lt;span class="mf"&gt;-0.4743725155726852&lt;/span&gt;
   &lt;span class="mf"&gt;-0.5203326352185804&lt;/span&gt;
   &lt;span class="mf"&gt;-0.5662927548644764&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;-0.7186534763126535&lt;/span&gt;
   &lt;span class="mf"&gt;-0.27380780936497917&lt;/span&gt;
   &lt;span class="mf"&gt;0.1710378575827312&lt;/span&gt;
   &lt;span class="mf"&gt;0.615883524530409&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;,
 &lt;span class="ss"&gt;:S&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mf"&gt;38.62265683187287&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt; &lt;span class="mf"&gt;2.0713230668787403&lt;/span&gt;&lt;span class="p"&gt;]]}&lt;/span&gt;
&lt;span class="nv"&gt;nil&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;h3 id="efficiency"&gt;Efficiency&lt;/h3&gt;

&lt;p&gt;In this example I shall demonstrate how valuable a truncated SVD is. Say we have a very large matrix and we only need 10 singular values/vectors. We will be using the &lt;code&gt;&lt;a href="https://github.com/mikera/vectorz-clj/"&gt;vectorz-clj&lt;/a&gt;&lt;/code&gt; implementation of &lt;code&gt;core.matrix&lt;/code&gt;.&lt;/p&gt;

&lt;div class="brush: clojure"&gt;
 &lt;table class="sourcetable"&gt;
  &lt;tbody&gt;
   &lt;tr&gt;
    &lt;td class="linenos"&gt;
     &lt;div class="linenodiv"&gt;
      &lt;pre&gt;1
2
3
4
5
6&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;
    &lt;td class="code"&gt;
     &lt;div class="source"&gt;
      &lt;pre&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;M1&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;reshape&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;matrix&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;range &lt;/span&gt;&lt;span class="mi"&gt;500000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="nv"&gt;M2&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;reshape&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;matrix&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;range &lt;/span&gt;&lt;span class="mi"&gt;5000000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="nv"&gt;M3&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;reshape&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;matrix&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;range &lt;/span&gt;&lt;span class="mi"&gt;5000000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;])]&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;time &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;kublai/svd&lt;/span&gt; &lt;span class="nv"&gt;M1&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;time &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;kublai/svd&lt;/span&gt; &lt;span class="nv"&gt;M2&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;time &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;kublai/svd&lt;/span&gt; &lt;span class="nv"&gt;M3&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;Here, &lt;code&gt;M1&lt;/code&gt; is a 10000 x 50 matrix, &lt;code&gt;M2&lt;/code&gt; is a 10000 x 500 matrix, and &lt;code&gt;M3&lt;/code&gt; is a 1000 x 5000 matrix.&lt;/p&gt;

&lt;p&gt;And the results are:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;"Elapsed time: 17372.943 msecs"
"Elapsed time: 78085.404 msecs"
"Elapsed time: 41511.266 msecs"&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now say we had to run a full decomposition on these matrices (using the standard stuff that ships with &lt;code&gt;core.matrix&lt;/code&gt;), the results look like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;"Elapsed time: 19617.777 msecs"
"Elapsed time: 157861.467 msecs"
"Elapsed time: 97627.002 msecs"&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For the larger matrices this is nearly twice as long as the truncated versions.&lt;/p&gt;

&lt;p&gt;(Experiments on a Macbook Air with 8 GB of memory and a 1.8 Ghz i5).&lt;/p&gt;

&lt;h3 id="links"&gt;Links:&lt;/h3&gt;

&lt;ul&gt;
 &lt;li&gt;&lt;a href="http://github.com/shriphani/kublai"&gt;Kublai&lt;/a&gt; - The decompositions  themselves&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://github.com/shriphani/kublai-timing"&gt;Kublai Timing Tests&lt;/a&gt; -  Tests to time these decompositions&lt;/li&gt;&lt;/ul&gt;&lt;/html&gt;</content></entry></feed>