# Writing New Embedding Algorithms

For example, the below algorithm for lol.project.lol:

#' Linear Optimal Low-Rank Projection (LOL)
#'
#' A function for implementing the Linear Optimal Low-Rank Projection (LOL) Algorithm.
#'
#' @param X \code{[n, d]} the data with \code{n} samples in \code{d} dimensions.
#' @param Y \code{[n]} the labels of the samples with \code{K} unique labels.
#' @param r the rank of the projection. Note that \code{r >= K}, and \code{r < d}.
#' @param ... trailing args.
#' @return A list of class \code{embedding} containing the following:
#' \item{A}{\code{[d, r]} the projection matrix from \code{d} to \code{r} dimensions.}
#' \item{ylabs}{\code{[K]} vector containing the \code{K} unique, ordered class labels.}
#' \item{centroids}{\code{[K, d]} centroid matrix of the \code{K} unique, ordered classes in native \code{d} dimensions.}
#' \item{priors}{\code{[K]} vector containing the \code{K} prior probabilities for the unique, ordered classes.}
#' \item{Xr}{\code{[n, r]} the \code{n} data points in reduced dimensionality \code{r}.}
#' \item{cr}{\code{[K, r]} the \code{K} centroids in reduced dimensionality \code{r}.}
#' @author Eric Bridgeford
#' @examples
#' library(lolR)
#' data <- lol.sims.rtrunk(n=200, d=30)  # 200 examples of 30 dimensions
#' X <- data$X; Y <- data$Y
#' model <- lol.project.lol(X=X, Y=Y, r=5)  # use lol to project into 5 dimensions
#' @export
lol.project.lol <- function(X, Y, r, ...) {
# class data
info <- lol.utils.info(X, Y)
priors <- info$priors; centroids <- info$centroids
K <- info$K; ylabs <- info$ylabs
n <- info$n; d <- info$d
deltas <- lol.utils.deltas(centroids, priors)
centroids <- t(centroids)

nv <- r - (K)
if (nv > 0) {

# Performing Cross-Validation with your Algorithm

With your new algorithm, you may want to perform some sort of cross-validation. Following the above spec, this is incredibly easy. Your argument may, for instance, require its own individual hyperparameters. For example, in my example above, I have a hyperparameter for r, the rank of the embedding. I can define the following list of the optional arguments:

alg = lol.project.lol
r = <desired-rank>  # the desired rank I want to embed into
alg.opts = list(r=r)
embed = "A"  # the name of the embedding matrix produced
alg.return = embed

I can then pass my algorithm into the lol.xval.eval algorithm:

xval.out <- lol.xval.eval(X, Y, alg=alg, alg.opts=alg.opts, alg.return=alg.return, k=<k>)

where <k> specifies the desired cross-validation method to use. For more details, see the xval vignette.

See the tutorial vignette extend_classification for how to specify the classifier, classifier.opts, and classifier.return. Alternatively, do not include these keyworded arguments to lol.xval.xval to use the default lda classifier.

Now, you should be able to use your user-defined embedding method with the lol package.