pca-web 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +421 -0
  3. package/dist/base.d.ts +79 -0
  4. package/dist/base.d.ts.map +1 -0
  5. package/dist/base.js +358 -0
  6. package/dist/base.js.map +1 -0
  7. package/dist/incremental-pca.d.ts +86 -0
  8. package/dist/incremental-pca.d.ts.map +1 -0
  9. package/dist/incremental-pca.js +397 -0
  10. package/dist/incremental-pca.js.map +1 -0
  11. package/dist/index.d.ts +21 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +14 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/matrix.d.ts +44 -0
  16. package/dist/matrix.d.ts.map +1 -0
  17. package/dist/matrix.js +99 -0
  18. package/dist/matrix.js.map +1 -0
  19. package/dist/model.d.ts +86 -0
  20. package/dist/model.d.ts.map +1 -0
  21. package/dist/model.js +132 -0
  22. package/dist/model.js.map +1 -0
  23. package/dist/numeric/blas.d.ts +33 -0
  24. package/dist/numeric/blas.d.ts.map +1 -0
  25. package/dist/numeric/blas.js +130 -0
  26. package/dist/numeric/blas.js.map +1 -0
  27. package/dist/numeric/eigh.d.ts +21 -0
  28. package/dist/numeric/eigh.d.ts.map +1 -0
  29. package/dist/numeric/eigh.js +233 -0
  30. package/dist/numeric/eigh.js.map +1 -0
  31. package/dist/numeric/lanczos.d.ts +31 -0
  32. package/dist/numeric/lanczos.d.ts.map +1 -0
  33. package/dist/numeric/lanczos.js +287 -0
  34. package/dist/numeric/lanczos.js.map +1 -0
  35. package/dist/numeric/lu.d.ts +27 -0
  36. package/dist/numeric/lu.d.ts.map +1 -0
  37. package/dist/numeric/lu.js +149 -0
  38. package/dist/numeric/lu.js.map +1 -0
  39. package/dist/numeric/mle.d.ts +5 -0
  40. package/dist/numeric/mle.d.ts.map +1 -0
  41. package/dist/numeric/mle.js +67 -0
  42. package/dist/numeric/mle.js.map +1 -0
  43. package/dist/numeric/qr.d.ts +15 -0
  44. package/dist/numeric/qr.d.ts.map +1 -0
  45. package/dist/numeric/qr.js +88 -0
  46. package/dist/numeric/qr.js.map +1 -0
  47. package/dist/numeric/randomized.d.ts +54 -0
  48. package/dist/numeric/randomized.d.ts.map +1 -0
  49. package/dist/numeric/randomized.js +130 -0
  50. package/dist/numeric/randomized.js.map +1 -0
  51. package/dist/numeric/rng.d.ts +40 -0
  52. package/dist/numeric/rng.d.ts.map +1 -0
  53. package/dist/numeric/rng.js +127 -0
  54. package/dist/numeric/rng.js.map +1 -0
  55. package/dist/numeric/special.d.ts +2 -0
  56. package/dist/numeric/special.d.ts.map +1 -0
  57. package/dist/numeric/special.js +25 -0
  58. package/dist/numeric/special.js.map +1 -0
  59. package/dist/numeric/stats.d.ts +27 -0
  60. package/dist/numeric/stats.d.ts.map +1 -0
  61. package/dist/numeric/stats.js +110 -0
  62. package/dist/numeric/stats.js.map +1 -0
  63. package/dist/numeric/svd.d.ts +27 -0
  64. package/dist/numeric/svd.d.ts.map +1 -0
  65. package/dist/numeric/svd.js +374 -0
  66. package/dist/numeric/svd.js.map +1 -0
  67. package/dist/numeric/svdflip.d.ts +9 -0
  68. package/dist/numeric/svdflip.d.ts.map +1 -0
  69. package/dist/numeric/svdflip.js +32 -0
  70. package/dist/numeric/svdflip.js.map +1 -0
  71. package/dist/pca.d.ts +170 -0
  72. package/dist/pca.d.ts.map +1 -0
  73. package/dist/pca.js +649 -0
  74. package/dist/pca.js.map +1 -0
  75. package/dist/progress.d.ts +155 -0
  76. package/dist/progress.d.ts.map +1 -0
  77. package/dist/progress.js +173 -0
  78. package/dist/progress.js.map +1 -0
  79. package/dist/scheduling.d.ts +66 -0
  80. package/dist/scheduling.d.ts.map +1 -0
  81. package/dist/scheduling.js +160 -0
  82. package/dist/scheduling.js.map +1 -0
  83. package/dist/types.d.ts +10 -0
  84. package/dist/types.d.ts.map +1 -0
  85. package/dist/types.js +11 -0
  86. package/dist/types.js.map +1 -0
  87. package/dist/validation.d.ts +17 -0
  88. package/dist/validation.d.ts.map +1 -0
  89. package/dist/validation.js +36 -0
  90. package/dist/validation.js.map +1 -0
  91. package/dist/webgpu/df64.d.ts +18 -0
  92. package/dist/webgpu/df64.d.ts.map +1 -0
  93. package/dist/webgpu/df64.js +42 -0
  94. package/dist/webgpu/df64.js.map +1 -0
  95. package/dist/webgpu/engine.d.ts +74 -0
  96. package/dist/webgpu/engine.d.ts.map +1 -0
  97. package/dist/webgpu/engine.js +326 -0
  98. package/dist/webgpu/engine.js.map +1 -0
  99. package/dist/webgpu/gpu-pca.d.ts +90 -0
  100. package/dist/webgpu/gpu-pca.d.ts.map +1 -0
  101. package/dist/webgpu/gpu-pca.js +407 -0
  102. package/dist/webgpu/gpu-pca.js.map +1 -0
  103. package/dist/webgpu/index.d.ts +19 -0
  104. package/dist/webgpu/index.d.ts.map +1 -0
  105. package/dist/webgpu/index.js +16 -0
  106. package/dist/webgpu/index.js.map +1 -0
  107. package/dist/webgpu/kernels.d.ts +47 -0
  108. package/dist/webgpu/kernels.d.ts.map +1 -0
  109. package/dist/webgpu/kernels.js +147 -0
  110. package/dist/webgpu/kernels.js.map +1 -0
  111. package/dist/worker/client.d.ts +174 -0
  112. package/dist/worker/client.d.ts.map +1 -0
  113. package/dist/worker/client.js +482 -0
  114. package/dist/worker/client.js.map +1 -0
  115. package/dist/worker/handler.d.ts +17 -0
  116. package/dist/worker/handler.d.ts.map +1 -0
  117. package/dist/worker/handler.js +404 -0
  118. package/dist/worker/handler.js.map +1 -0
  119. package/dist/worker/protocol.d.ts +192 -0
  120. package/dist/worker/protocol.d.ts.map +1 -0
  121. package/dist/worker/protocol.js +70 -0
  122. package/dist/worker/protocol.js.map +1 -0
  123. package/dist/worker/worker.d.ts +14 -0
  124. package/dist/worker/worker.d.ts.map +1 -0
  125. package/dist/worker/worker.js +20 -0
  126. package/dist/worker/worker.js.map +1 -0
  127. package/package.json +94 -0
