1. Independent Component Analysis (ICA)

Koki Tsuyuzaki

Department of Artificial Intelligence Medicine, Graduate School of Medicine, Chiba University
k.t.the-answer@hotmail.co.jp

2026-11-02

Introduction

In this vignette, we consider approximating a data matrix as a product of multiple low-rank matrices (a.k.a., factor matrices).

Test data is available from toyModel.

library("iTensor")
data1 <- iTensor::toyModel("ICA_Type1")
data2 <- iTensor::toyModel("ICA_Type2")
data3 <- iTensor::toyModel("ICA_Type3")
data4 <- iTensor::toyModel("ICA_Type4")
data5 <- iTensor::toyModel("ICA_Type5")
dim(data1$X_observed)
## [1] 500   3
dim(data2$X_observed)
## [1] 500   3
dim(data3$X_observed)
## [1] 500   3
dim(data4$X_observed)
## [1] 480   3
dim(data5$X_observed) # N < P systems
## [1]  50 200

Summary of these data is as follows:

  1. ICA with time-independent sub-Gaussian data
  2. ICA with time-independent super-Gaussian data
  3. ICA with data mixed with signals having no time dependence and different kurtosis
  4. ICA with time-dependent data
  5. IPCA in N < P systems

You will see that the stuctures of these data as follows.

pairs(data1$X_observed, main="data1")

pairs(data2$X_observed, main="data2")

pairs(data3$X_observed, main="data3")

pairs(data4$X_observed, main="data4")

dim(data5$X_observed)
## [1]  50 200

To perform and visualize all the ICA at once, here we write some functions as follows.

allICA <- function(X, J){
    # Classic ICA Methods
    out.FastICA <- ICA(X=X, J=J, algorithm="FastICA")
    out.InfoMax <- ICA(X=X, J=J, algorithm="InfoMax")
    out.ExtInfoMax <- ICA(X=X, J=J, algorithm="ExtInfoMax")
    # Modern ICA Method
    out.JADE <- ICA2(X=X, J=J, algorithm="JADE")
    # Output
    list(out.FastICA=out.FastICA, out.InfoMax=out.InfoMax,
      out.ExtInfoMax=out.ExtInfoMax, out.JADE=out.JADE)
}

CorrIndexAllICA <- function(S, out){
    tmp <- lapply(out, function(x, S){CorrIndex(cor(S, Re(x$S)))}, S=S)
    Name <- gsub("out.", "", names(tmp))
    Value <- round(unlist(tmp), 3)
    names(Value) <- NULL
    cbind(Name, Value)
    tmp <- as.data.frame(cbind(Name, Value))
    colnames(tmp) <- c("Method", "CorrIndex")
    knitr::kable(tmp)
}

Note that we select only four ICA algorithms for the demonstration but in iTensor 12 ICA algorithms are available. For the details, check ?ICA and ?ICA2.

1. ICA with time-independent sub-Gaussian data

In this data, according to the independence between estimated source signal, an upright square means that the calculation is successful and other cases such as a rhombus rotated 45 degrees from a square means that the calculation is fail.

set.seed(123456)
out1 <- allICA(X=data1$X_observed, J=3)

Here we use CorrIndex, which is a performance index to evaluate ICA results (Sobhani 2022). CorrIndex imply that FastICA, ExtInfoMax, and JADE performed well (the closer to 0, the better the performance).

CorrIndexAllICA(data1$S_true, out1)
Method CorrIndex
FastICA 0.263
InfoMax 7.439
ExtInfoMax 0.263
JADE 0.221

We can see the details of source signals as follows.

pairs(out1$out.FastICA$S, main="FastICA")

pairs(out1$out.InfoMax$S, main="InfoMax")

pairs(out1$out.ExtInfoMax$S, main="ExtInfoMax")

pairs(Re(out1$out.JADE$S), main="JADE")

2. ICA with time-independent super-Gaussian data

In this data, if the outliers are distributed along the lines of x = 0 and y = 0, the calculation is successful and if they are of the cross-shape, it is a failure.

set.seed(123456)
out2 <- allICA(X=data2$X_observed, J=3)

