From e4c903bd48e1724c19dd208375734da5bbd6026c Mon Sep 17 00:00:00 2001 From: Nathaniel pritchard Date: Mon, 6 Oct 2025 15:48:08 +0100 Subject: [PATCH 1/5] initialized low rank approximators --- docs/make.jl | 1 + docs/src/manual/low_rank_approximators.md | 26 +++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 docs/src/manual/low_rank_approximators.md diff --git a/docs/make.jl b/docs/make.jl index f2a212b9..502dd6bc 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -22,6 +22,7 @@ makedocs( "Manual" => [ "Introduction" => "manual/introduction.md", "Compression" => "manual/compression.md", + "Low-Rank Approximation" => "manual/low_rank_approximators.md", ], "API Reference" => [ "Compressors" => [ diff --git a/docs/src/manual/low_rank_approximators.md b/docs/src/manual/low_rank_approximators.md new file mode 100644 index 00000000..93d85605 --- /dev/null +++ b/docs/src/manual/low_rank_approximators.md @@ -0,0 +1,26 @@ +# Low-Rank Approximations of Matrices +Often large matrices contain a lot of redundant information. This means that it is often +possible to form representations of large matrices with far fewer vectors than what the +original matrix contains. Representing a matrix with far fewer vectors than what it +initially contains is known as low-rank approximation. Generally, low-rank approximations of +a matrix ``A \\in \\mathbb{R}^{m \\times n}``take two forms either a two matrix form where +`` + A \\approx MN, +`` +where ``M \\in \\mathbb{R}^{m \\times r}`` and ``N \\in \\mathbb{R}^{r \\times n}``, +or the three matrix representation where +`` +A \\approx MBN +`` +and ``M \\in \\mathbb{R}^{m \\times r}``, ``N \\in \\mathbb{R}^{t \\times n}``, and +``B \\in \\mathbb{R}^{r \\times s}``. + +Once one of the above representations has been obtained they can then be used to speed up: +matrix multiplication, clustering, or approximate eigenvalue decompositions [Add citations]. + +# A RangeFinder Example +Lets say that we wish to obtain a rank-5 RandomizedSVD to matrix with 1000 rows and columns. +In RLinearAlgebra.jl we can do this by first generating the `RandomizedSVD` `Approximator`. +This will require us to specify a `Compressor` with the desired rank of approximation as the +`compression_dim` and the `cardinality=Right()`, the number of power iterations we want +to be performed, and the type of power iterations we want to perform. From db1324153ca7d98f3bd0f50081d70df61e7b5bbf Mon Sep 17 00:00:00 2001 From: Nathaniel pritchard Date: Wed, 8 Oct 2025 11:10:40 +0100 Subject: [PATCH 2/5] added projection image --- docs/src/manual/images/projection.png | Bin 0 -> 48264 bytes docs/src/manual/low_rank_approximators.md | 23 +- docs/src/refs.bib | 271 +++++++++++----------- 3 files changed, 151 insertions(+), 143 deletions(-) create mode 100644 docs/src/manual/images/projection.png diff --git a/docs/src/manual/images/projection.png b/docs/src/manual/images/projection.png new file mode 100644 index 0000000000000000000000000000000000000000..d4fd8590a5406596504e1a3269e44380902b52f1 GIT binary patch literal 48264 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
34(JDTeqrAXq` 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 Z!>W#kgJUzVzC6HwR9|W;RVtW&`d{8)+DZTb literal 0 HcmV?d00001 diff --git a/docs/src/manual/low_rank_approximators.md b/docs/src/manual/low_rank_approximators.md index 93d85605..b608760d 100644 --- a/docs/src/manual/low_rank_approximators.md +++ b/docs/src/manual/low_rank_approximators.md @@ -3,21 +3,32 @@ Often large matrices contain a lot of redundant information. This means that it possible to form representations of large matrices with far fewer vectors than what the original matrix contains. Representing a matrix with far fewer vectors than what it initially contains is known as low-rank approximation. Generally, low-rank approximations of -a matrix ``A \\in \\mathbb{R}^{m \\times n}``take two forms either a two matrix form where +a matrix ``A \in \mathbb{R}^{m \times n}``take two forms either a two matrix form where `` - A \\approx MN, + A \approx MN, `` -where ``M \\in \\mathbb{R}^{m \\times r}`` and ``N \\in \\mathbb{R}^{r \\times n}``, +where ``M \in \mathbb{R}^{m \times r}`` and ``N \in \mathbb{R}^{r \times n}``, or the three matrix representation where `` -A \\approx MBN +A \approx MBN `` -and ``M \\in \\mathbb{R}^{m \\times r}``, ``N \\in \\mathbb{R}^{t \\times n}``, and -``B \\in \\mathbb{R}^{r \\times s}``. +and ``M \in \mathbb{R}^{m \times r}``, ``N \in \mathbb{R}^{t \times n}``, and +``B \in \mathbb{R}^{r \times s}``. Once one of the above representations has been obtained they can then be used to speed up: matrix multiplication, clustering, or approximate eigenvalue decompositions [Add citations]. +Low rank approximations can take two different forms one being the orthogonal projection +form where coordinates are projected perpendicularly to onto a plane and the second being +the oblique forms where points are projected along another plane (see the below figure +for a visualization). +```@raw html + +``` + +We also can consider low-rank approximations for symmetric matrices and general matrices. +For symmetric and general matrices, the RandomizedSVD can be used as the orthogonal +projection method [halko2011finding](@cite). # A RangeFinder Example Lets say that we wish to obtain a rank-5 RandomizedSVD to matrix with 1000 rows and columns. In RLinearAlgebra.jl we can do this by first generating the `RandomizedSVD` `Approximator`. diff --git a/docs/src/refs.bib b/docs/src/refs.bib index f504507c..ec775adf 100644 --- a/docs/src/refs.bib +++ b/docs/src/refs.bib @@ -1,160 +1,157 @@ +%% This BibTeX bibliography file was created using BibDesk. +%% https://bibdesk.sourceforge.io/ + +%% Created for Nathaniel pritchard at 2025-10-08 10:50:23 +0100 + + +%% Saved with string encoding Unicode (UTF-8) + + + @article{ailon2009fast, - title = {The {{Fast Johnson}}--{{Lindenstrauss Transform}} and {{Approximate Nearest Neighbors}}}, - author = {Ailon, Nir and Chazelle, Bernard}, - year = {2009}, - month = jan, - journal = {SIAM Journal on Computing}, - volume = {39}, - number = {1}, - pages = {302--322}, - issn = {0097-5397, 1095-7111}, - doi = {10.1137/060673096}, - langid = {english}, -} + author = {Ailon, Nir and Chazelle, Bernard}, + doi = {10.1137/060673096}, + issn = {0097-5397, 1095-7111}, + journal = {SIAM Journal on Computing}, + month = jan, + number = {1}, + pages = {302--322}, + title = {The {{Fast Johnson}}--{{Lindenstrauss Transform}} and {{Approximate Nearest Neighbors}}}, + volume = {39}, + year = {2009}, + bdsk-url-1 = {https://doi.org/10.1137/060673096}} @article{halko2011finding, - title = {Finding {{Structure}} with {{Randomness}}: {{Probabilistic Algorithms}} for {{Constructing Approximate Matrix Decompositions}}}, - shorttitle = {Finding {{Structure}} with {{Randomness}}}, - author = {Halko, N. and Martinsson, P. G. and Tropp, J. A.}, - year = {2011}, - month = jan, - journal = {SIAM Review}, - volume = {53}, - number = {2}, - pages = {217--288}, - issn = {0036-1445, 1095-7200}, - doi = {10.1137/090771806}, - langid = {english} -} + author = {Halko, N. and Martinsson, P. G. and Tropp, J. A.}, + doi = {10.1137/090771806}, + issn = {0036-1445, 1095-7200}, + journal = {SIAM Review}, + month = jan, + number = {2}, + pages = {217--288}, + shorttitle = {Finding {{Structure}} with {{Randomness}}}, + title = {Finding {{Structure}} with {{Randomness}}: {{Probabilistic Algorithms}} for {{Constructing Approximate Matrix Decompositions}}}, + volume = {53}, + year = {2011}, + bdsk-url-1 = {https://doi.org/10.1137/090771806}} @misc{martinsson2020randomized, - title = {Randomized {{Numerical Linear Algebra}}: {{Foundations}} \& {{Algorithms}}}, - shorttitle = {Randomized {{Numerical Linear Algebra}}}, - author = {Martinsson, Per-Gunnar and Tropp, Joel}, - year = {2020}, - publisher = {arXiv}, - doi = {10.48550/ARXIV.2002.01387}, - copyright = {arXiv.org perpetual, non-exclusive license}, - keywords = {FOS: Mathematics,Numerical Analysis (math.NA)} -} + author = {Martinsson, Per-Gunnar and Tropp, Joel}, + doi = {10.48550/ARXIV.2002.01387}, + publisher = {arXiv}, + shorttitle = {Randomized {{Numerical Linear Algebra}}}, + title = {Randomized {{Numerical Linear Algebra}}: {{Foundations}} \& {{Algorithms}}}, + year = {2020}, + bdsk-url-1 = {https://doi.org/10.48550/ARXIV.2002.01387}} @article{motzkin1954relaxation, - title = {The {{Relaxation Method}} for {{Linear Inequalities}}}, - author = {Motzkin, T. S. and Schoenberg, I. J.}, - year = {1954}, - journal = {Canadian Journal of Mathematics}, - volume = {6}, - pages = {393--404}, - issn = {0008-414X, 1496-4279}, - doi = {10.4153/CJM-1954-038-x}, - copyright = {https://www.cambridge.org/core/terms}, - langid = {english}, -} + author = {Motzkin, T. S. and Schoenberg, I. J.}, + doi = {10.4153/CJM-1954-038-x}, + issn = {0008-414X, 1496-4279}, + journal = {Canadian Journal of Mathematics}, + pages = {393--404}, + title = {The {{Relaxation Method}} for {{Linear Inequalities}}}, + volume = {6}, + year = {1954}, + bdsk-url-1 = {https://doi.org/10.4153/CJM-1954-038-x}} @article{needell2014paved, - title = {Paved with Good Intentions: {{Analysis}} of a Randomized Block {{Kaczmarz}} Method}, - shorttitle = {Paved with Good Intentions}, - author = {Needell, Deanna and Tropp, Joel A.}, - year = {2014}, - month = jan, - journal = {Linear Algebra and its Applications}, - volume = {441}, - pages = {199--221}, - issn = {00243795}, - doi = {10.1016/j.laa.2012.12.022}, - langid = {english}, -} + author = {Needell, Deanna and Tropp, Joel A.}, + doi = {10.1016/j.laa.2012.12.022}, + issn = {00243795}, + journal = {Linear Algebra and its Applications}, + month = jan, + pages = {199--221}, + shorttitle = {Paved with Good Intentions}, + title = {Paved with Good Intentions: {{Analysis}} of a Randomized Block {{Kaczmarz}} Method}, + volume = {441}, + year = {2014}, + bdsk-url-1 = {https://doi.org/10.1016/j.laa.2012.12.022}} @article{patel2023randomized, - title = {Randomized {{Block Adaptive Linear System Solvers}}}, - author = {Patel, Vivak and Jahangoshahi, Mohammad and Maldonado, D. Adrian}, - year = {2023}, - month = sep, - journal = {SIAM Journal on Matrix Analysis and Applications}, - volume = {44}, - number = {3}, - pages = {1349--1369}, - issn = {0895-4798, 1095-7162}, - doi = {10.1137/22M1488715}, - langid = {english}, -} + author = {Patel, Vivak and Jahangoshahi, Mohammad and Maldonado, D. Adrian}, + doi = {10.1137/22M1488715}, + issn = {0895-4798, 1095-7162}, + journal = {SIAM Journal on Matrix Analysis and Applications}, + month = sep, + number = {3}, + pages = {1349--1369}, + title = {Randomized {{Block Adaptive Linear System Solvers}}}, + volume = {44}, + year = {2023}, + bdsk-url-1 = {https://doi.org/10.1137/22M1488715}} @misc{pilanci2014iterative, - title = {Iterative {{Hessian}} Sketch: {{Fast}} and Accurate Solution Approximation for Constrained Least-Squares}, - shorttitle = {Iterative {{Hessian}} Sketch}, - author = {Pilanci, Mert and Wainwright, Martin J.}, - year = {2014}, - publisher = {arXiv}, - doi = {10.48550/ARXIV.1411.0347}, - copyright = {arXiv.org perpetual, non-exclusive license}, - keywords = {FOS: Computer and information sciences,FOS: Mathematics,Information Theory (cs.IT),Machine Learning (cs.LG),Machine Learning (stat.ML),Optimization and Control (math.OC)} -} + author = {Pilanci, Mert and Wainwright, Martin J.}, + doi = {10.48550/ARXIV.1411.0347}, + publisher = {arXiv}, + shorttitle = {Iterative {{Hessian}} Sketch}, + title = {Iterative {{Hessian}} Sketch: {{Fast}} and Accurate Solution Approximation for Constrained Least-Squares}, + year = {2014}, + bdsk-url-1 = {https://doi.org/10.48550/ARXIV.1411.0347}} @article{pritchard2023practical, - title = {Towards {{Practical Large-Scale Randomized Iterative Least Squares Solvers}} through {{Uncertainty Quantification}}}, - author = {Pritchard, Nathaniel and Patel, Vivak}, - year = {2023}, - month = sep, - journal = {SIAM/ASA Journal on Uncertainty Quantification}, - volume = {11}, - number = {3}, - pages = {996--1024}, - issn = {2166-2525}, - doi = {10.1137/22M1515057}, - langid = {english} -} + author = {Pritchard, Nathaniel and Patel, Vivak}, + doi = {10.1137/22M1515057}, + issn = {2166-2525}, + journal = {SIAM/ASA Journal on Uncertainty Quantification}, + month = sep, + number = {3}, + pages = {996--1024}, + title = {Towards {{Practical Large-Scale Randomized Iterative Least Squares Solvers}} through {{Uncertainty Quantification}}}, + volume = {11}, + year = {2023}, + bdsk-url-1 = {https://doi.org/10.1137/22M1515057}} @article{pritchard2024solving, - title = {Solving, Tracking and Stopping Streaming Linear Inverse Problems}, - author = {Pritchard, Nathaniel and Patel, Vivak}, - year = {2024}, - month = aug, - journal = {Inverse Problems}, - volume = {40}, - number = {8}, - pages = {085003}, - issn = {0266-5611, 1361-6420}, - doi = {10.1088/1361-6420/ad5583}, -} + author = {Pritchard, Nathaniel and Patel, Vivak}, + doi = {10.1088/1361-6420/ad5583}, + issn = {0266-5611, 1361-6420}, + journal = {Inverse Problems}, + month = aug, + number = {8}, + pages = {085003}, + title = {Solving, Tracking and Stopping Streaming Linear Inverse Problems}, + volume = {40}, + year = {2024}, + bdsk-url-1 = {https://doi.org/10.1088/1361-6420/ad5583}} @article{strohmer2009randomized, - title = {A {{Randomized Kaczmarz Algorithm}} with {{Exponential Convergence}}}, - author = {Strohmer, Thomas and Vershynin, Roman}, - year = {2009}, - month = apr, - journal = {Journal of Fourier Analysis and Applications}, - volume = {15}, - number = {2}, - pages = {262--278}, - issn = {1069-5869, 1531-5851}, - doi = {10.1007/s00041-008-9030-4}, - copyright = {http://www.springer.com/tdm}, - langid = {english} -} + author = {Strohmer, Thomas and Vershynin, Roman}, + doi = {10.1007/s00041-008-9030-4}, + issn = {1069-5869, 1531-5851}, + journal = {Journal of Fourier Analysis and Applications}, + month = apr, + number = {2}, + pages = {262--278}, + title = {A {{Randomized Kaczmarz Algorithm}} with {{Exponential Convergence}}}, + volume = {15}, + year = {2009}, + bdsk-url-1 = {https://doi.org/10.1007/s00041-008-9030-4}} @article{tropp2011improved, - title = {{{Improved Analysis of the Subsampled Randomized Hadamard Transform}}}, - author = {Tropp, Joel A.}, - year = {2011}, - month = apr, - journal = {Advances in Adaptive Data Analysis}, - volume = {03}, - number = {01n02}, - pages = {115--126}, - issn = {1793-5369, 1793-7175}, - doi = {10.1142/S1793536911000787}, - langid = {english}, -} + author = {Tropp, Joel A.}, + doi = {10.1142/S1793536911000787}, + issn = {1793-5369, 1793-7175}, + journal = {Advances in Adaptive Data Analysis}, + month = apr, + number = {01n02}, + pages = {115--126}, + title = {Improved {{Analysis}} of the {{Subsampled Randomized Hadamard Transform}}}, + volume = {03}, + year = {2011}, + bdsk-url-1 = {https://doi.org/10.1142/S1793536911000787}} @article{woodruff2014sketching, - title = {Sketching as a {{Tool}} for {{Numerical Linear Algebra}}}, - author = {Woodruff, David P.}, - year = {2014}, - journal = {Foundations and Trends in Theoretical Computer Science}, - volume = {10}, - number = {1-2}, - pages = {1--157}, - issn = {1551-305X, 1551-3068}, - doi = {10.1561/0400000060}, - langid = {english}, -} + author = {Woodruff, David P.}, + date-modified = {2025-10-08 10:50:19 +0100}, + doi = {10.1561/0400000060}, + issn = {1551-305X, 1551-3068}, + journal = {Foundations and Trends in Theoretical Computer Science}, + number = {1-2}, + pages = {1--157}, + shorttitle = {Computational {{Advertising}}}, + title = {Sketching as a {{Tool}} for {{Numerical Linear Algebra}}}, + volume = {10}, + year = {2014}, + bdsk-url-1 = {https://doi.org/10.1561/0400000060}} From 1fa5b2642d2771087ef2bbfc58f1fb9e2e867a60 Mon Sep 17 00:00:00 2001 From: Nathaniel pritchard Date: Mon, 13 Oct 2025 12:49:36 +0100 Subject: [PATCH 3/5] added summary tables for low rank approximations --- docs/src/manual/low_rank_approximators.md | 31 ++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/docs/src/manual/low_rank_approximators.md b/docs/src/manual/low_rank_approximators.md index b608760d..93711060 100644 --- a/docs/src/manual/low_rank_approximators.md +++ b/docs/src/manual/low_rank_approximators.md @@ -28,7 +28,36 @@ for a visualization). We also can consider low-rank approximations for symmetric matrices and general matrices. For symmetric and general matrices, the RandomizedSVD can be used as the orthogonal -projection method [halko2011finding](@cite). +projection method [halko2011finding](@cite). + +As far as oblique methods go, the difference between symmetric and asymmetric decompositions +becomes more complicated. For symmetric matrices, the go to approximation is the Nystr\"om +approximation. For the non-symmetric matrices, we can have a generalization of Nystr\"om +known as Generalized Nystr\"om or we can interpolative approaches, which select subsets of +the rows and/or columns to a matrix. If it these interpolative decompositions are performed +to select only columns or only rows then they are known as one sided IDs, if they are used +to select both columns and rows then they are known as a CUR decomposition. Below, we +present a summary of the decompositions in a table. +|Approximation Name| General Matrices| Interpolative| Type| Form of Approximation| +|:-----------------|:----------------|:-------------|:----|:---------------------| +|RandRangeFinder| Yes| No| Orthogonal| ``A \\approx QQ^\top A``| +|RandSVD|Yes|No|Orthogonal|``A \\approx U\\SigmaV^\\top``| +|Nystr\"om| Symmetric| Can be| Oblique| ``(AS)((SA)^\\top AS)^\\dagger(AS)^\\top``| +|Generalizedd Nystr\"om| Yes| Can be| Oblique| ``(AS_1)(S_2A AS_1)^\\dagger S_2 A``| +|CUR| Yes| Yes| Oblique| ``(A[:,J])U(A[I,:])``| +|One-Sided-ID| Yes| Yes| Oblique| ``A[:,J]U_c`` or ``U_r A[I,:]``| + +Once you have obtained a low-rank approximation you can then use it to perform +multiplications in all cases or in some specific areas use it to precondition a linear +system through the ldiv! function. Below we have the table of decompositions and indicate +how they can be used. +|Approximation Name| `mul!`| `ldiv!`| +|:-----------------|:------|:-------| +|RandRangeFinder| Yes| No| +|RandSVD|Yes| No| +|Nystr\"om|Yes| No| +|CUR|Yes| No| +|One-Sided-ID|Yes|No| # A RangeFinder Example Lets say that we wish to obtain a rank-5 RandomizedSVD to matrix with 1000 rows and columns. In RLinearAlgebra.jl we can do this by first generating the `RandomizedSVD` `Approximator`. From 1167070ccff21ec383ba8f8ccd0c5efb4e0de5f3 Mon Sep 17 00:00:00 2001 From: Nathaniel pritchard Date: Mon, 10 Nov 2025 16:54:06 +0000 Subject: [PATCH 4/5] addded rangefinder desc to man --- docs/src/manual/low_rank_approximators.md | 61 ++++++++++++++++--- .../RangeApproximators/rangefinder.jl | 2 +- 2 files changed, 53 insertions(+), 10 deletions(-) diff --git a/docs/src/manual/low_rank_approximators.md b/docs/src/manual/low_rank_approximators.md index 93711060..6e0bbdc1 100644 --- a/docs/src/manual/low_rank_approximators.md +++ b/docs/src/manual/low_rank_approximators.md @@ -31,19 +31,20 @@ For symmetric and general matrices, the RandomizedSVD can be used as the orthogo projection method [halko2011finding](@cite). As far as oblique methods go, the difference between symmetric and asymmetric decompositions -becomes more complicated. For symmetric matrices, the go to approximation is the Nystr\"om -approximation. For the non-symmetric matrices, we can have a generalization of Nystr\"om -known as Generalized Nystr\"om or we can interpolative approaches, which select subsets of +becomes more complicated. For symmetric matrices, the go to approximation is the Nystrom +approximation. For the non-symmetric matrices, we can have a generalization of Nystrom +known as Generalized Nystrom or we can interpolative approaches, which select subsets of the rows and/or columns to a matrix. If it these interpolative decompositions are performed to select only columns or only rows then they are known as one sided IDs, if they are used to select both columns and rows then they are known as a CUR decomposition. Below, we present a summary of the decompositions in a table. + |Approximation Name| General Matrices| Interpolative| Type| Form of Approximation| |:-----------------|:----------------|:-------------|:----|:---------------------| -|RandRangeFinder| Yes| No| Orthogonal| ``A \\approx QQ^\top A``| -|RandSVD|Yes|No|Orthogonal|``A \\approx U\\SigmaV^\\top``| -|Nystr\"om| Symmetric| Can be| Oblique| ``(AS)((SA)^\\top AS)^\\dagger(AS)^\\top``| -|Generalizedd Nystr\"om| Yes| Can be| Oblique| ``(AS_1)(S_2A AS_1)^\\dagger S_2 A``| +|RandRangeFinder| Yes| No| Orthogonal| ``A \approx QQ^\top A``| +|RandSVD|Yes|No|Orthogonal|``A \approx U \Sigma V^\top``| +|Nystrom| Symmetric| Can be| Oblique| ``(AS)((SA)^\top AS)^\dagger(AS)^\top``| +|Generalizedd Nystrom| Yes| Can be| Oblique| ``(AS_1)(S_2A AS_1)^\dagger S_2 A``| |CUR| Yes| Yes| Oblique| ``(A[:,J])U(A[I,:])``| |One-Sided-ID| Yes| Yes| Oblique| ``A[:,J]U_c`` or ``U_r A[I,:]``| @@ -51,16 +52,58 @@ Once you have obtained a low-rank approximation you can then use it to perform multiplications in all cases or in some specific areas use it to precondition a linear system through the ldiv! function. Below we have the table of decompositions and indicate how they can be used. + |Approximation Name| `mul!`| `ldiv!`| |:-----------------|:------|:-------| |RandRangeFinder| Yes| No| |RandSVD|Yes| No| -|Nystr\"om|Yes| No| +|Nystrom|Yes| No| |CUR|Yes| No| |One-Sided-ID|Yes|No| -# A RangeFinder Example +# The Randomized Rangefinder +The idea behind the randomized range finder is to find an orthogonal matrix ``Q`` such that +``A \approx QQ^\top A``. In their seminal work, [halko2011finding](@cite) showed that +forming ``Q`` was as simple as compressing ``A`` from the right and storing the Q from the +resulting QR factorization. Despite the simplicity of this procedure they were able to show + if the compression dimension, ``k>2``, then +``\|A - QQ^\top A\|_F \leq \sqrt{k+1} (\sum_{i=k+1}^{\min{(m,n)}}\sigma_{i})^{1/2}``, + where ``\sigma_{k+1}`` is the ``k+1^\text{th}`` singular value of A (see Theorem 10.5 +of [halko2011finding](@cite)). This is very close to the error from the truncated SVD, which +is known to be the lowest achievable error. + + +For many matrices that singular values that decay quickly, this bound can be far more +conservative than the observed performance. However, for some matrices whose singular values +decay slowly this bound is fairly tight. Luckily, using power iterations we can +still improve the quality of the approximation. Power Iterations basically involve +multiplying the matrix with itself, which results in raising each singular value to a +higher power. This powering of the singular values increases the gap between the singular +values large making them easier to differentiate between each other and therefore capture. +In `RLinearAlgebra`, you can control the number of power iterations using the `power_its` +keyword in the constructor. + +One issue with power iterations is that they can sometimes be +unstable. We can also improve the stability of these iterations by orthogonalizing between +power iterations. Meaning that instead of computing ``A A^\top A`` as is done in the power +iterations we compute ``A^\top A`` and take a QR factorization of this matrix to obtain a +``Q`` then compute ``A Q``. In RLinearAlgebra you can control whether or not the +orthogonalization is performed using the `orthogonalize` keyword argument in the +constructor. + +## A RangeFinder Example Lets say that we wish to obtain a rank-5 RandomizedSVD to matrix with 1000 rows and columns. In RLinearAlgebra.jl we can do this by first generating the `RandomizedSVD` `Approximator`. This will require us to specify a `Compressor` with the desired rank of approximation as the `compression_dim` and the `cardinality=Right()`, the number of power iterations we want to be performed, and the type of power iterations we want to perform. + +```julia +# Generate the matrix we wish to approximate +A = randn(1000, 5) * randn(5, 1000); + + +``` + +# The RandSVD + +## A RandSVD example diff --git a/src/Approximators/RangeApproximators/rangefinder.jl b/src/Approximators/RangeApproximators/rangefinder.jl index 5426dcea..00afa4d7 100644 --- a/src/Approximators/RangeApproximators/rangefinder.jl +++ b/src/Approximators/RangeApproximators/rangefinder.jl @@ -13,7 +13,7 @@ Suppose we have a matrix ``A \\in \\mathbb{R}^{m \\times n}`` of which we wish t A simple way to find such a matrix is to choose a ``k`` representing the number of vectors we wish to have in the subspace. Then we can generate a compression matrix ``S\\in\\mathbb{R}^{n \\times k}`` and compute ``Q = \\text{qr}(AS)``. - With high probability we will have ``\\|A - QQ^\\top A\\|_2 \\leq + With high probability we will have ``\\|A - QQ^\\top A\\|_F \\leq \\sqrt{k+1} (\\sum_{i=k+1}^{\\min{(m,n)}}\\sigma_{i})^{1/2}``, where ``\\sigma_{k+1}`` is the ``k+1^\\text{th}`` singular value of A (see Theorem 10.5 of [halko2011finding](@cite)). This bound is often conservative From 93f74c3ac9009b5e9423c072e0a2f13a2ff3402a Mon Sep 17 00:00:00 2001 From: Nathaniel pritchard Date: Wed, 12 Nov 2025 16:32:51 +0000 Subject: [PATCH 5/5] finished low-rank approximation manual for orthogonal approximations --- docs/src/manual/low_rank_approximators.md | 165 ++++++++++++++++-- docs/src/refs.bib | 38 ++++ .../RangeApproximators/rangefinder.jl | 2 +- 3 files changed, 187 insertions(+), 18 deletions(-) diff --git a/docs/src/manual/low_rank_approximators.md b/docs/src/manual/low_rank_approximators.md index 6e0bbdc1..bac2ac07 100644 --- a/docs/src/manual/low_rank_approximators.md +++ b/docs/src/manual/low_rank_approximators.md @@ -1,22 +1,23 @@ # Low-Rank Approximations of Matrices Often large matrices contain a lot of redundant information. This means that it is often possible to form representations of large matrices with far fewer vectors than what the -original matrix contains. Representing a matrix with far fewer vectors than what it -initially contains is known as low-rank approximation. Generally, low-rank approximations of -a matrix ``A \in \mathbb{R}^{m \times n}``take two forms either a two matrix form where +original matrix contains. Representing a matrix with a small number of vectors +is known as low-rank approximation. Generally, low-rank approximations of +a matrix ``A \in \mathbb{R}^{m \times n}`` take two forms either a two matrix form where `` A \approx MN, `` where ``M \in \mathbb{R}^{m \times r}`` and ``N \in \mathbb{R}^{r \times n}``, -or the three matrix representation where +or the three matrix form where `` A \approx MBN `` -and ``M \in \mathbb{R}^{m \times r}``, ``N \in \mathbb{R}^{t \times n}``, and +and ``M \in \mathbb{R}^{m \times r}``, ``N \in \mathbb{R}^{s \times n}``, and ``B \in \mathbb{R}^{r \times s}``. Once one of the above representations has been obtained they can then be used to speed up: -matrix multiplication, clustering, or approximate eigenvalue decompositions [Add citations]. +matrix multiplication, clustering, or approximate eigenvalue decompositions +[halko2011finding, eckart1936approximation, udell2019why, park2025curing](@cite). Low rank approximations can take two different forms one being the orthogonal projection form where coordinates are projected perpendicularly to onto a plane and the second being @@ -48,21 +49,22 @@ present a summary of the decompositions in a table. |CUR| Yes| Yes| Oblique| ``(A[:,J])U(A[I,:])``| |One-Sided-ID| Yes| Yes| Oblique| ``A[:,J]U_c`` or ``U_r A[I,:]``| -Once you have obtained a low-rank approximation you can then use it to perform +In RLinearAlgebra, +once you have obtained a low-rank approximation `Recipe` you can then use it to perform multiplications in all cases or in some specific areas use it to precondition a linear -system through the ldiv! function. Below we have the table of decompositions and indicate -how they can be used. +system through the `ldiv!` function. Below we have the table of approximation recipes +and indicate how they can be used. |Approximation Name| `mul!`| `ldiv!`| |:-----------------|:------|:-------| -|RandRangeFinder| Yes| No| -|RandSVD|Yes| No| -|Nystrom|Yes| No| -|CUR|Yes| No| -|One-Sided-ID|Yes|No| +|RandRangeFinderRecipe| Yes| No| +|RandSVDRecipe|Yes| No| +|NystromRecipe|Yes| No| +|CURRecipe|Yes| No| +|IDRecipe(One-Sided-ID)|Yes|No| # The Randomized Rangefinder The idea behind the randomized range finder is to find an orthogonal matrix ``Q`` such that -``A \approx QQ^\top A``. In their seminal work, [halko2011finding](@cite) showed that +``A \approx QQ^\top A``. In their seminal work [halko2011finding](@cite) showed that forming ``Q`` was as simple as compressing ``A`` from the right and storing the Q from the resulting QR factorization. Despite the simplicity of this procedure they were able to show if the compression dimension, ``k>2``, then @@ -78,7 +80,7 @@ decay slowly this bound is fairly tight. Luckily, using power iterations we can still improve the quality of the approximation. Power Iterations basically involve multiplying the matrix with itself, which results in raising each singular value to a higher power. This powering of the singular values increases the gap between the singular -values large making them easier to differentiate between each other and therefore capture. +values making them easier to accurately capture. In `RLinearAlgebra`, you can control the number of power iterations using the `power_its` keyword in the constructor. @@ -90,20 +92,149 @@ iterations we compute ``A^\top A`` and take a QR factorization of this matrix to orthogonalization is performed using the `orthogonalize` keyword argument in the constructor. +!!! info + If the cardinality of the compressor in the `RangeFinder` is not `Right()` a warning + will be returned and the approximation may be incorrect. + ## A RangeFinder Example Lets say that we wish to obtain a rank-5 RandomizedSVD to matrix with 1000 rows and columns. In RLinearAlgebra.jl we can do this by first generating the `RandomizedSVD` `Approximator`. This will require us to specify a `Compressor` with the desired rank of approximation as the `compression_dim` and the `cardinality=Right()`, the number of power iterations we want -to be performed, and the type of power iterations we want to perform. +to be performed, and whether we want to orthogonalize the power iterations. + +To begin, we consider forming an approximation to a rank 5 matrix with 1000 rows and +columns. Then will define a `RangeFinder` structure with a `FJLT` compressor with a +`compression_dim = 5` and a +`cardinality = Right()`. After defining this structure we will then use `rapproximate` to +generate a `RangeFinderRecipe`, which we will then compute the error relying on the ability +to multiply `RangeFinderRecipe`s. ```julia +using RLinearAlgebra, LinearAlgebra + # Generate the matrix we wish to approximate A = randn(1000, 5) * randn(5, 1000); +# Form the RangeFinder Structure +approx = RangeFinder( + compressor = FJLT(compression_dim = 5, cardinality = Right()) +) + +# Approximate A +range_A = rapproximate(approx, A) +# Check the error of the approximation +norm(A - range_A * (range_A' * A)) ``` +To see the benefits of power iterations we consider the same example but now with +`compression_dim = 3`, then we consider the truncated SVD error, +the error of an approximation with no power iterations, +the error of an approximation with 10 power iterations but no +orthogonalization, and the error of an approximation with 10 power iterations and +orthogonalization. + +```julia +# Get error of truncated svd by computing the sqrt of the sum^2 of singular values 4:1000 +printstyled("Error of rank 3 truncated SVD:", + sqrt(sum(svd(A).S[4:end].^2)), + "\n" +) + +# Try approximating with a compression dimension of 3 and no power its/orthogonalization +# Form the RangeFinder Structure +approx = RangeFinder( + compressor = FJLT(compression_dim = 3, cardinality = Right()) +); + +range_A = rapproximate(approx, A); + +printstyled("Error of rank 3 approximation:", + norm(A - range_A * (range_A' * A)), + "\n" +) + +# Now consider adding power iterations +approx_pi = RangeFinder( + compressor = FJLT(compression_dim = 3, cardinality = Right()), + power_its = 10 +); + +range_A_pi = rapproximate(approx_pi, A); + + +printstyled("Error with 10 Power its and Orthogonalization:", + norm(A - range_A_pi * (range_A_pi' * A)), + "\n" +) + +# Now consider power its with orthogonalization +approx_pi_o = RangeFinder( + compressor = FJLT(compression_dim = 3, cardinality = Right()), + power_its = 10, + orthogonalize = true +); + +range_A_pi_o = rapproximate(approx_pi_o, A); +printstyled("Error with 10 Power its and Orthogonalization:", + norm(A - range_A_pi_o * (range_A_pi_o' * A)), + "\n" +) +``` # The RandSVD +The RandomizedSVD is a form of low-rank approximation that returns the approximate +singular values and vectors to the truncated SVD. Algorithmically, it is implemented as +three additional steps to the Randomized Rangefinder in [halko2011finding](@cite). +Specifically these steps are: +1. Take the ``Q`` matrix from the Randomized Rangefinder and compute ``Q^\top A``. +2. Compute the ``W,S,V = \text{svd}(Q^\top A)``. +3. Obtain the left singular vectors from ``U = Q^\top W``. + +Since, the RandomizedSVD is simply an extension of the Randomized RangeFinder, the effects +of all modifications, such as power iterations and orthogonalization still apply. The +difference between the two procedures is found in the Recipes. Where for the `RandSVDRecipe` +you find a approximate truncated SVD where the singular values can be accessed by +calling `recipe.S`, the left singular vectors can be accessed by calling `recipe.U`, +and the right singular vectors can be accessed by calling `recipe.V`. Additionally, +when you multiply with the RandomizedSVD it is as if you are multiplying with the +truncated SVD, meaning for a vector ``x`` the operation ``USV^\top x`` is performed. This +type of multiplication can be substantially faster than multiplications with the original +matrix. + +!!! info + As for the RandomizedSVD if the cardinality of the compressor is not `Right()` a warning + will be returned and the approximation may be incorrect. ## A RandSVD example +We now demonstrate how to use the RandSVD, by first generating the technique structure +with a `FJLT` compressor with `compression_dim = 5` and `cardinality = Right()`. Then we +will run `rapproximate` and compare the singular values of the returned recipe to the +5 singular values of the truncated SVD. We will then end the experiment by comparing +the difference between multiplying a our `RandSVDRecipe` to vector and multiplying the +original matrix. + +```julia +using RLinearAlgebra, LinearAlgebra + +# Generate the matrix we wish to approximate +A = randn(1000, 5) * randn(5, 1000); + +# Form the RangeFinder Structure +approx = RandSVD( + compressor = FJLT(compression_dim = 5, cardinality = Right()) +) + +# Approximate A +randsvd_A = rapproximate(approx, A) + +# Compare singular vectors +svd(A).S[1:5] + +randsvd_A.S + +# Compare multiplications +x = rand(1000); + +norm(A * x - randsvd_A * x) +``` diff --git a/docs/src/refs.bib b/docs/src/refs.bib index ec775adf..59a17002 100644 --- a/docs/src/refs.bib +++ b/docs/src/refs.bib @@ -155,3 +155,41 @@ @article{woodruff2014sketching volume = {10}, year = {2014}, bdsk-url-1 = {https://doi.org/10.1561/0400000060}} +@misc{park2025curing, + title = {{{CURing Large Models}}: {{Compression}} via {{CUR Decomposition}}}, + shorttitle = {{{CURing Large Models}}}, + author = {Park, Sanghyeon and Moon, Soo-Mook}, + year = 2025, + month = jan, + number = {arXiv:2501.04211}, + eprint = {2501.04211}, + primaryclass = {cs}, + publisher = {arXiv}, + doi = {10.48550/arXiv.2501.04211}, +} +@article{udell2019why, + title = {Why {{Are Big Data Matrices Approximately Low Rank}}?}, + author = {Udell, Madeleine and Townsend, Alex}, + year = 2019, + month = jan, + journal = {SIAM Journal on Mathematics of Data Science}, + volume = {1}, + number = {1}, + pages = {144--160}, + issn = {2577-0187}, + doi = {10.1137/18M1183480} +} +@article{eckart1936approximation, + title = {The {{Approximation}} of {{One Matrix}} by {{Another}} of {{Lower Rank}}}, + author = {Eckart, Carl and Young, Gale}, + year = 1936, + month = sep, + journal = {Psychometrika}, + volume = {1}, + number = {3}, + pages = {211--218}, + issn = {0033-3123, 1860-0980}, + doi = {10.1007/BF02288367}, +} + + diff --git a/src/Approximators/RangeApproximators/rangefinder.jl b/src/Approximators/RangeApproximators/rangefinder.jl index 00afa4d7..5e225c91 100644 --- a/src/Approximators/RangeApproximators/rangefinder.jl +++ b/src/Approximators/RangeApproximators/rangefinder.jl @@ -86,7 +86,7 @@ RangeFinder(; compressor = SparseSign(cardinality = Right()), orthogonalize = false, power_its = 0 -) = RangeFinder(compressor, orthogonalize, power_its) +) = RangeFinder(compressor, power_its, orthogonalize) """ RangeFinderRecipe