Decomposition truncatedsvd fit - CyrilB1531/lodestar GitHub Wiki

Development build. This page describes main, not a released package. The latest published Lodestar.Decomposition is 0.3.0 — read its documentation.

Home › Decomposition › Factorization

TruncatedSvd.Fit

Factorizes a sparse matrix at a given rank, by randomized SVD, without centring it.

public static TruncatedSvd Fit(CsrMatrix matrix, int componentCount, TruncatedSvdOptions options = null)

Parameters — matrix is the term-document matrix, rows as samples and columns as features; it is read, never modified. componentCount is the rank to ask for, at least 1 and no greater than the number of columns, which is scikit-learn's own bound; a matrix with fewer rows than that keeps one component per row, as the reference keeps them. options carries the randomized solver's settings, or is left out for scikit-learn's defaults: ten extra columns of oversampling, five power iterations, and the normalizer chosen automatically.

Returns — a TruncatedSvd holding the components, the singular values and the explained variance. Every property is populated; there is no second call to make.

Exceptions — ArgumentNullException when matrix is null. ArgumentOutOfRangeException when componentCount is below 1 or above the number of columns, or needs a range-finder block of the longer side by componentCount + Oversampling past the largest array (#1315), when an option is negative, or when Oversampling and componentCount do not add up within an int. ArgumentException when matrix has no row, holds a NaN or an infinity, as scikit-learn's input check refuses, or when RandomMatrix is given and is not min(rows, columns) × (componentCount + Oversampling) values long.

Example — four documents over three terms, kept at rank 2.

using Lodestar.Abstractions;
using Lodestar.Decomposition;

// Row-major CSR: values, the column each sits in, and where each row starts.
CsrMatrix matrix = new(
    4, 3,
    [3.0, 1.0, 2.0, 1.0, 1.0, 4.0, 2.0, 3.0],
    [0, 1, 0, 2, 1, 2, 0, 2],
    [0, 2, 4, 6, 8]);

TruncatedSvd fitted = TruncatedSvd.Fit(matrix, 2);

int kept = fitted.ComponentCount;                                 // => 2
double first = Math.Round(fitted.SingularValues[0], 3);           // => 5.614
double covered = Math.Round(fitted.ExplainedVarianceRatio.Sum(), 3);   // => 0.928

Remarks — the answer is randomized. Ω, the block that probes the matrix's range, is drawn from this package's own generator when only Seed is given, and the numbers below the fourth or fifth digit move with it. Hand it RandomMatrix instead and the run is reproducible across implementations rather than merely across runs.

Oversampling and power iterations both buy accuracy and both cost time. The defaults are scikit-learn's, and are the right starting point; raising PowerIterations is what helps when the singular values decay slowly, which is the case a randomized method finds hardest.

ExplainedVarianceRatio is not sorted. Its denominator is the input's total column variance, so the entries sum to less than one — but the first component of an uncentred factorization carries the mean direction, which is large in norm and small in variance, and it is routinely not the largest share. That is the arithmetic, not a bug: use the sum to judge the rank, not the order.

Applies to — net10.0, netstandard2.0.

See also — TruncatedSvd.Transform, TruncatedSvdOptions, PowerIterationNormalizer, the Python equivalence table.