# Algorithm comparison

#### Cristian Castiglione

## Workspace setup

Load the package in the workspace.

    library(sgdGMF)

Load other useful packages in the workspace.

    library(ggplot2)
    library(ggpubr)
    library(reshape2)

## Ant traits data

Load the ant traits data in the workspace and define the response matrix `Y` and covariate matrices `X` and `Z`.

    # install.packages("mvabund")
    # data(antTraits, package = "mvabund")

    load(url("https://raw.githubusercontent.com/cran/mvabund/master/data/antTraits.RData"))

    Y = as.matrix(antTraits$abund)
    X = as.matrix(antTraits$env[,-3])
    Z = matrix(1, nrow = ncol(Y), ncol = 1)

    n = nrow(Y)
    m = ncol(Y)

## Model specification

Set the model family to Poisson since the response matrix contain count data.

    family = poisson()

Select the optimal number of latent factors using the function , which employs an adjusted eigenvalue thresholding method to identify the optimal elbow point of a screeplot.

    ncomp = sgdgmf.rank(Y = Y, X = X, Z = Z, family = family)$ncomp
    cat("Selected rank: ", ncomp)
    #> Selected rank:  2

## Model estimation

implements four estimation algorithms which are outlined below. Notice that we here describe the algorithms by assuming, without loss of generality, that \(B = 0\) and \(A = 0\) (see the documentation of the function for the notation). In the real implementation, where non-zero \(B\) and \(A\) are considered, we jointly optimize \([A, U]\) and \([B, V]\) following the same algorithmic strategy, but accounting for regression effects.

Estimate a Poisson GMF model using iterated least squares, diagonal quasi-Newton and stochastic gradient descent algorithms.

    gmf.airwls = sgdgmf.fit(Y, X, Z, ncomp = ncomp, family = family, method = "airwls")
    gmf.newton = sgdgmf.fit(Y, X, Z, ncomp = ncomp, family = family, method = "newton")
    gmf.sgd    = sgdgmf.fit(Y, X, Z, ncomp = ncomp, family = family, method = "sgd", sampling = "block")

## Model validation

Compute the correlation between the observed data and the predicted values.

    cat(" AIRWLS: ", 100 * round(cor(c(Y), c(gmf.airwls$mu)), 4), "\n",
        " Newton: ", 100 * round(cor(c(Y), c(gmf.newton$mu)), 4), "\n",
        " SGD:    ", 100 * round(cor(c(Y), c(gmf.sgd$mu)), 4), sep = "")
    #>  AIRWLS: 90.26
    #>  Newton: 89.62
    #>  SGD:    89.98

Compute the partial deviance residuals holding out from the model the estimated matrix factorization. Additionally, compute the spectrum of such a residual matrix.

    res.airwls = residuals(gmf.airwls, partial = FALSE, spectrum = TRUE, ncomp = 20)
    res.newton = residuals(gmf.newton, partial = FALSE, spectrum = TRUE, ncomp = 20)
    res.sgd = residuals(gmf.sgd, partial = FALSE, spectrum = TRUE, ncomp = 20)

Analyze the residual distribution.

Plot the variance explained by each principal component of the residual matrix.

## Observations vs fitted values

Plot the abundance predicted by each method comparing it with the observed matrix.

## Latent scores and low-dimensional representation

Plot the latent scores and loadings in a biplot-like figure.