Source code for CompSensePack.dictionaries.dictionary_utils

"""
dictionary_utils.py - Utility functions for matrix operations used in dictionary learning.

This module provides various utility functions for working with matrices, such as:
1. Computing the independent columns of a matrix.
2. Checking if the columns of a matrix are normalized.
3. Computing the coherence of a matrix.
4. Checking various properties of a matrix, such as full rank, normalization, and coherence.

These utilities are useful for tasks in dictionary learning, signal processing, and sparse coding.

Example usage:
--------------
>>> from dictionary_utils import compute_independent_columns, check_normalization, compute_coherence, check_matrix_properties

>>> A = np.random.randn(5, 5)
>>> independent_columns = compute_independent_columns(A)
>>> is_normalized = check_normalization(A)
>>> coherence = compute_coherence(A)
>>> check_matrix_properties(A)
"""

import numpy as np

[docs] def compute_independent_columns(A, tol=1e-10): """ Computes the independent columns of a matrix using the QR decomposition. This function identifies the independent columns of a given matrix `A` by performing a QR decomposition. It selects columns corresponding to non-zero diagonal elements of the `R` matrix, which are considered linearly independent. Parameters ---------- A : numpy.ndarray The matrix for which to compute the independent columns. tol : float, optional (default=1e-10) The tolerance value for considering diagonal elements of `R` as non-zero. Returns ------- ind_cols : numpy.ndarray A matrix containing the independent columns of `A`. Notes ----- - The QR decomposition is used to determine the rank of the matrix `A`. - Columns corresponding to non-zero diagonal elements of the `R` matrix are considered independent. Example ------- >>> A = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) >>> compute_independent_columns(A) array([[1, 2], [4, 5], [7, 8]]) """ # Perform the QR decomposition Q, R = np.linalg.qr(A) # Find the independent columns based on the rank of R rank = np.sum(np.abs(np.diagonal(R)) > tol) ind_cols = A[:, :rank] return ind_cols
[docs] def check_normalization(A): """ Checks if the columns of a matrix are normalized (i.e., each column has a unit norm). This function calculates the norm of each column in the matrix `A` and checks if all column norms are close to 1.0, which indicates normalization. Parameters ---------- A : numpy.ndarray The matrix to check for normalization. Returns ------- is_normalized : bool True if all columns of `A` are normalized, False otherwise. Example ------- >>> A = np.array([[1, 0], [0, 1]]) >>> check_normalization(A) True """ column_norms = np.linalg.norm(A, axis=0) is_normalized = np.allclose(column_norms, 1.0) return is_normalized
[docs] def compute_coherence(matrix): """ Computes the coherence of the given matrix. Coherence is a measure of the maximum correlation between any two columns of a matrix. It is useful in various applications, such as signal processing and compressed sensing, to assess the degree of similarity between different columns of the matrix. Parameters ---------- matrix : numpy.ndarray An (N x M) matrix where coherence is to be calculated. Returns ------- coherence : float The coherence of the matrix, defined as the maximum absolute value of the off-diagonal elements in the Gram matrix of the column-normalized input matrix. Example ------- >>> matrix = np.array([[1, 0], [0, 1]]) >>> compute_coherence(matrix) 0.0 """ # Normalize the columns of the matrix normalized_matrix = matrix / np.linalg.norm(matrix, axis=0, keepdims=True) # Compute the Gram matrix (inner products between all pairs of columns) gram_matrix = np.dot(normalized_matrix.T, normalized_matrix) # Remove the diagonal elements (which are all 1's) to only consider distinct columns np.fill_diagonal(gram_matrix, 0) # Compute the coherence as the maximum absolute value of the off-diagonal elements coherence = np.max(np.abs(gram_matrix)) return coherence
[docs] def check_matrix_properties(A): """ Checks various properties of a matrix. This function checks if the matrix `A` is full rank, if its columns and rows are normalized, and computes the coherence of the matrix. It also prints the results for each property. Parameters ---------- A : numpy.ndarray The matrix to check. Returns ------- None Example ------- >>> A = np.array([[1, 2], [3, 4]]) >>> check_matrix_properties(A) Is full rank: True Are columns normalized: False Are rows normalized: False Coherence: 0.9999999999999999 """ # Check if the matrix is full rank is_full_rank = np.linalg.matrix_rank(A) == min(A.shape) # Check if the columns are normalized is_columns_normalized = check_normalization(A) # Check if the rows are normalized is_rows_normalized = check_normalization(A.T) # Compute the coherence of the matrix coherence = compute_coherence(A) # Print the results print("Is full rank:", is_full_rank) print("Are columns normalized:", is_columns_normalized) print("Are rows normalized:", is_rows_normalized) print("Coherence:", coherence)