-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
128 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#' Anomaly index. | ||
#' | ||
#' Calculates an index that looks for the best projection of | ||
#' observations that are outside a pre-determined p-D ellipse. | ||
#' | ||
#' @export | ||
anomaly_index <- function() { | ||
|
||
function(mat, ell2d) { | ||
|
||
mat_tab <- mean(sqrt(mahalanobis(mat, center=c(0,0), cov=ell2d))) | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
#' A guided anomaly tour path. | ||
#' | ||
#' The guided anomaly tour is a variation of the guided tour that is | ||
#' using an ellipse to determine anomalies on which to select target planes. | ||
#' | ||
#' Usually, you will not call this function directly, but will pass it to | ||
#' a method that works with tour paths like \code{\link{animate_slice}}, | ||
#' \code{\link{save_history}} or \code{\link{render}}. | ||
#' | ||
#' @param index_f the section pursuit index function to optimise. The function | ||
#' needs to take two arguments, the projected data, indexes of anomalies. | ||
#' @param d target dimensionality | ||
#' @param alpha the initial size of the search window, in radians | ||
#' @param cooling the amount the size of the search window should be adjusted | ||
#' by after each step | ||
#' @param search_f the search strategy to use | ||
#' @param max.tries the maximum number of unsuccessful attempts to find | ||
#' a better projection before giving up | ||
#' @param max.i the maximum index value, stop search if a larger value is found | ||
#' @param ellipse pxp variance-covariance matrix defining ellipse, default NULL. | ||
#' Useful for comparing data with some hypothesized null. | ||
#' @param ellsize This can be considered the equivalent of a critical value, used to | ||
#' scale the ellipse larger or smaller to capture more or fewer anomalies. Default 1. | ||
#' @param ... arguments sent to the search_f | ||
#' @seealso \code{\link{slice_index}} for an example of an index functions. | ||
#' \code{\link{search_geodesic}}, \code{\link{search_better}}, | ||
#' \code{\link{search_better_random}} for different search strategies | ||
#' @export | ||
#' @examples | ||
#' animate_xy(flea[, 1:6], guided_anomaly_tour(anomaly_index(), | ||
#' ellipse=cov(flea[,1:6])), ellipse=cov(flea[,1:6]), axes="off") | ||
guided_anomaly_tour <- function(index_f, d = 2, alpha = 0.5, cooling = 0.99, | ||
max.tries = 25, max.i = Inf, | ||
ellipse, ellsize=1, | ||
search_f = search_geodesic, ...) { | ||
h <- NULL | ||
|
||
generator <- function(current, data, tries, ...) { | ||
if (is.null(current)) { | ||
return(basis_init(ncol(data), d)) | ||
} | ||
|
||
if (is.null(h)) { | ||
half_range <- compute_half_range(NULL, data, FALSE) | ||
} | ||
|
||
index <- function(proj) { | ||
# Check which observations are outside pD ellipse | ||
mdst <- sqrt(mahalanobis(data, center=rep(0, ncol(data)), cov=ellipse)) | ||
anomalies <- which(mdst > ellsize) | ||
stopifnot(length(anomalies) > 0) | ||
# Project ellipse into 2D | ||
evc <- eigen(ellipse) | ||
ellinv <- (evc$vectors) %*% diag(evc$values) %*% t(evc$vectors) | ||
e2 <- t(proj) %*% ellinv %*% proj | ||
evc2 <- eigen(e2) | ||
ell2d <- (evc2$vectors) %*% diag(sqrt(evc2$values)) %*% t(evc2$vectors) | ||
index_f(as.matrix(data[anomalies,]) %*% proj, ell2d) | ||
} | ||
|
||
cur_index <- index(current) | ||
|
||
if (cur_index > max.i) { | ||
cat("Found index ", cur_index, ", larger than selected maximum ", max.i, ". Stopping search.\n", | ||
sep = "" | ||
) | ||
cat("Final projection: \n") | ||
if (ncol(current) == 1) { | ||
for (i in 1:length(current)) { | ||
cat(sprintf("%.3f", current[i]), " ") | ||
} | ||
cat("\n") | ||
} | ||
else { | ||
for (i in 1:nrow(current)) { | ||
for (j in 1:ncol(current)) { | ||
cat(sprintf("%.3f", current[i, j]), " ") | ||
} | ||
cat("\n") | ||
} | ||
} | ||
return(NULL) | ||
} | ||
|
||
basis <- search_f(current, alpha, index, tries, max.tries, cur_index = cur_index, ...) | ||
alpha <<- alpha * cooling | ||
|
||
list(target = basis$target, index = index) | ||
} | ||
|
||
new_geodesic_path("guided", generator) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.