Skip to main content

Regularized coupled matrix factorisation with AO-ADMM

Project description

Learning coupled matrix factorizations with Python

Tests Coverage Documentation Status https://img.shields.io/badge/code%20style-black-000000.svg

MatCoupLy is a Python library for learning coupled matrix factorizations with flexible constraints and regularization. For a quick introduction to coupled matrix factorization and PARAFAC2 see the online documentation.

Installation

To install MatCoupLy and all MIT-compatible dependencies from PyPI, you can run

pip install matcouply

If you also want to enable total variation regularization, you need to install all components, which comes with a GPL-v3 lisence

pip install matcouply[gpl]

About

Illustration of a coupled matrix factorization

MatCoupLy is a Python library that adds support for coupled matrix factorization in TensorLy. For optimization, MatCoupLy uses alternating updates with the alternating direction method of multipliers (AO-ADMM), which allows you to fit coupled matrix factorization (and PARAFAC2) models with flexible constraints in any mode of your data [1, 2]. Currently, MatCoupLy supports the NumPy and PyTorch backends of TensorLy.

Example

Below is a simulated example, where a set of 15 non-negative coupled matrices are generated and decomposed using a non-negative PARAFAC2 factorization with an L1 penalty on C, constraining the maximum norm of the A and Bᵢ matrices and unimodality constraints on the component vectors in the Bᵢ matrices. For more examples, see the Gallery of examples in the online documentation.

import matplotlib.pyplot as plt
import numpy as np

from matcouply.data import get_simple_simulated_data
from matcouply.decomposition import cmf_aoadmm

noisy_matrices, cmf = get_simple_simulated_data(noise_level=0.2, random_state=1)
rank = cmf.rank
weights, (A, B_is, C) = cmf

# Decompose the dataset
estimated_cmf = cmf_aoadmm(
    noisy_matrices,
    rank=rank,
    non_negative=True,  # Constrain all components to be non-negative
    l1_penalty={2: 0.1},  # Sparsity on C
    l2_norm_bound=[1, 1, 0],  # Norm of A and B_i-component vectors less than 1
    parafac2=True,  # Enforce PARAFAC2 constraint
    unimodal={1: True},  # Unimodality (one peak) on the B_i component vectors
    constant_feasibility_penalty=True,  # Must be set to apply l2_norm_penalty (row-penalty) on A. See documentation for more details
    verbose=-1,  # Negative verbosity level for minimal (nonzero) printouts
    random_state=0,  # A seed can be given similar to how it's done in TensorLy
)

est_weights, (est_A, est_B_is, est_C) = estimated_cmf

# Code to display the results
def normalize(M):
    return M / np.linalg.norm(M, axis=0)

fig, axes = plt.subplots(2, 3, figsize=(5, 2))
axes[0, 0].plot(normalize(A))
axes[0, 1].plot(normalize(B_is[0]))
axes[0, 2].plot(normalize(C))

axes[1, 0].plot(normalize(est_A))
axes[1, 1].plot(normalize(est_B_is[0]))
axes[1, 2].plot(normalize(est_C))

axes[0, 0].set_title(r"$\mathbf{A}$")
axes[0, 1].set_title(r"$\mathbf{B}_0$")
axes[0, 2].set_title(r"$\mathbf{C}$")

axes[0, 0].set_ylabel("True")
axes[1, 0].set_ylabel("Estimated")

for ax in axes.ravel():
    ax.set_yticks([])  # Components can be aribtrarily scaled
for ax in axes[0]:
    ax.set_xticks([])  # Remove xticks from upper row

plt.savefig("figures/readme_components.png", dpi=300)
All regularization penalties (including regs list):
* Mode 0:
   - <'matcouply.penalties.L2Ball' with aux_init='random_uniform', dual_init='random_uniform', norm_bound=1, non_negativity=True)>
* Mode 1:
   - <'matcouply.penalties.Parafac2' with svd='truncated_svd', aux_init='random_uniform', dual_init='random_uniform', update_basis_matrices=True, update_coordinate_matrix=True, n_iter=1)>
   - <'matcouply.penalties.Unimodality' with aux_init='random_uniform', dual_init='random_uniform', non_negativity=True)>
   - <'matcouply.penalties.L2Ball' with aux_init='random_uniform', dual_init='random_uniform', norm_bound=1, non_negativity=True)>
* Mode 2:
   - <'matcouply.penalties.L1Penalty' with aux_init='random_uniform', dual_init='random_uniform', reg_strength=0.1, non_negativity=True)>
converged in 218 iterations: FEASIBILITY GAP CRITERION AND RELATIVE LOSS CRITERION SATISFIED
Plot of simulated and estimated components

References

  • [1]: Roald M, Schenker C, Cohen JE, Acar E PARAFAC2 AO-ADMM: Constraints in all modes. EUSIPCO (2021).

  • [2]: Roald M, Schenker C, Calhoun VD, Adali T, Bro R, Cohen JE, Acar E An AO-ADMM approach to constraining PARAFAC2 on all modes (2022). Accepted for publication in SIAM Journal on Mathematics of Data Science, arXiv preprint arXiv:2110.01278.

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

matcouply-0.1.2.tar.gz (1.6 MB view details)

Uploaded Source

Built Distribution

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

matcouply-0.1.2-py3-none-any.whl (2.3 MB view details)

Uploaded Python 3

File details

Details for the file matcouply-0.1.2.tar.gz.

File metadata

  • Download URL: matcouply-0.1.2.tar.gz
  • Upload date:
  • Size: 1.6 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.9.13

File hashes

Hashes for matcouply-0.1.2.tar.gz
Algorithm Hash digest
SHA256 76ad80ea4e167d34ae88294202386743450ebaacc5849367aebf070528ce0e9b
MD5 9aab3da38e96ab1d226137ddce27b0c0
BLAKE2b-256 c064f8742733ee1511ee91e96205b0823bfaa5b77434cdf33d306eb4809db674

See more details on using hashes here.

File details

Details for the file matcouply-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: matcouply-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 2.3 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.9.13

File hashes

Hashes for matcouply-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 6f2069ee7f8dd962e95c87cd71be41710ef8c0ff9d0e3b129c4e106a03c42717
MD5 fc6b47d727857bde8d00bf82261dc80f
BLAKE2b-256 c9634f7a486604d48db40bbe1321ce1cea39f253bdbc31e4f3bfba72637b8a00

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