Skip to main content

GMM-based estimator for linear inverse problems with complex-valued priors.

Project description

gmm-estimator

Python License: BSD-3-Clause Package

GMM-based estimator for complex-valued linear inverse problems.

gmm-estimator provides an estimator for noisy linear observation models using a complex-valued Gaussian mixture model (GMM) prior. The package builds on cplx-gmm for fitting the complex-valued GMM prior and adds an estimation layer for problems of the form y = A h + n.

The estimator is domain-independent and can be used for linear inverse problems in signal processing, communications, and related applications. Channel estimation is one motivating application and is discussed in the research background section.

✨ Highlights

  • GMM-based estimator for complex-valued linear inverse problems
  • Supports general linear observation models of the form y = A h + n
  • Uses complex-valued GMM priors fitted with cplx-gmm
  • Component-wise LMMSE estimation under the fitted mixture prior
  • Posterior component weighting in the observation domain
  • Supports identity and rectangular observation matrices
  • Supports full posterior mixture estimates or truncated component sums
  • Supports full, diagonal, spherical, circulant, block-circulant, Toeplitz, and block-Toeplitz GMM covariance types
  • FFT fast paths for circulant and block-circulant priors under scalar identity observation and noise models
  • scikit-learn-like workflow via inherited fit(...) and added estimate(...)
  • Modern Python packaging with pyproject.toml, uv, pytest, and ruff

📌 Citation

If you use gmm-estimator in academic work, please cite the package directly:

@software{koller_fesl_gmm_estimator,
  author = {Koller, Michael and Fesl, Benedikt},
  title = {{gmm-estimator}: GMM-based estimator for complex-valued linear inverse problems},
  year = {2026},
  url = {https://github.com/michael-koller-91/gmm-estimator},
  version = {0.1.0}
}

Plain-text citation:

M. Koller and B. Fesl, gmm-estimator: GMM-based estimator for complex-valued linear inverse problems, version 0.1.0. Available: https://github.com/michael-koller-91/gmm-estimator

If you use the estimator in the context of channel estimation, please also consider citing the related works listed in the research background section.

📦 Installation

Install from PyPI:

pip install gmm-estimator

or with uv:

uv add gmm-estimator

gmm-estimator depends on cplx-gmm for fitting complex-valued GMM priors. The dependency is installed automatically when installing gmm-estimator.

For development, clone the repository and install the development environment:

git clone https://github.com/michael-koller-91/gmm-estimator.git
cd gmm-estimator
uv sync --group dev

🚀 Quick Start

import numpy as np

from gmm_estimator import GmmEstimator

rng = np.random.default_rng(0)

h_train = (
    rng.normal(size=(1_000, 8))
    + 1j * rng.normal(size=(1_000, 8))
) / np.sqrt(2.0)

h_val = (
    rng.normal(size=(100, 8))
    + 1j * rng.normal(size=(100, 8))
) / np.sqrt(2.0)

noise = (
    rng.normal(size=(100, 8))
    + 1j * rng.normal(size=(100, 8))
) / np.sqrt(2.0)

# Identity observation model: y = h + n
noise_covariance = np.eye(8, dtype=complex)
y = h_val + noise

estimator = GmmEstimator(
    n_components=4,
    covariance_type="full",
    random_state=0,
    max_iter=100,
    n_init=1,
)

# Fit the complex-valued GMM prior p(h).
estimator.fit(h_train)

# Estimate h from noisy observations y.
h_est = estimator.estimate(
    y=y,
    noise_covariance=noise_covariance,
    observation_matrix=None,
    n_components_or_probability=1.0,
)

The estimator follows a two-step pattern:

  1. fit(h_train) fits the complex-valued GMM prior using the inherited cplx-gmm implementation.
  2. estimate(y, noise_covariance, observation_matrix) estimates the unknown vector from noisy linear observations.

🧩 Estimation Model

The package assumes a noisy linear observation model:

y = A h + n

where h is the unknown complex-valued vector, A is the known observation matrix, and n is zero-mean complex Gaussian observation noise with known covariance matrix Cn.

Using the estimator is a two-step process.

Step 1: Fit the GMM prior

Training samples of the unknown vector are used to fit a complex-valued GMM prior:

p(h) = sum_k pi_k CN(h; mu_k, C_k)

Here, K is the number of GMM components, pi_k is the mixture weight, mu_k is the component mean vector, and C_k is the component covariance matrix. After fitting, the GMM approximates the unknown prior distribution of h.

This step only needs to be done once and can be performed in an offline training phase.

Step 2: Estimate from noisy observations

Given the fitted GMM prior, the estimator approximates the MMSE estimate of h from y. For each mixture component, the observation-domain model is:

y | k ~ CN(A mu_k, A C_k A^H + Cn)

The estimator computes posterior component probabilities in the observation domain and combines component-wise LMMSE estimates. Equivalently, it implements the closed-form GMM-based MMSE estimator under the fitted prior.

🧠 Estimator API

The main class is:

from gmm_estimator import GmmEstimator

GmmEstimator inherits from cplx_gmm.GaussianMixtureCplx and therefore supports the same prior-fitting API.

Core methods:

Method Description
fit(X, y=None) Fit the complex-valued GMM prior. Inherited from cplx-gmm.
fit_predict(X, y=None) Fit the GMM prior and return component labels. Inherited from cplx-gmm.
predict(X) Predict the most likely GMM prior component. Inherited from cplx-gmm.
predict_proba(X) Return prior-domain component probabilities. Inherited from cplx-gmm.
score_samples(X) Return per-sample log-likelihoods. Inherited from cplx-gmm.
score(X, y=None) Return the mean log-likelihood. Inherited from cplx-gmm.
sample(n_samples=1) Draw samples from the fitted GMM prior. Inherited from cplx-gmm.
estimate(y, noise_covariance, observation_matrix=None, n_components_or_probability=1.0) Estimate unknown vectors from noisy linear observations.

Constructor parameters are inherited from GaussianMixtureCplx:

Parameter Description
n_components Number of mixture components.
covariance_type Covariance type of the complex-valued GMM prior.
tol EM convergence tolerance.
reg_covar Non-negative regularization added to covariance estimates.
max_iter Maximum number of EM iterations.
n_init Number of initializations.
init_params Initialization method, either "kmeans" or "random".
random_state Random seed or random state.
warm_start Reuse previous solution for supported covariance types.
zero_mean If True, fit zero-mean mixture components.
blocks Block dimensions for block-structured covariance types.

The fitted prior parameters are exposed using trailing-underscore attributes from cplx-gmm:

Attribute Description
weights_ Mixture weights of shape (n_components,).
means_ Component means of shape (n_components, n_features).
covariances_ Component covariance parameters. Shape depends on the covariance type.
precisions_ Component precision parameters.
precisions_cholesky_ Cholesky factors of component precision parameters.
converged_ Whether EM converged.
n_iter_ Number of EM iterations used by the best initialization.
lower_bound_ Final EM lower bound.
means_fft_ FFT-domain component means for covariance_type="circulant".
covariances_fft_ FFT-domain diagonal covariance entries for covariance_type="circulant".
means_fft2_ Two-dimensional FFT-domain component means for covariance_type="block-circulant".
covariances_fft2_ Two-dimensional FFT-domain diagonal covariance entries for covariance_type="block-circulant".

🔎 Estimation

The main method added by this package is estimate(...):

h_est = estimator.estimate(
    y=y,
    noise_covariance=noise_covariance,
    observation_matrix=observation_matrix,
    n_components_or_probability=1.0,
)

Arguments:

Argument Description
y Observations of shape (n_samples, n_observations).
noise_covariance Observation noise covariance of shape (n_observations, n_observations).
observation_matrix Observation matrix of shape (n_observations, n_features). If None, the identity matrix is used.
n_components_or_probability Component-selection rule for the posterior mixture estimate.

The component-selection parameter can be used in two ways:

Value Behavior
Integer, e.g. 1 or 5 Use the corresponding number of most likely posterior components.
Float in (0, 1], e.g. 0.9 Use the fewest most likely components whose cumulative posterior probability reaches the threshold.
1.0 Use all components.

Note that 1 and 1.0 intentionally have different meanings: 1 selects one component, while 1.0 selects all components.

🧩 Covariance Types

The estimator supports all covariance types provided by cplx-gmm:

covariance_type Description
"full" Full covariance matrix for each GMM component.
"diag" Diagonal covariance for each GMM component.
"spherical" One scalar variance per GMM component.
"circulant" Circulant covariance matrix for each component.
"block-circulant" Block-circulant covariance matrix. Requires blocks=(n_1, n_2).
"toeplitz" Toeplitz covariance matrix for each component.
"block-toeplitz" Block-Toeplitz covariance matrix. Requires blocks=(n_1, n_2).

For block-structured covariance types, pass blocks to the constructor:

estimator = GmmEstimator(
    n_components=4,
    covariance_type="block-circulant",
    blocks=(4, 8),
    random_state=0,
)

estimator.fit(h_train)

⚡ FFT Acceleration

For covariance_type="circulant" and covariance_type="block-circulant", cplx-gmm fits the prior in a Fourier-domain representation and stores the corresponding fitted FFT-domain parameters.

gmm-estimator uses these attributes for fast estimation when the observation model satisfies the required structure:

A = α I
Cn = σ² I

where α and σ² are scalar values. In this case, the posterior component probabilities and component-wise LMMSE estimates can be computed in the Fourier domain using diagonal covariance entries.

If the fast-path assumptions are not satisfied, the estimator automatically falls back to the generic full-covariance implementation.

🧪 Examples

Run the example script:

uv run python examples/gmm_estimator_examples.py --nr 1

Available examples:

Number Description
1 Full covariance matrices with identity observation matrix.
2 Full covariance matrices with selection observation matrix.
3 Circulant covariance matrices with identity observation matrix.
4 Circulant covariance matrices with selection observation matrix.
5 Block-circulant covariance matrices with identity observation matrix.
6 Toeplitz covariance matrices with identity observation matrix.
7 Block-Toeplitz covariance matrices with identity observation matrix.

Run all examples:

uv run python examples/gmm_estimator_examples.py

Use --help to inspect the script interface:

uv run python examples/gmm_estimator_examples.py --help

📚 Research Background

This repository is joint work of Michael Koller and Benedikt Fesl.

Papers

The following reference provides more details and properties of the GMM estimator.

  • Koller, Fesl, Turan, Utschick, "An Asymptotically MSE-Optimal Estimator Based on Gaussian Mixture Models," IEEE Trans. Signal. Process., 2022. [IEEEXplore] [arXiv]

The estimator implementation has been used in the following references.

  • N. Turan, B. Fesl, M. Grundei, M. Koller, and W. Utschick, “Evaluation of a Gaussian Mixture Model-based Channel Estimator using Measurement Data,” in Int. Symp. Wireless Commun. Syst. (ISWCS), 2022. [IEEEXplore] [arXiv]

  • B. Fesl, M. Joham, S. Hu, M. Koller, N. Turan, and W. Utschick, “Channel Estimation based on Gaussian Mixture Models with Structured Covariances,” in 56th Asilomar Conf. Signals, Syst., Comput., 2022, pp. 533–537. [IEEEXplore] [arXiv]

  • B. Fesl, N. Turan, M. Joham, and W. Utschick, “Learning a Gaussian Mixture Model from Imperfect Training Data for Robust Channel Estimation,” IEEE Wireless Commun. Lett., 2023. [IEEEXplore] [arXiv]

  • M. Koller, B. Fesl, N. Turan and W. Utschick, "An Asymptotically Optimal Approximation of the Conditional Mean Channel Estimator Based on Gaussian Mixture Models," IEEE Int. Conf. Acoust., Speech, Signal Process. (ICASSP), 2022, pp. 5268-5272. [IEEEXplore] [arXiv]

  • B. Fesl, A. Faika, N. Turan, M. Joham, and W. Utschick, “Channel Estimation with Reduced Phase Allocations in RIS-Aided Systems,” in IEEE 24th Int. Workshop Signal Process. Adv. Wireless Commun. (SPAWC), 2023, pp. 161-165. [IEEEXplore] [arXiv]

  • N. Turan, B. Fesl, M. Koller, M. Joham and W. Utschick, "A Versatile Low-Complexity Feedback Scheme for FDD Systems via Generative Modeling," in IEEE Trans. Wireless Commun., vol. 23, no. 6, pp. 6251-6265, 2024. [IEEEXplore] [arXiv]

  • N. Turan, B. Fesl, and W. Utschick, "Enhanced Low-Complexity FDD System Feedback with Variable Bit Lengths via Generative Modeling," in 57th Asilomar Conf. Signals, Syst., Comput., 2023. [IEEEXplore] [arXiv]

  • N. Turan, M. Koller, B. Fesl, S. Bazzi, W. Xu and W. Utschick, "GMM-based Codebook Construction and Feedback Encoding in FDD Systems," in 56th Asilomar Conf. Signals, Syst., Comput., 2022, pp. 37-42. [IEEEXplore] [arXiv]

  • M. Koller, “Asymptotically Optimal Channel Estimation and Learning Suitable Compressive Sensing Matrices,” Ph.D. dissertation, Technical University of Munich, 2022. [TUM]

  • B. Fesl, “Generative Model-Aided Channel Estimation Design and Optimality Analysis,” Ph.D. dissertation, Technical University of Munich, 2025. [TUM]

🧪 Development

Install the development environment with uv:

uv sync --group dev

Run tests:

uv run pytest

Run linting:

uv run ruff check .

Format code:

uv run ruff format .

Run the examples:

uv run python examples/gmm_estimator_examples.py

Build the package:

uv run python -m build

Check the package distribution:

uv run twine check dist/*

✅ Test Coverage

The test suite covers:

  • package imports
  • integration with the cplx-gmm package
  • estimation with identity observation matrices
  • estimation with rectangular observation matrices
  • estimation with complex-valued observation matrices
  • real-valued input handling
  • posterior probability normalization
  • component-count selection
  • cumulative-probability selection
  • compact covariance representations
  • full estimator output against manual reference implementations
  • FFT fast-path equivalence for circulant covariance matrices
  • FFT fast-path equivalence for block-circulant covariance matrices
  • unfitted-estimator behavior
  • invalid input validation
  • example script execution

📄 License

This project is licensed under the BSD 3-Clause License.

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

gmm_estimator-0.1.0.tar.gz (21.7 kB view details)

Uploaded Source

Built Distribution

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

gmm_estimator-0.1.0-py3-none-any.whl (12.2 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for gmm_estimator-0.1.0.tar.gz
Algorithm Hash digest
SHA256 a7eebf3da6c4ab35a24b0865c698f18c193188f6fcc00df72fd52facbb91dd22
MD5 9ebcda4f429490babe55941690da3112
BLAKE2b-256 45e7bec0337f3cfe5aa8fa6b799dbab674718ad52770b6c820710b2a67e9bf87

See more details on using hashes here.

File details

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

File metadata

  • Download URL: gmm_estimator-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 12.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for gmm_estimator-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d7d74685857791382febc36ccd06ee74edff91056a522b970d0bdcfda59de889
MD5 ed62ba344f3afb918f036af2836c75e3
BLAKE2b-256 a2488d743cc8b8c3ee49fbb67531fd5f1d76e729e90ec605548d4df87bc86a08

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