package/dist/pca.d.ts ADDED
@@ -0,0 +1,170 @@
1
+ /**
2
+ * Principal component analysis matching `sklearn.decomposition.PCA` (1.9).
3
+ *
4
+ * Naming is idiomatic TypeScript camelCase; every option and fitted attribute
5
+ * maps 1:1 to its sklearn counterpart (`nComponents` ↔ `n_components`,
6
+ * `explainedVarianceRatio` ↔ `explained_variance_ratio_`, …). Numerics follow
7
+ * sklearn's exact computation order, including its deterministic
8
+ * `svd_flip(u_based_decision=False)` sign convention.
9
+ */
10
+ import { BasePCA } from './base.js';
11
+ import { Matrix, type MatrixInput } from './matrix.js';
12
+ import { type PCAModel } from './model.js';
13
+ import { RandomState } from './numeric/rng.js';
14
+ import { type SvdResult } from './numeric/svd.js';
15
+ import { type FitAsyncOptions, type FitObserver, type ProgressReporter } from './progress.js';
16
+ import { type FloatArray } from './types.js';
17
+ export type SvdSolver = 'auto' | 'full' | 'covariance_eigh' | 'arpack' | 'randomized';
18
+ export type PowerIterationNormalizer = 'auto' | 'QR' | 'LU' | 'none';
19
+ export interface PCAOptions {
20
+ /**
21
+ * Number of components to keep. An integer ≥ 0, a fraction in (0, 1) to
22
+ * select by explained-variance ratio (full/covariance_eigh solvers),
23
+ * 'mle' for Minka's MLE (full/covariance_eigh), or null (default) to keep
24
+ * min(nSamples, nFeatures) components (min − 1 for arpack).
25
+ */
26
+ nComponents?: number | 'mle' | null;
27
+ /** When false, fit may overwrite the training Matrix's data (like sklearn's copy=False). */
28
+ copy?: boolean;
29
+ /** Scale transformed output to unit component-wise variance. */
30
+ whiten?: boolean;
31
+ svdSolver?: SvdSolver;
32
+ /**
33
+ * Accepted for API parity with sklearn's arpack tolerance. The built-in
34
+ * Lanczos solver always converges the requested triplets to machine
35
+ * precision (equivalent to sklearn's default tol=0.0).
36
+ */
37
+ tol?: number;
38
+ /** Power-iteration count for the randomized solver ('auto' → 7 or 4 like sklearn). */
39
+ iteratedPower?: number | 'auto';
40
+ /** Extra random test vectors for the randomized solver's range finder. */
41
+ nOversamples?: number;
42
+ powerIterationNormalizer?: PowerIterationNormalizer;
43
+ /** Integer seed (or RandomState) making arpack/randomized reproducible — sklearn-stream compatible. */
44
+ randomState?: number | RandomState | null;
45
+ }
46
+ interface ResolvedOptions {
47
+ nComponents: number | 'mle' | null;
48
+ copy: boolean;
49
+ whiten: boolean;
50
+ svdSolver: SvdSolver;
51
+ tol: number;
52
+ iteratedPower: number | 'auto';
53
+ nOversamples: number;
54
+ powerIterationNormalizer: PowerIterationNormalizer;
55
+ randomState: number | RandomState | null;
56
+ }
57
+ interface FitResult {
58
+ /** Left singular vectors from the fit, null for covariance_eigh. */
59
+ u: Float64Array | null;
60
+ uCols: number;
61
+ s: Float64Array;
62
+ x: Matrix;
63
+ }
64
+ /**
65
+ * sklearn 1.9's auto-solver heuristic (`PCA._fit`), as a pure function so the
66
+ * WebGPU frontend dispatches identically. `nComponents` is the raw option
67
+ * (null → min(shape) for the heuristic, like sklearn's unset default).
68
+ */
69
+ export declare function resolveSvdSolver(rows: number, cols: number, nComponents: number | 'mle' | null, requested: SvdSolver): Exclude<SvdSolver, 'auto'>;
70
+ /**
71
+ * Fit-time nComponents/solver compatibility checks, shared by the CPU and
72
+ * WebGPU frontends. Message text mirrors the sklearn errors it was ported
73
+ * from (camelCased).
74
+ */
75
+ export declare function validateNcForSolver(nc: number | 'mle', n: number, p: number, solver: Exclude<SvdSolver, 'auto'>): void;
76
+ export declare class PCA extends BasePCA {
77
+ private readonly opts;
78
+ private nSamples_;
79
+ private fitSvdSolver_;
80
+ constructor(options?: PCAOptions);
81
+ /** sklearn's `n_samples_`. */
82
+ get nSamples(): number;
83
+ /** The solver actually used by fit (sklearn's `_fit_svd_solver`). */
84
+ get resolvedSvdSolver(): Exclude<SvdSolver, 'auto'>;
85
+ /** Fit the model on X — sklearn's `fit`. X must have at least 2 samples. */
86
+ fit(X: MatrixInput, observer?: FitObserver): this;
87
+ /** Fit and return the embedding of X — sklearn's `fit_transform` fast path. */
88
+ fitTransform(X: MatrixInput, observer?: FitObserver): Matrix;
89
+ /**
90
+ * Non-blocking fit: runs the exact same steps as `fit`, time-sliced on
91
+ * the event loop (`budgetMs` of work per slice), so the UI stays
92
+ * responsive. Results are bit-identical to the synchronous fit.
93
+ */
94
+ fitAsync(X: MatrixInput, options?: FitAsyncOptions): Promise<this>;
95
+ /** Non-blocking fitTransform — the same U·S fast path as the sync version. */
96
+ fitTransformAsync(X: MatrixInput, options?: FitAsyncOptions): Promise<Matrix>;
97
+ /** The U·S fast path shared by fitTransform and fitTransformAsync. */
98
+ private fitTransformFromResult;
99
+ /**
100
+ * @internal The fit as a step generator — every `yield` is a suspension
101
+ * and abort checkpoint for the drivers (sync drain, time-sliced async,
102
+ * worker). Runs the exact statement sequence of the classic fit. Progress
103
+ * events (including the identical sequence for sync and async drives) are
104
+ * emitted synchronously between steps; on any exit before completion —
105
+ * abort, input error, callback throw — the estimator ends up unfitted.
106
+ */
107
+ _fitSteps(X: Matrix, observer?: FitObserver): Generator<void, FitResult, void>;
108
+ private fitFullSteps;
109
+ /**
110
+ * The XᵀX Gram product in row chunks, yielding between chunks. Chunked
111
+ * accumulation is strictly row-sequential, so the result is bitwise
112
+ * identical to one monolithic syrkT pass.
113
+ */
114
+ private gramSteps;
115
+ private fitTruncatedSteps;
116
+ /** Post-decomposition tail of the truncated solvers (flip, variances, store). */
117
+ private finishTruncated;
118
+ /**
119
+ * @internal Completes a covariance_eigh fit from an externally computed
120
+ * raw Gram matrix XᵀX (uncentered, float64, p×p). Used by the WebGPU
121
+ * frontend; all semantics downstream of the Gram product are shared with
122
+ * the CPU path. `rawGram` is consumed (mutated in place).
123
+ */
124
+ _fitGram(X: Matrix, rawGram: Float64Array): void;
125
+ /**
126
+ * @internal Completes a randomized fit from an externally computed
127
+ * decomposition of the centered data. `xc` must be the centered training
128
+ * buffer (X.data itself when copy=false, matching sklearn's destructive
129
+ * semantics) and `meanF64` the original column means.
130
+ */
131
+ _fitDecomposed(X: Matrix, xc: FloatArray, meanF64: Float64Array, dec: SvdResult): void;
132
+ /** @internal Option access for the WebGPU frontend (read-only). */
133
+ _resolvedOptions(): Readonly<ResolvedOptions>;
134
+ /** The fitCore preamble shared by the internal fit bridges. */
135
+ private prepareFit;
136
+ /**
137
+ * @internal Emits the finalize event (fraction 1, snapshot of the final
138
+ * model) after storeFitted — shared by _fitSteps and the WebGPU frontend.
139
+ * `u`/`s` are the fit's left vectors and singular values when the solver
140
+ * produced them (already sign-flipped), used for U·S snapshot scores.
141
+ */
142
+ _emitFinalize(reporter: ProgressReporter, x: Matrix, u: Float64Array | null, uCols: number, s: Float64Array | null): void;
143
+ /**
144
+ * The final model as a snapshot (fresh float64 copies of the stored
145
+ * attributes — float32 fits produce float32-rounded values, faithfully
146
+ * reflecting the model). Scores use U·S when the solver produced a U
147
+ * (`fitTransform`'s math) and one projection GEMM for covariance_eigh,
148
+ * whose fit never mutates X.
149
+ */
150
+ private finalizeSnapshot;
151
+ private storeFitted;
152
+ /**
153
+ * The fitted model as a plain structured-clone-friendly object (tight
154
+ * typed-array copies) — for `postMessage`, IndexedDB, or `modelToJSON`.
155
+ * A live `RandomState` in the options serializes as null.
156
+ */
157
+ toModel(): PCAModel;
158
+ /**
159
+ * Rehydrates a fitted PCA from `toModel()` output (validated first).
160
+ * The model's arrays are adopted without copying — pass a copy if the
161
+ * caller keeps mutating the model object.
162
+ */
163
+ static fromModel(model: PCAModel): PCA;
164
+ /** Per-sample log-likelihood under the Tipping–Bishop probabilistic PCA model. */
165
+ scoreSamples(X: MatrixInput): FloatArray;
166
+ /** Mean log-likelihood of all samples — sklearn's `score`. */
167
+ score(X: MatrixInput): number;
168
+ }
169
+ export { RandomState };
170
+ //# sourceMappingURL=pca.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pca.d.ts","sourceRoot":"","sources":["../src/pca.ts"],"names":[],"mappings":"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"}