Optimal Transport Independent Component Analysis
Project description
ot-ica: Linear Independent Component Analysis via Optimal Transport
ot-ica is a Python library that recovers independent source signals from linear mixtures by maximizing the 1D squared Wasserstein distance ($W_2^2$) between each projected component and a standard Gaussian.
Unlike classical ICA algorithms (FastICA, JADE, InfoMax) that use proxies (such as kurtosis or parametric approximations) that can fail on heterogeneous source distributions, ot-ica computes the exact 1D Wasserstein distance via quantile sorting. This provides an assumption-free, exact non-Gaussianity contrast function that is computed efficiently without density estimation or binning.
Key Features
- Exact Contrast Evaluation: Bypasses heuristic approximations by utilizing the exact 1D squared Wasserstein distance ($W_2^2$) computed analytically via sorted quantiles.
- Flexible Optimization Modes:
- Deflationary: Extract independent components one by one.
- Symmetric: Solve for all components simultaneously under orthogonal constraints.
- Diverse Optimizers:
- Riemannian gradient ascent on the Stiefel manifold.
- Standard Stochastic Gradient Descent (SGD) and L-BFGS.
- A fast Fixed-Point update rule (OT-Mapping) for extremely quick convergence.
- Robust Costs: Supports standard L2 Wasserstein distance and a robust Huber-like
logcoshWasserstein cost to handle extreme outliers. - Continuous Smoothing (Dithering): Inject continuous noise to smooth discrete CDF steps and avoid flat gradients.
- Fully Vectorized: Written in PyTorch, supporting GPU acceleration out of the box.
Installation
Install from PyPI:
pip install optimal-transport-ica
Or install from source:
git clone https://github.com/ashutoshjha3103/ot_ica.git
cd ot_ica
pip install .
Verify your installation:
python -c 'from ot_ica import WassersteinICA; print("OK")'
Quick Start
Here are three ways to use the ot_ica package for source separation:
1. Deflationary Optimization (Extracting One Component)
import numpy as np
import torch
from ot_ica import WassersteinICA
# Generate synthetic mixed data
rng = np.random.default_rng(0)
S = rng.laplace(0, 1, size=(3, 2000)) # 3 Laplace sources
A = rng.standard_normal((3, 3)) # Mixing matrix
X = torch.tensor(A @ S, dtype=torch.float32) # Mixed signals
# Initialize and Whiten
ica = WassersteinICA(X)
ica.whiten()
# Optimize one component using deflationary gradient ascent
w_est, w2_score = ica.optimize_wasserstein2(continuous=True)
print("Estimated unmixing row:", w_est)
print("Wasserstein distance score:", float(w2_score))
2. Symmetric Optimization (Riemannian SGD on the Stiefel Manifold)
# Solves for all components simultaneously using Stiefel manifold SGD
W_est = ica.optimize_symmetric(n_components=3, optimizer='stiefel', lr=0.5)
# Reconstruct independent sources
S_est = torch.matmul(W_est, ica.X_white)
print("Estimated unmixing matrix W:\n", W_est)
3. Fast Fixed-Point Optimization (OT-Mapping)
# Runs a fast fixed-point rule by stepping away from the ideal Gaussian target
W_est_fp = ica.optimize_fixed_point(n_components=3, step_size=0.5)
# Reconstruct independent sources
S_est_fp = torch.matmul(W_est_fp, ica.X_white)
print("Fixed-Point unmixing matrix W:\n", W_est_fp)
Visualizing the Contrast
1. Mixing Two Sources (Central Limit Theorem)
Mixing two independent sources (e.g., Laplace and Uniform) results in a more Gaussian distribution due to the Central Limit Theorem. The 1D squared Wasserstein distance ($W_2^2$) provides the contrast by dipping toward the Gaussian mixture and peaking at the pure, non-Gaussian sources.
2. Contrast Function Race
Comparing how FastICA (logcosh), JADE, InfoMax, and OT-ICA ($W_2^2$) scan a 2D mixture. All four rotate the projection and scan for a non-Gaussianity peak, landing on the independent components with varying sharpness.
Citation
If you use this package or method in your research, please cite our paper:
@misc{jha2026linearindependentcomponentanalysis,
title={Linear Independent Component Analysis via Optimal Transport},
author={Ashutosh Jha and Michel Besserve and Simon Buchholz},
year={2026},
eprint={2607.14081},
archivePrefix={arXiv},
primaryClass={cs.LG},
url={https://arxiv.org/abs/2607.14081},
}
License
This project is licensed under the GNU General Public License v3 (GPLv3) - see the LICENSE file for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file optimal_transport_ica-0.1.1.tar.gz.
File metadata
- Download URL: optimal_transport_ica-0.1.1.tar.gz
- Upload date:
- Size: 8.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
07286f8f05b9563b65868b4a93b16503cba329e64e135caf7e08ed363f8fd4c1
|
|
| MD5 |
7a8d35fd24fc42166031ac6e2fe42630
|
|
| BLAKE2b-256 |
f167775375d4cdb5d805e92c875b633ce69500a870964b824de1a1f2c85b8f01
|
File details
Details for the file optimal_transport_ica-0.1.1-py3-none-any.whl.
File metadata
- Download URL: optimal_transport_ica-0.1.1-py3-none-any.whl
- Upload date:
- Size: 8.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7d268baf82273b0ff2442d8c9926181ac9c01822cfaacaa4586bd1a4b746da46
|
|
| MD5 |
6d1fe0b3ab67b4ef6c85cd029ccb461e
|
|
| BLAKE2b-256 |
84295ee636b596a9093d1bf8a9fda7739983fd15d8121d14fa58b86b0d6dc7bb
|