% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/largeVis.R
\name{projectKNNs}
\alias{projectKNNs}
\title{Project a distance matrix into a lower-dimensional space.}
\usage{
projectKNNs(
  wij,
  dim = 2,
  sgd_batches = NULL,
  M = 5,
  gamma = 7,
  alpha = 1,
  rho = 1,
  coords = NULL,
  useDegree = FALSE,
  momentum = NULL,
  seed = NULL,
  threads = NULL,
  verbose = getOption("verbose", TRUE)
)
}
\arguments{
\item{wij}{A symmetric sparse matrix of edge weights, in C-compressed format, as created with the \code{Matrix} package.}

\item{dim}{numeric Number of dimensions for the projection space (default=2).}

\item{sgd_batches}{The number of edges to process during SGD (default=NULL). Defaults to a value set based on the size of the dataset. If the parameter given is
between \code{0} and \code{1}, the default value will be multiplied by the parameter.}

\item{M}{numeric Number of negative edges to sample for each positive edge (default=5).}

\item{gamma}{numeric Strength of the force pushing non-neighbor nodes apart (default=7).}

\item{alpha}{numeric Hyperparameter used in the default distance function, \eqn{1 / (1 + \alpha \dot ||y_i - y_j||^2)} (default=1).  The function relates the distance
between points in the low-dimensional projection to the likelihood that the two points are nearest neighbors. Increasing \eqn{\alpha} tends
to push nodes and their neighbors closer together; decreasing \eqn{\alpha} produces a broader distribution. Setting \eqn{\alpha} to zero
enables the alternative distance function. \eqn{\alpha} below zero is meaningless.}

\item{rho}{numeric Initial learning rate (default=1)}

\item{coords}{An initialized coordinate matrix (default=NULL).}

\item{useDegree}{boolean Whether to use vertex degree to determine weights (default=FALSE). If TRUE, weights determined in negative sampling; if FALSE, weights determined by the sum of the vertex's edges. See Notes.}

\item{momentum}{If not \code{NULL} (the default), SGD with momentum is used, with this multiplier, which must be between 0 and 1. Note that
momentum can drastically speed-up training time, at the cost of additional memory consumed.}

\item{seed}{numeric Random seed to be passed to the C++ functions (default=NULL). If NULL, sampled from hardware entropy pool.
Note that if the seed is not \code{NULL} (the default), the maximum number of threads will be set to 1 in phases of the algorithm
that would otherwise be non-deterministic.}

\item{threads}{numeric The maximum number of threads to spawn (default=NULL). Determined automatically if \code{NULL}.}

\item{verbose}{boolean Verbosity (default=getOption("verbose", TRUE))}
}
\value{
A dense [N,D] matrix of the coordinates projecting the w_ij matrix into the lower-dimensional space.
}
\description{
Takes as input a sparse matrix of the edge weights connecting each node to its nearest neighbors, and outputs
a matrix of coordinates embedding the inputs in a lower-dimensional space.
}
\details{
The algorithm attempts to estimate a \code{dim}-dimensional embedding using stochastic gradient descent and
negative sampling.

The objective function is: \deqn{ O = \sum_{(i,j)\in E} w_{ij} (\log f(||p(e_{ij} = 1||) + \sum_{k=1}^{M} E_{jk~P_{n}(j)} \gamma \log(1 - f(||p(e_{ij_k} - 1||)))}
where \eqn{f()} is a probabilistic function relating the distance between two points in the low-dimensional projection space,
and the probability that they are nearest neighbors.

The default probabilistic function is \eqn{1 / (1 + \alpha \dot ||x||^2)}. If \eqn{\alpha} is set to zero,
an alternative probabilistic function, \eqn{1 / (1 + \exp(x^2))} will be used instead.

Note that the input matrix should be symmetric.  If any columns in the matrix are empty, the function will fail.
}
\note{
If specified, \code{seed} is passed to the C++ and used to initialize the random number generator. This will not, however, be
sufficient to ensure reproducible results, because the initial coordinate matrix is generated using the \code{R} random number generator.
To ensure reproducibility, call \code{\link[base]{set.seed}} before calling this function, or pass it a pre-allocated coordinate matrix.

The original paper called for weights in negative sampling to be calculated according to the degree of each vertex, the number of edges
connecting to the vertex. The reference implementation, however, uses the sum of the weights of the edges to each vertex. In experiments, the
difference was imperceptible with small (MNIST-size) datasets, but the results seems aesthetically preferrable using degree. The default
is to use the edge weights, consistent with the reference implementation.
}
\examples{
\dontrun{
data(CO2)
CO2$Plant <- as.integer(CO2$Plant)
CO2$Type <- as.integer(CO2$Type)
CO2$Treatment <- as.integer(CO2$Treatment)
co <- scale(as.matrix(CO2))
# Very small datasets often produce a warning regarding the alias table.  This is safely ignored.
suppressWarnings(vis <- largeVis(t(co), K = 20, sgd_batches = 1, threads = 2))
suppressWarnings(coords <- projectKNNs(vis$wij, threads = 2))
plot(t(coords))
}

}