CorrIndex imply that all the algorithms performed well.

CorrIndexAllICA(data2$S_true, out2)
Method CorrIndex
FastICA 0.268
InfoMax 0.322
ExtInfoMax 0.268
JADE 0.374

We can see the details of source signals as follows.

pairs(out2$out.FastICA$S, main="FastICA")

pairs(out2$out.InfoMax$S, main="InfoMax")

pairs(out2$out.ExtInfoMax$S, main="ExtInfoMax")

pairs(Re(out2$out.JADE$S), main="JADE")

3. ICA with data mixed with signals having no time dependence and different kurtosis

In this data, the uniform distribution should be extracted in such a way that it is not rhombic, and furthermore the normal distribution and the t-distribution with 1 degree of freedom should be extracted independently. Sometimes, it is difficult ot determine visually though.

set.seed(123456)
out3 <- allICA(X=data3$X_observed, J=3)

CorrIndex imply that FastICA, ExtInfoMax, and JADE performed well.

CorrIndexAllICA(data3$S_true, out3)
Method CorrIndex
FastICA 0.23
InfoMax 3.799
ExtInfoMax 0.213
JADE 0.408

We can see the details of source signals as follows.

pairs(out3$out.FastICA$S, main="FastICA")

pairs(out3$out.InfoMax$S, main="InfoMax")

pairs(out3$out.ExtInfoMax$S, main="ExtInfoMax")

pairs(Re(out3$out.JADE$S), main="JADE")

4. ICA with time-dependent data

In this data, if the mesh pattern is reproduced, the calculation is successful.

set.seed(123456)
out4 <- allICA(X=data4$X_observed, J=3)

CorrIndex imply that FastICA, ExtInfoMax, and JADE performed well.

CorrIndexAllICA(data4$S_true, out4)
Method CorrIndex
FastICA 0.081
InfoMax 8.026
ExtInfoMax 0.081
JADE 0.08

We can see the details of source signals as follows.

pairs(out4$out.FastICA$S, main="FastICA")

pairs(out4$out.InfoMax$S, main="InfoMax")

pairs(out4$out.ExtInfoMax$S, main="ExtInfoMax")

pairs(Re(out4$out.JADE$S), main="JADE")

5. IPCA in N < P systems

This kind of data is a thin and long matrix (N < P), which is a very common data structure in omics data.

set.seed(123456)

# iTensor's IPCA
out5 <- ICA2(X=data5$X_observed, J=3, algorithm="IPCA")

We can see the details of source signals as follows.

pairs(out5$S, main="IPCA (iTensor)", pch=16)

Session Information

## R version 3.6.3 (2020-02-29)
## Platform: x86_64-conda-linux-gnu (64-bit)
## Running under: Rocky Linux 9.5 (Blue Onyx)
## 
## Matrix products: default
## BLAS:   /home/koki/miniconda3/lib/libblas.so.3.9.0
## LAPACK: /home/koki/miniconda3/lib/liblapack.so.3.9.0
## 
## locale:
##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=C              
##  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
##  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
## [1] iTensor_1.0.7
## 
## loaded via a namespace (and not attached):
##  [1] Rcpp_1.1.2      knitr_1.42      rTensor_1.5.0   splines_3.6.3  
##  [5] MASS_7.3-58.3   lattice_0.20-45 R6_2.5.1        rlang_0.4.11   
##  [9] fastmap_1.1.1   highr_0.10      tools_3.6.3     grid_3.6.3     
## [13] nlme_3.1-162    mgcv_1.8-42     xfun_0.38       jquerylib_0.1.4
## [17] htmltools_0.5.5 yaml_2.3.7      digest_0.6.31   jointDiag_0.4  
## [21] Matrix_1.5-4    sass_0.4.0      evaluate_0.20   rmarkdown_2.11 
## [25] compiler_3.6.3  bslib_0.3.1     jsonlite_1.8.4  einsum_0.2.0

References

Sobhani, E. et al. 2022. “CorrIndex: A Permutation Invariant Performance Index.” Signal Processing 195: 108457.