rpca-kit
Separate shared structure from sparse disruptions in your matrix data.
rpca-kit is a lightweight Robust PCA toolkit for Python. Start with NumPy on CPU,
choose among five decomposition methods, and inspect the fitted components and
convergence diagnostics. Optional PyTorch support gives you the same solver API
on CPU or CUDA.
PyPI · Source · Algorithm guide · Issues
What you get
- A small starting point: Python 3.10+ and NumPy are enough for the core package.
- Separate outputs you can inspect: low-rank structure, sparse deviations, and the remaining residual, all with the same shape as your input.
- A method for your corruption pattern: isolated bad readings, whole unusual samples, or a model that allows dense noise.
- Visible numerical behavior: convergence status, iteration count, objective, and per-iteration history. No silent fallback when a requested GPU is unavailable.
observed = low_rank + sparse + residual
This is an alpha research package, not an automatic anomaly-labeling system. A useful decomposition depends on whether your data fit the selected model.
Where it can fit
These are application scenarios, not claims of deployed customer results:
| Scenario | Arrange the matrix | What to investigate |
|---|---|---|
| Sensor monitoring | Sensors × time samples | Shared operating patterns versus isolated faulty readings with pcp. |
| Batch or sample quality review | Measurements × samples | Whole unusual samples with outlier_pursuit; each candidate sample must be a column. |
| Fixed-camera video experiments | Flattened pixels × frames | A low-rank background and sparse moving regions, if the camera is stable and motion occupies a small portion of the scene. |
You supply the numeric matrix and domain interpretation. The package does not load videos, select alert thresholds, or decide whether a deviation is a fault.
Install
python -m pip install rpca-kit
For the optional PyTorch backend:
python -m pip install 'rpca-kit[torch]'
The gpu extra is an alias for the same PyTorch dependency. A CUDA-capable GPU,
compatible driver, and appropriate PyTorch build are still required; follow the
official PyTorch installation guide.
Installing an extra does not install a working CUDA driver.
Quickstart: recover sensor patterns beneath spikes
This fully reproducible synthetic example models 40 sensors sampled at 120 times. Their clean readings share three smooth patterns. We then inject 100 large, isolated reading errors and ask PCP to separate the two components.
import numpy as np
from rpca_kit import pcp
rng = np.random.default_rng(7)
time = np.linspace(0, 4 * np.pi, 120)
patterns = np.vstack([np.sin(time), np.cos(time), np.sin(0.5 * time)])
clean = rng.normal(size=(40, 3)) @ patterns
spikes = np.zeros_like(clean)
positions = rng.choice(clean.size, size=100, replace=False)
spikes.flat[positions] = rng.choice([-12.0, 12.0], size=100)
observed = clean + spikes
result = pcp(observed, tol=1e-7, max_iter=2000)
recovery_error = np.linalg.norm(result.low_rank - clean) / np.linalg.norm(clean)
print(f"converged: {result.converged}")
print(f"component shapes: {result.low_rank.shape}, {result.sparse.shape}")
print(f"relative recovery error: {recovery_error:.2e}")
assert result.converged
assert recovery_error < 1e-4
np.testing.assert_allclose(
observed, result.low_rank + result.sparse + result.residual
)
The input and each output are (40, 120) arrays. result.low_rank estimates the
shared patterns; result.sparse contains the estimated spikes. A NumPy CPU run
produces a relative recovery error of approximately 7.3e-08 for this seeded
example; the final digits can vary across numerical libraries.
We can measure recovery here because we created clean. For real measurements,
that ground truth is usually unknown. A small reconstruction residual alone does
not establish that the components have the interpretation you want.
Example: prioritize unusual samples for review
If an entire sample may be corrupted, use column-sparse decomposition instead of treating each bad entry independently. Here, each column contains 32 measurements for one of 70 synthetic samples. Three columns receive large perturbations.
import numpy as np
from rpca_kit import outlier_pursuit
rng = np.random.default_rng(57)
basis, _ = np.linalg.qr(rng.normal(size=(32, 2)))
normal_samples = basis @ rng.normal(size=(2, 70))
observed = normal_samples.copy()
observed[:, [2, 31, 59]] += rng.normal(scale=8.0, size=(32, 3))
result = outlier_pursuit(
observed, lambda_=0.5, tol=1e-7, max_iter=3000
)
scores = np.linalg.norm(result.sparse, axis=0)
review_first = np.sort(np.argsort(scores)[-3:])
print(f"converged: {result.converged}")
print(f"samples to inspect first: {review_first.tolist()}")
assert result.converged
np.testing.assert_array_equal(review_first, [2, 31, 59])
Expected review indices: [2, 31, 59]. The column norms are review scores, not
probabilities. We select three because this example contains three perturbed
samples; a real application needs its own threshold or review budget. Tune
lambda_ to your data and validate the results. Original clean values at
arbitrarily corrupted columns are not generally identifiable.
Both examples run independently with the basic NumPy installation. Their source files are also available as readme_quickstart.py and readme_sensors.py.
Choose a solver
| Function | Model | Choose it when |
|---|---|---|
pcp |
Principal Component Pursuit, solved by IALM | You expect low-rank structure plus sparse entrywise corruption. |
admm |
The same PCP objective, with fixed penalty | You want explicit control over the numerical penalty mu. |
stable_pcp |
Penalized stable PCP, solved by FISTA | You need a nonzero dense residual as well as low-rank and sparse terms. |
outlier_pursuit |
Low rank plus column-sparse corruption | Entire samples, arranged as columns, may be unusual. |
godec |
Deterministic rank/cardinality projections | You can specify the rank and maximum number of sparse entries. |
The function API returns an RPCAResult. For a stateful interface,
RPCA(method="ialm").fit(data) stores low_rank_, sparse_, residual_, and
result_. Each fit decomposes its input matrix; there is no learned
out-of-sample transform or forecasting step.
Parameters worth understanding
lambda_: controls the penalty on the sparse component. The default,1 / sqrt(max(data.shape)), is a starting point, not automatic tuning. A larger value penalizes sparse deviations more strongly.tauinstable_pcp: controls overall regularization. This is a penalized objective, not a user-specified hard bound on the noise norm.tolandmax_iter: control numerical stopping. Inspectconverged; exhausting the iteration budget returns the last result with a warning.rankandcardinalityingodec: are required bounds supplied by you.cardinalityis a count of entries, not a percentage.
result.error is the chosen solver's stopping criterion, not a universal
accuracy score. The algorithm guide
explains objectives, stopping rules, and assumptions.
CPU, PyTorch, and CUDA
NumPy input uses CPU by default. Select PyTorch CPU explicitly with
backend="torch", device="cpu", or CUDA with backend="torch", device="cuda"
when calling a solver. With backend="auto", a PyTorch tensor keeps its backend
and device. result.to_numpy() makes an explicit, independent CPU copy.
CI tests NumPy on Python 3.10–3.13 and PyTorch on CPU. CUDA execution is implemented but has not been validated on GPU hardware for this release. Skipped GPU tests are not GPU validation. Requesting unavailable CUDA raises an error rather than silently switching to CPU. GPU transfers and synchronization can outweigh any benefit for small matrices; no universal speedup is claimed.
Know the limits
- Input must be a dense, finite, real, nonempty 2D matrix. Missing values, sparse-matrix inputs, and streaming data are not supported.
- No automatic centering or scaling is applied. Decide how different units and measurement scales should be handled before fitting.
float32andfloat64are preserved; integers becomefloat64. Forfloat32, start withtol=1e-5rather than assuming the default1e-7is attainable.- The solvers use exact SVD. Large dense matrices can be expensive in time and memory. GoDec here does not include the original randomized acceleration.
- Low-rank and sparse components need identifiability assumptions. GoDec is nonconvex; convergence does not certify global optimality or correct recovery.
- PyTorch operations do not construct autograd graphs. This is a decomposition toolkit, not a differentiable training layer.
- Unrepresentable norms or objectives raise
FloatingPointError; rescale the data and regularization parameters before retrying.
Develop and reproduce
From a checkout of the repository:
python -m pip install -e '.[dev]'
python -m pytest
python -m ruff check src tests examples scripts
python scripts/release.py
The release script tests, builds, and checks the distributions without uploading unless explicitly requested. See the publishing guide and CI runs.
References and license
These are established algorithms, implemented here in a compact shared API:
- Candès, Li, Ma, and Wright. Robust Principal Component Analysis? JACM, 2011. Paper.
- Lin, Chen, and Ma. The Augmented Lagrange Multiplier Method for Exact Recovery of Corrupted Low-Rank Matrices, 2010. Paper.
- Zhou, Li, Wright, Candès, and Ma. Stable Principal Component Pursuit, 2010. Paper. This package uses the penalized formulation, not a directly constrained noise-ball formulation.
- Xu, Caramanis, and Sanghavi. Robust PCA via Outlier Pursuit, 2010. Paper.
- Zhou and Tao. GoDec: Randomized Low-rank & Sparse Matrix Decomposition in Noisy Case, ICML, 2011. This implementation uses deterministic alternating projections with exact SVD, not the randomized acceleration.
Created by Giovanny Torres. Released under the MIT license.
Metadata
Release files for rpca-kit 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| rpca_kit-0.1.2.tar.gz | 34.1 kB | With provenance | Details for rpca_kit-0.1.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| rpca_kit-0.1.2-py3-none-any.whl | Python 3 | none | any | Details for rpca_kit-0.1.2-py3-none-any.whl |
Total release size: 50.2 kB
Release files / rpca_kit-0.1.2.tar.gz
| Download URL | rpca_kit-0.1.2.tar.gz |
|---|---|
| Size | 34.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
dc63223ec0fd26e110b20d58964aff2013d1a6ff1aecff2f4aee0444351063e4
|
|
BLAKE2b-256 checksum How to use checksums |
14c4986865704e6f1aee663130eda7c80c5dd7e89a0555ac78835911a1e957d4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 31, 2026.
Transparency logRelease files / rpca_kit-0.1.2-py3-none-any.whl
| Download URL | rpca_kit-0.1.2-py3-none-any.whl |
|---|---|
| Size | 16.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dc2dcb48730a9527a9651185f14a75b515b574b3b94a6f9c25460cc375639f5b
|
|
BLAKE2b-256 checksum How to use checksums |
b78d7a00921b8183931302f455a147c202d3967bfa05119fbe57109f18893f29
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 31, 2026.
Transparency logSecurity for rpca-kit 0.1.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for rpca_kit-0.1.2.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 31, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.