Skip to main content

Optimal Transport Independent Component Analysis

Project description

ot-ica: Linear Independent Component Analysis via Optimal Transport

Python 3.8+ PyTorch License: GPL v3

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 logcosh Wasserstein 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 ot-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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

optimal_transport_ica-0.1.0.tar.gz (8.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

optimal_transport_ica-0.1.0-py3-none-any.whl (8.9 kB view details)

Uploaded Python 3

File details

Details for the file optimal_transport_ica-0.1.0.tar.gz.

File metadata

  • Download URL: optimal_transport_ica-0.1.0.tar.gz
  • Upload date:
  • Size: 8.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.4

File hashes

Hashes for optimal_transport_ica-0.1.0.tar.gz
Algorithm Hash digest
SHA256 25d9a292368e1b3435882b6391e0b7d1813f81a15304150eab20884b5c9f48ce
MD5 7aca5dc25331adb56fcee13817d22bb4
BLAKE2b-256 c1928935647956473d2d77e83b7947c4a596040b2235d9ebc74440740a28fac4

See more details on using hashes here.

File details

Details for the file optimal_transport_ica-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for optimal_transport_ica-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e4f04377be1e2baecdab599def678272a63a73d06fffb39fc0b3560b8f9f661d
MD5 e051a00822ff12973ddafba3c3e087f3
BLAKE2b-256 c0a6cccf1d16826b8f214aa14c584d08764579d8d89a7772bc557f767e3ac48c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page