How to set constraints for non-negativity in parallel factor analysis using the multiway package in R?

83 views Asked by At

I want to perform a Parallel Factor Analysis (PARAFAC) with data from Fluorescence spectroscopy. I have a three dimensional array (39x151x43) that I pass to the parafac function in the "multiway" package. So far, it works well but I get negative values for some of the components.

I read in the manual that one can specify constraints for non-negativity. However, I don't understand how the vector for the constraints option should look like. When I try to do the following I get an error that says "Input 'const' must be 3 element vector specifying constraint for each mode"

#### creating dummy values for Stackoverflow ####
A <- c(1:39)
B <- rnorm(151, mean =1, sd=0.5)
C <- rnorm(43, mean=1, sd = 0.5)

myArray <- array(c(A,B,C), dim = c(39,151,43))
dim(myArray)

library(multiway)  # load the library
myModel <- parafac(myArray, nfac = 3) # how to set const? 
#Input 'const' must be  3  element vector specifying constraint for each mode

Some research was to no avail. How should the vector look like so that the parafac function accepts it?

1

There are 1 answers

0
Silence Dogood On BEST ANSWER

The parameters of constraints vector are unconstrained:0,orthogonal:1,non-negative:2.

If all three inputs A,B,C are to be non-negative the constraint vector should be const=c(2,2,2)

#Always remember to use set.seed when performing random sampling
#this ensures the example is reproducible 

set.seed(123)
A <- c(1:39)
B <- rnorm(151, mean =1, sd=0.5)
C <- rnorm(43, mean=1, sd = 0.5)

myArray <- array(c(A,B,C), dim = c(39,151,43))
dim(myArray)

library(multiway)

#Without constraints  
myModel_Default <- parafac(myArray, nfac = 3) 

#Percentage of negative elements

sum(myModel_Default$A<0)/length(myModel_Default$A)
#[1] 0.3333333
sum(myModel_Default$B<0)/length(myModel_Default$B)
#[1] 0.6865342
sum(myModel_Default$C<0)/length(myModel_Default$C)
#[1] 0.3488372

#With constraints

myModel_NonNeg <- parafac(myArray, nfac = 3,const=c(2,2,2))

sum(myModel_NonNeg$A<0)/length(myModel_NonNeg$A)
#[1] 0
sum(myModel_NonNeg$B<0)/length(myModel_NonNeg$B)
#[1] 0
sum(myModel_NonNeg$C<0)/length(myModel_NonNeg$C)
#[1] 0