X-Git-Url: https://git.auder.net/?p=epclust.git;a=blobdiff_plain;f=epclust%2FR%2Fmain.R;h=a039d1cc029f94f641d6943b7aacc63d27c38002;hp=31ce390e15f717f55420622d4847ee76abb6a6ef;hb=37c82bbafbffc19e8b47a521952bac58f189e9ea;hpb=bccecb19b4faa20808dab761d30f2d2dd4dcf587 diff --git a/epclust/R/main.R b/epclust/R/main.R index 31ce390..a039d1c 100644 --- a/epclust/R/main.R +++ b/epclust/R/main.R @@ -39,16 +39,16 @@ #' } #' @param K1 Number of clusters to be found after stage 1 (K1 << N [number of series]) #' @param K2 Number of clusters to be found after stage 2 (K2 << K1) -#' @param nb_per_chunk (Maximum) number of items to retrieve in one batch, for both types of -#' retrieval: resp. series and contribution; in a vector of size 2 +#' @param nb_series_per_chunk (Maximum) number of series to retrieve in one batch #' @param algo_clust1 Clustering algorithm for stage 1. A function which takes (data, K) #' as argument where data is a matrix in columns and K the desired number of clusters, #' and outputs K medoids ranks. Default: PAM #' @param algo_clust2 Clustering algorithm for stage 2. A function which takes (dists, K) #' as argument where dists is a matrix of distances and K the desired number of clusters, #' and outputs K clusters representatives (curves). Default: k-means -#' @param nb_items_clust1 (Maximum) number of items in input of the clustering algorithm -#' for stage 1 +#' @param nb_items_clust1 (~Maximum) number of items in input of the clustering algorithm +#' for stage 1. At worst, a clustering algorithm might be called with ~2*nb_items_clust1 +#' items; but this could only happen at the last few iterations. #' @param wav_filt Wavelet transform filter; see ?wavelets::wt.filter #' @param contrib_type Type of contribution: "relative", "logit" or "absolute" (any prefix) #' @param WER "end" to apply stage 2 after stage 1 has fully iterated, or "mix" to apply @@ -84,12 +84,12 @@ #' series = do.call( cbind, lapply( 1:6, function(i) #' do.call(cbind, wmtsa::wavBootstrap(ref_series[i,], n.realization=400)) ) ) #' #dim(series) #c(2400,10001) -#' medoids_ascii = claws(series, K1=60, K2=6, nb_per_chunk=c(200,500), verbose=TRUE) +#' medoids_ascii = claws(series, K1=60, K2=6, 200, verbose=TRUE) #' #' # Same example, from CSV file #' csv_file = "/tmp/epclust_series.csv" #' write.table(series, csv_file, sep=",", row.names=FALSE, col.names=FALSE) -#' medoids_csv = claws(csv_file, K1=60, K2=6, nb_per_chunk=c(200,500)) +#' medoids_csv = claws(csv_file, K1=60, K2=6, 200) #' #' # Same example, from binary file #' bin_file <- "/tmp/epclust_series.bin" @@ -97,7 +97,7 @@ #' endian <- "little" #' binarize(csv_file, bin_file, 500, nbytes, endian) #' getSeries <- function(indices) getDataInFile(indices, bin_file, nbytes, endian) -#' medoids_bin <- claws(getSeries, K1=60, K2=6, nb_per_chunk=c(200,500)) +#' medoids_bin <- claws(getSeries, K1=60, K2=6, 200) #' unlink(csv_file) #' unlink(bin_file) #' @@ -124,7 +124,7 @@ #' df_series <- dbGetQuery(series_db, request) #' as.matrix(df_series[,"value"], nrow=serie_length) #' } -#' medoids_db = claws(getSeries, K1=60, K2=6, nb_per_chunk=c(200,500)) +#' medoids_db = claws(getSeries, K1=60, K2=6, 200)) #' dbDisconnect(series_db) #' #' # All computed medoids should be the same: @@ -134,11 +134,11 @@ #' digest::sha1(medoids_db) #' } #' @export -claws <- function(getSeries, K1, K2, nb_per_chunk, +claws <- function(getSeries, K1, K2, nb_series_per_chunk, nb_items_clust1=7*K1, algo_clust1=function(data,K) cluster::pam(data,K,diss=FALSE), algo_clust2=function(dists,K) stats::kmeans(dists,K,iter.max=50,nstart=3), - wav_filt="d8",contrib_type="absolute", + wav_filt="d8", contrib_type="absolute", WER="end", random=TRUE, ntasks=1, ncores_tasks=1, ncores_clust=4, @@ -155,12 +155,11 @@ claws <- function(getSeries, K1, K2, nb_per_chunk, } K1 <- .toInteger(K1, function(x) x>=2) K2 <- .toInteger(K2, function(x) x>=2) - if (!is.numeric(nb_per_chunk) || length(nb_per_chunk)!=2) - stop("'nb_per_chunk': numeric, size 2") - nb_per_chunk[1] <- .toInteger(nb_per_chunk[1], function(x) x>=1) - # A batch of contributions should have at least as many elements as a batch of series, - # because it always contains much less values - nb_per_chunk[2] <- max(.toInteger(nb_per_chunk[2],function(x) x>=1), nb_per_chunk[1]) + nb_series_per_chunk <- .toInteger(nb_series_per_chunk, function(x) x>=1) + # K1 (number of clusters at step 1) cannot exceed nb_series_per_chunk, because we will need + # to load K1 series in memory for clustering stage 2. + if (K1 > nb_series_per_chunk) + stop("'K1' cannot exceed 'nb_series_per_chunk'") nb_items_clust1 <- .toInteger(nb_items_clust1, function(x) x>K1) random <- .toLogical(random) tryCatch @@ -236,8 +235,8 @@ claws <- function(getSeries, K1, K2, nb_per_chunk, # under Linux. All necessary variables are passed to the workers. cl = parallel::makeCluster(ncores_tasks, outfile="") varlist = c("getSeries","getContribs","K1","K2","algo_clust1","algo_clust2", - "nb_per_chunk","nb_items_clust","ncores_clust","sep","nbytes","endian", - "verbose","parll") + "nb_series_per_chunk","nb_items_clust","ncores_clust","sep", + "nbytes","endian","verbose","parll") if (WER=="mix") varlist = c(varlist, "medoids_file") parallel::clusterExport(cl, varlist, envir = environment())