Source code for Basic.Matrix_Computation

# Yuncong Ma, 2/2/2024
# basic matrix computation functions

#########################################
# Packages
import torch
import numpy as np
# disable grad computation on 08/03/2024
torch.set_grad_enabled(False)
# other functions of pNet
from Module.Data_Input import set_data_precision, set_data_precision_torch


[docs]def mat_corr_(X, Y=None, dataPrecision='double'): """ mat_corr(X, Y=None, dataPrecision='double') Perform corr as in MATLAB, pair-wise Pearson correlation between columns in X and Y :param X: 1D or 2D matrix :param Y: 1D or 2D matrix, or None :param dataPrecision: 'double' or 'single' X and Y have the same number of rows :return: Corr Note: this method will use memory as it concatenates X and Y along column direction. By Yuncong Ma, 9/5/2023 """ np_float, np_eps = set_data_precision(dataPrecision) if not isinstance(X, np.ndarray): X = np.array(X, dtype=np_float) else: X = X.astype(np_float) if Y is not None: if not isinstance(Y, np.ndarray): Y = np.array(Y, dtype=np_float) else: Y = Y.astype(np_float) # Check size of X and Y if len(X.shape) > 2 or (Y is not None and len(Y.shape) > 2): raise ValueError("X and Y must be 1D or 2D matrices") if Y is not None and X.shape[0] != Y.shape[0]: raise ValueError("X and Y must have the same number of columns") dim_X = X.shape if Y is not None: dim_Y = Y.shape if len(dim_X) == 2 and len(dim_Y) == 2: temp = np.corrcoef(X, Y, rowvar=False) Corr = temp[0:dim_X[1], dim_X[1]:dim_X[1]+dim_Y[1]] elif len(dim_X) == 1 and len(dim_Y) == 2: temp = np.corrcoef(X, Y, rowvar=False) Corr = temp[0, 1:1+dim_Y[1]] elif len(dim_X) == 2 and len(dim_Y) == 1: temp = np.corrcoef(X, Y, rowvar=False) Corr = temp[1:1+dim_X[1], 0] else: temp = np.corrcoef(X, Y, rowvar=False) Corr = temp[0, 1] else: if len(X.shape) != 2: raise ValueError("X must be a 2D matrix") Corr = np.corrcoef(X, rowvar=False) return Corr
[docs]def mat_corr(X, Y=None, dataPrecision='double'): """ Perform corr as in MATLAB, pair-wise Pearson correlation between columns in X and Y :param X: 1D or 2D matrix, numpy.ndarray or torch.Tensor :param Y: 1D or 2D matrix, or None, numpy.ndarray or torch.Tensor :param dataPrecision: 'double' or 'single' X and Y have the same number of rows :return: Corr Note: this method will use memory as it concatenates X and Y along column direction. #modified version of the torch corr on 08/05/2024 """ np_float, np_eps = set_data_precision(dataPrecision) if not isinstance(X, np.ndarray): X = np.ndarray(X, dtype=np_float) else: X = X.astype(np_float) if Y is not None: if not isinstance(Y, np.ndarray): Y = np.ndarray(Y, dtype=np_float) else: Y = Y.astype(np_float) # Check size of X and Y if len(X.shape) > 2 or (Y is not None and len(Y.shape) > 2): raise ValueError("X and Y must be 1D or 2D matrices") if Y is not None and X.shape[0] != Y.shape[0]: raise ValueError("X and Y must have the same number of columns") if Y is not None: # Subtract the mean to calculate the covariance X_centered = X - np.mean(X, axis=0, keepdims=True) Y_centered = Y - np.mean(Y, axis=0, keepdims=True) # Compute the standard deviation of the columns std_X = np.std(X_centered, axis=0, keepdims=True, ddof=1) std_Y = np.std(Y_centered, axis=0, keepdims=True, ddof=1) # Compute the correlation matrix numerator = (X_centered.T @ Y_centered) denominator = (std_X.T @ std_Y) * np.array(X.shape[0] - 1) Corr = numerator / (denominator + np_eps) else: if len(X.shape) != 2: raise ValueError("X must be a 2D matrix") X_centered = X - np.mean(X, axis=0, keepdims=True) std_X = np.std(X_centered, axis=0, keepdims=True, ddof=1) numerator = (X_centered.T @ X_centered) denominator = (std_X.T @ std_X) * np.array(X.shape[0] - 1) Corr = numerator / (denominator + np.eps) return Corr
[docs]def mat_corr_torch(X, Y=None, dataPrecision='double'): """ Perform corr as in MATLAB, pair-wise Pearson correlation between columns in X and Y :param X: 1D or 2D matrix, numpy.ndarray or torch.Tensor :param Y: 1D or 2D matrix, or None, numpy.ndarray or torch.Tensor :param dataPrecision: 'double' or 'single' X and Y have the same number of rows :return: Corr Note: this method will use memory as it concatenates X and Y along column direction. By Yuncong Ma, 12/6/2023 """ torch_float, torch_eps = set_data_precision_torch(dataPrecision) if not isinstance(X, torch.Tensor): X = torch.tensor(X, dtype=torch_float) else: X = X.type(torch_float) if Y is not None: if not isinstance(Y, torch.Tensor): Y = torch.tensor(Y, dtype=torch_float) else: Y = Y.type(torch_float) # Check size of X and Y if len(X.shape) > 2 or (Y is not None and len(Y.shape) > 2): raise ValueError("X and Y must be 1D or 2D matrices") if Y is not None and X.shape[0] != Y.shape[0]: raise ValueError("X and Y must have the same number of columns") if Y is not None: # Subtract the mean to calculate the covariance X_centered = X - torch.mean(X, dim=0, keepdim=True) Y_centered = Y - torch.mean(Y, dim=0, keepdim=True) # Compute the standard deviation of the columns std_X = torch.std(X_centered, dim=0, keepdim=True, unbiased=True) std_Y = torch.std(Y_centered, dim=0, keepdim=True, unbiased=True) # Compute the correlation matrix numerator = (X_centered.T @ Y_centered) denominator = (std_X.T @ std_Y) * torch.tensor(X.shape[0] - 1) Corr = numerator / denominator else: if len(X.shape) != 2: raise ValueError("X must be a 2D matrix") X_centered = X - torch.mean(X, dim=0, keepdim=True) std_X = torch.std(X_centered, dim=0, keepdim=True, unbiased=True) numerator = (X_centered.T @ X_centered) denominator = (std_X.T @ std_X) * torch.tensor(X.shape[0] - 1) Corr = numerator / denominator return Corr