Skip to content

Commit

Permalink
#115: avoid irlba code path unless necessary
Browse files Browse the repository at this point in the history
  • Loading branch information
jlmelville committed Apr 20, 2024
1 parent 3b9628e commit 2c94a8a
Show file tree
Hide file tree
Showing 11 changed files with 64 additions and 11 deletions.
40 changes: 35 additions & 5 deletions R/init.R
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,17 @@ rspectra_laplacian_eigenmap <- function(A, ndim = 2, verbose = FALSE) {
# and because A is symmetric, they're equivalent
M <- A / colSums(A)
res <- rspectra_eigs_asym(M, ndim)
if (is.null(res) || ncol(res$vectors) < ndim) {
if (is.null(res) ||
!is.list(res) ||
!"vectors" %in% names(res) ||
is.null(res$vectors) ||
tryCatch(
is.na(ncol(res$vectors)),
error = function(e) {
TRUE
}
) ||
ncol(res$vectors) < ndim) {
message(
"Laplacian Eigenmap failed to converge, ",
"using random initialization instead"
Expand Down Expand Up @@ -125,7 +135,17 @@ rspectra_normalized_laplacian_init <- function(A, ndim = 2, verbose = FALSE) {
L <- form_normalized_laplacian(A)
res <- rspectra_eigs_sym(L, ndim, verbose = verbose)

if (is.null(res) || ncol(res$vectors) < ndim) {
if (is.null(res) ||
!is.list(res) ||
!"vectors" %in% names(res) ||
is.null(res$vectors) ||
tryCatch(
is.na(ncol(res$vectors)),
error = function(e) {
TRUE
}
) ||
ncol(res$vectors) < ndim) {
message(
"Spectral initialization failed to converge, ",
"using random initialization instead"
Expand Down Expand Up @@ -215,16 +235,26 @@ irlba_normalized_laplacian_init <- function(A, ndim = 2, verbose = FALSE) {
# Laplacian and look for largest eigenvalues
L <- form_modified_laplacian(A)
res <- irlba_eigs_sym(L, ndim, smallest = FALSE)
# shift back the eigenvalues
res$values <- 2.0 - res$values
if (is.null(res) || ncol(res$vectors) < ndim) {
if (is.null(res) ||
!is.list(res) ||
!"vectors" %in% names(res) ||
is.null(res$vectors) ||
tryCatch(
is.na(ncol(res$vectors)),
error = function(e) {
TRUE
}
) ||
ncol(res$vectors) < ndim) {
message(
"Spectral initialization failed to converge, ",
"using random initialization instead"
)
n <- nrow(A)
return(rand_init(n, ndim))
}
# shift back the eigenvalues
res$values <- 2.0 - res$values
sort_eigenvectors(res, ndim)
}

Expand Down
12 changes: 11 additions & 1 deletion R/rspectra_init.R
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,17 @@ rspectra_eigs_sym <- function(L, ndim, verbose = FALSE) {
tsmessage("RSpectra calculation failed, retrying with shifted")
}
))
if (is.null(res) || ncol(res$vectors) < ndim) {
if (is.null(res) ||
!is.list(res) ||
!"vectors" %in% names(res) ||
is.null(res$vectors) ||
tryCatch(
is.na(ncol(res$vectors)),
error = function(e) {
TRUE
}
) ||
ncol(res$vectors) < ndim) {
suppressWarnings(res <- tryCatch(
RSpectra::eigs_sym(
L,
Expand Down
2 changes: 2 additions & 0 deletions R/uwot.R
Original file line number Diff line number Diff line change
Expand Up @@ -4000,6 +4000,8 @@ save_uwot <- function(model, file, unload = FALSE, verbose = FALSE) {
#' used during loading of the model. This directory cannot be removed until
#' this model has been unloaded by using \code{\link{unload_uwot}}.
#' @examples
#' library(RSpectra)
#'
#' iris_train <- iris[c(1:10, 51:60), ]
#' iris_test <- iris[100:110, ]
#'
Expand Down
2 changes: 2 additions & 0 deletions man/load_uwot.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions tests/testthat/test_errors.R
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
library(uwot)
library(RSpectra)
context("Input validation")

expect_error(umap(X = list(X = "bad", Y = "wrong", nn = "what")), "data format")
Expand Down
1 change: 1 addition & 0 deletions tests/testthat/test_neighbors.R
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
library(uwot)
library(RSpectra)
context("neighbors")

i10nn4dist <- matrix(c(
Expand Down
13 changes: 8 additions & 5 deletions tests/testthat/test_normlaplacian.R
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
library(uwot)
library(RSpectra)
context("normalized laplacian")

# this exists as a separate file only because it's easier to comment out as
Expand Down Expand Up @@ -29,12 +30,14 @@ test_that("normalized laplacian", {
res <- normalized_laplacian_init(sparse_m)
expect_equal(abs(res), abs_expected_norm_lap, tolerance = 0.2)

# ensure irlba code path gets tested
res <- irlba_tsvd_normalized_laplacian_init(sparse_m)
expect_equal(abs(res), abs_expected_norm_lap, tolerance = 0.2)
# 115: ensure irlba code path gets tested if we can avoid Matrix ABI issue
if (Matrix::Matrix.Version()$package >= "1.6.3") {
res <- irlba_tsvd_normalized_laplacian_init(sparse_m)
expect_equal(abs(res), abs_expected_norm_lap, tolerance = 0.2)

res <- irlba_normalized_laplacian_init(sparse_m)
expect_equal(abs(res), abs_expected_norm_lap, tolerance = 0.2)
res <- irlba_normalized_laplacian_init(sparse_m)
expect_equal(abs(res), abs_expected_norm_lap, tolerance = 0.2)
}
})

test_that("laplacian eigenmap", {
Expand Down
1 change: 1 addition & 0 deletions tests/testthat/test_saveload.R
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
library(uwot)
library(RSpectra)
context("load/save model")

test_that("can save and load simple model", {
Expand Down
1 change: 1 addition & 0 deletions tests/testthat/test_similarity_graph.R
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
library(uwot)
library(RSpectra)
context("similarity graph")

# #96: more convenient way to just get the high dimensional similarity graph
Expand Down
1 change: 1 addition & 0 deletions tests/testthat/test_spectral.R
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
library(uwot)
library(RSpectra)
context("Spectral")

test_that("1 dimensional output gives a matrix", {
Expand Down
1 change: 1 addition & 0 deletions tests/testthat/test_transform.R
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
library(uwot)
library(RSpectra)
context("Transform")

diagonal1s <- as(Matrix::drop0(diag(1, nrow(V_asymm), ncol(V_asymm))), "generalMatrix")
Expand Down

0 comments on commit 2c94a8a

Please sign in to comment.