| Title: | FARM Algorithm Evaluation |
|---|---|
| Description: | Providing data sets and functions used for evaluating the FARM (Forward Alignment Relevance Measure) algorithm. Datasets include energy consumption series from a university research cube in combination with two and four exogenous series consisting 768 and 62840 samples, respectively. To run particular functions from terminal: Rscript $(R -e 'cat(system.file("scripts","FARM.eval.R",package = "FARM.eval"))') --fexecute get.global.rel.meas --parworkers 1 --parobjsize 500. |
| Authors: | Ramón Christen [aut, cre] (ORCID: <https://orcid.org/0000-0002-3963-0785>) |
| Maintainer: | Ramón Christen <[email protected]> |
| License: | GPL-3 |
| Version: | 1.0.0 |
| Built: | 2026-11-05 01:09:25 UTC |
| Source: | https://github.com/cran/FARM.eval |
: Collection of functions that evaluate the alignment capabilities and relevance measure accuracy of the FARM algorithm (provided in R-package: FARM).
load evaluation data sets
loads, prprocesses and slices all data required for experiments. Does nothing, if variable 'ds.eval' already exist.
IMPORTANT: This package only provides the data sources recorded by the authors itself. Thus, to run this function load.data() correctly, you have to save the other data sets from the official sources in .csv files within the folder /extdata beside the existing data files. In fact, you have to add missing data files (.csv and .parquet files) while maintaining the following folder structure: ./inst/ |-extdata/ |-ResC1W.no.f.pwr.cons.csv |-ResC1W.no.f.co2.csv |-ResC1W.no.f.ecar.csv |-ResC1Y.hslu.rc.data.large.clean.csv |-Finance.PETR4.SA_raw_data.csv |-ETTh1.csv |-ETTh2.csv |-ETTm1.csv |-ETTm2.csv |-Weather.csv |-epex-de.parquet
The additional data sets can be downloaded from: ETTx: https://github.com/zhouhaoyi/ETDataset Finance: https://finance.yahoo.com/quote/PETR4.SA/history/?period1=1514764800&period2=1672444800 Weather: https://www.ncei.noaa.gov/data/local-climatological-data/ EPEX: https://zenodo.org/records/4624805
load.data()load.data()
#############################################################
list: ds.eval comprising all data required for the experiments
: date: 2026-09-22
: rch
: the script provides various helpful functions for time series experiments
load data or apply method
loads (RDS) or applies and saves (RDS) data from/to a file. The function ensures that the method is applied if results are not available in provided file.
load.apply.save(file, method, ...)load.apply.save(file, method, ...)
file |
relative path and name of .rds file to load. |
method |
method to apply on data. |
... |
parameters passed to method. positional or keyword arguments allowed. |
result from provided method.
: date: 2023-08-29
: rch
dewarps query time series using algorithms defined in test bench and calculates alignment results with respect to the original query time series
align.eval.dewarp.bench( ts.ref, ts.qry, qry.gt, warp.gt, approaches = NULL, measures = NULL )align.eval.dewarp.bench( ts.ref, ts.qry, qry.gt, warp.gt, approaches = NULL, measures = NULL )
ts.ref |
vector: reference time series. Must be of same length as ts.qry. |
ts.qry |
vector: query time series. Must be of same length as ts.ref. |
qry.gt |
vector: ground truth of query time series. |
warp.gt |
vector: series of warp width for every single data point of ground truth series |
approaches |
list of applied approaches defined in: dewarp.approaches. default: NULL (all methods) |
measures |
list of calculated evaluation measures defined in: align.eval.error.stat. default: NULL (all measures) |
experiment results
returns different statistical alignment performance values for given list of alignment results
align.eval.error.stat(align.res, ts.gt, ts.qry, warp.gt, measures = NULL)align.eval.error.stat(align.res, ts.gt, ts.qry, warp.gt, measures = NULL)
align.res |
list of alignment results |
ts.gt |
ground truth time series referred to for quality measures |
ts.qry |
query time series used for experiment |
warp.gt |
series of warp width for every single data point of ground truth series |
measures |
list of calculated evaluation measures. ['sum.d', 'mae', 'rmae', 'mape', 'corr', 'mean.p', 'slm.f', 'sum.xd', 'gl.rel', 'wp.sim', 'wp.sim.r']. default: NULL (ALL) |
list sum.d: sum of distance of absolute values mae: mean absolute error (sum.d / length(qts)) cor: correlation of query and reference ts mean.p: ... see farm mean.p slm.f: ... see farm slm.f sum.xd: sum of distance of 1st derivation gl.rel: global relevance value (i.e. measure value) wp.sim: sum of warp difference between de-warped result and ground truth
calculates alot distance for two given series
alot(x, v2 = NULL, w = 2, s = 3)alot(x, v2 = NULL, w = 2, s = 3)
x |
time series: reference only if v2 query |
v2 |
time series: query |
w |
window width: default = 2, as used by Ogul when algorithm was published |
s |
sigma: default = 3, center of set {2,3,4} also used by Ogul in alg. publication |
dist: alot distance, dist.m: distance matrix, path: warping path
this variation is speed optimized by calculating the distance in a preceding separate step
alot(x = runif(100), v2 = runif(100)) alot(x = data.frame(v1 = runif(100), v2 = runif(100)))alot(x = runif(100), v2 = runif(100)) alot(x = data.frame(v1 = runif(100), v2 = runif(100)))
AMSS dynamic distance calculation according to the documentation in the official publication
amss(x, v2 = NULL)amss(x, v2 = NULL)
x |
input vector 1 OR data.frame with input vectors 1 and 2 |
v2 |
input vector 2 if v2 missing in x |
dist: AMSS distance, dist.m: distance matrix, path: warping path
amss(x = runif(100), v2 = runif(100)) amss(x = data.frame(v1 = runif(100), v2 = runif(100)))amss(x = runif(100), v2 = runif(100)) amss(x = data.frame(v1 = runif(100), v2 = runif(100)))
AMSS warping path calculation according the documentation in the official publication
amss.wpath(dist.m)amss.wpath(dist.m)
dist.m |
distance matrix between compared feature vectors |
warping path
Runs the method get.global.rel.meas and saves all results in the file "res/eval.res.global.rel.meas.Rdata" if the file does not exist already.
calc.global.rel.meas()calc.global.rel.meas()
list with data frames for each data set providing the different relevance measures for each exogenous variable
applies the bunch of de-warping algorithms (or parts of it) on given query and reference time series. For a reasonable comparison, all distance measures that represent the last sum value of the distance matrix, the value was divided by the length of query time series.
dewarp.approaches(ts.ref, ts.qry, approaches = NULL, edr.e = EDR.e)dewarp.approaches(ts.ref, ts.qry, approaches = NULL, edr.e = EDR.e)
ts.ref |
reference time series |
ts.qry |
query time series |
approaches |
list of applied approaches: ['pure', farm', 'farm.mtr', 'farm.mtr.nfuzz', 'amss', 'dtw', 'ddtw', 'alot', 'edr', 'msm', 'shapedtw']. default: all |
edr.e |
float: the EDR epsilon parameter |
list of de-warping results for all applied approaches
de-warp series with different approaches all results must provide the list elements: - rts.decomp: decomposed reference time series - qts.decomp: decomposed query time series - path: data.frame providing warping path (x, y) - rel.global: global relevance measure - wp.univar: univariate warping path: warping compensation for every single data point
returns de-warp indices for amplitude algorithms (dtw) CAUTION: the returned de-warp size equals inverse of original warp size, ideally.
dewarp.idx.univar(y.warp.idx, x.warp.idx, abs)dewarp.idx.univar(y.warp.idx, x.warp.idx, abs)
y.warp.idx |
[int]: reference indexes (dtw.index2, farm.ref) |
x.warp.idx |
[int]: query indexes (dtw.index1, farm.qry) |
abs |
bool: flag if warping indexes are related to absolute values (TRUE) or derivatives (FALSE) like for FARM, AMSS |
ideally the inverse of the applied warping
dewarp.idx.univar(y.warp.idx = c(1,2,3,3,4,5,5), x.warp.idx = c(1,2,2,2,3,4,5), abs = TRUE)dewarp.idx.univar(y.warp.idx = c(1,2,3,3,4,5,5), x.warp.idx = c(1,2,2,2,3,4,5), abs = TRUE)
alot distance calculation between extracted textures
dist.h(x, y)dist.h(x, y)
x |
texture 1 |
y |
texture 2 |
distance between textures
extracts the best fitting mapping path from a distance matrix by applying the given conditional function
dist.matrix.wpath(dist.m, cond.f = which.min)dist.matrix.wpath(dist.m, cond.f = which.min)
dist.m |
distance matrix |
cond.f |
conditional function for backtracking the mapping path - default: min |
warping path with x and y indexes
dist.matrix.wpath(matrix(runif(9), nrow=3, ncol=3))dist.matrix.wpath(matrix(runif(9), nrow=3, ncol=3))
the function calculates the edr distance of two trajectories. Thereby, it applies the threshold e on the abs(delta x) and abs(delta y) and returns a binary value: 0 if delta < e else 1 For time series, the condition is always true for the delta x. For this reason, the function proves the delta y only.
edr(x, v2 = NULL, e = 1)edr(x, v2 = NULL, e = 1)
x |
time series: reference if v2 not NULL |
v2 |
time series: query |
e |
epsilon: threshold parameter |
dist: edr distance, dist.m: distance matrix, path: warping path
edr(x = runif(100), v2 = runif(100)) edr(x = data.frame(v1 = runif(100), v2 = runif(100)))edr(x = runif(100), v2 = runif(100)) edr(x = data.frame(v1 = runif(100), v2 = runif(100)))
: implementation of the edr algorithm according the publication chen et al. https://doi.org/10.1145/1066157.1066213
edr feature distance
calculation of the edr distance
edr.dist(x, v2 = NULL, e = 1)edr.dist(x, v2 = NULL, e = 1)
x |
data.frame(x, y) comprising comparing vectors. if it contains single vector only, it must provide dx and dy of first vector. |
v2 |
components (dx, dy) of second vector for comparison if x represents single first vector. |
e |
epsilon threshold for vector comparison |
edr distance
: date: 2023-10-19
: rch
: implementation of the amss algorithm according the publication Nakamura et al. https://doi.org/10.1007/s10044-011-0262-6
amss feature extraction
AMSS feature extraction of a vector
feat.ext(x)feat.ext(x)
x |
vector for feature extraction |
vector with features of x
: date: 2023-10-19
: rch
ffalign experiment function
ffalign.exp( df, vtarget = "OT", warp.max = c(3, 5, 8, 16), ds.name = NULL, align.appr = NULL, eval.meas = NULL )ffalign.exp( df, vtarget = "OT", warp.max = c(3, 5, 8, 16), ds.name = NULL, align.appr = NULL, eval.meas = NULL )
df |
data frame with target variable (default: OT) and all exogenous variables. date and time variable should be removed |
vtarget |
name of target variable if other than 'OT' |
warp.max |
list with maximum warping step width. default: c(3,5,8,16) |
ds.name |
name of data set used for saving results. deault: name of passed data.frame |
align.appr |
alignment approaches applied on every single experiment. default: all possible approaches |
eval.meas |
applied evaluation measures. default: sum.d and corr |
list with experiment for all exogenous data
This function defines all executed alignment experiments. It applies the ffalign.exp function on several experimental data sets and stores the results in rds files accordingly
ffalign.exp.calc(eval.meas = NULL, align.appr = NULL)ffalign.exp.calc(eval.meas = NULL, align.appr = NULL)
eval.meas |
vector: applied evaluation measures from set: 'sum.d', 'mae', 'rmae', 'mape', 'corr', 'mean.p', 'slm.f', 'sum.xd', 'gl.rel', 'wp.sim', 'wp.sim.r' |
align.appr |
vector: applied alignment approaches from set: 'pure', 'farm', 'farm.mtr', 'farm.mtr.nfuzz', 'amss', 'dtw', 'ddtw', 'alot', 'edr', 'msm', 'shapedtw' |
list: results of alignment experiment calculations applied on all tested datasets
fills shorter list elements with NA to the max length of all list elements.
fit.list.lengths(x, len = NA)fit.list.lengths(x, len = NA)
x |
list with elements of different length. |
len |
int length to set for each element in list x. |
given list for x where all entries are of the same length.
fit.list.lengths(list(a = c(1,2,3,4,5), b = c(1,2,3,4,5,6,7)))fit.list.lengths(list(a = c(1,2,3,4,5), b = c(1,2,3,4,5,6,7)))
Calculates a set of global relevance measures for each pair of reference and exogenous time series across all evaluation data sets.
get.global.rel.meas(ds.rel.meas = NULL, edr.e = EDR.e)get.global.rel.meas(ds.rel.meas = NULL, edr.e = EDR.e)
ds.rel.meas |
list: data sets with reference and exogenous series used for calculating the relevance measure. |
edr.e |
float: the EDR epsilon parameter |
list with data frames for each data set providing the different relevance measures for each exogenous variable
harmonizes result structure such that all result objects are of the same structure
harm.res(x, dec, path, rel.gl, abs)harm.res(x, dec, path, rel.gl, abs)
x |
list: de-warping results |
dec |
list with decomposed series (ref.ts, qry.ts) |
path |
data.frame: resulting warping path (x, y) |
rel.gl |
number: global relevance measure |
abs |
boolean: absolute measures used in algorithm |
selects all data containing given match-string
match.slice.df(x, match, by = 1, format = c)match.slice.df(x, match, by = 1, format = c)
x |
sourcing data frame |
match |
vector with matching data for selecting recordings |
by |
look-up column - default: 1 |
format |
format for type cast of look-up column - default c (vector) |
sliced data frame
match.slice.df(x = data.frame(x = c(1,2,3,2,5), y = 5:9), 2)match.slice.df(x = data.frame(x = c(1,2,3,2,5), y = 5:9), 2)
returns the msm distance for the given time series
msm(x, v2 = NULL, c = 1)msm(x, v2 = NULL, c = 1)
x |
time series: reference only if query given by v2 |
v2 |
time series: query |
c |
cost parameter used for msm.cost calculation |
dist: msm distance, dist.m: distance matrix, path: warping path
msm(x = runif(100), v2 = runif(100)) msm(x = data.frame(v1 = runif(100), v2 = runif(100)))msm(x = runif(100), v2 = runif(100)) msm(x = data.frame(v1 = runif(100), v2 = runif(100)))
: implementation of the msm algorithm according the publication Stefan et al. https://doi.org/10.1109/TKDE.2012.88
msm feature cost
calculates the msm cost for given series elements
msm.cost(x, xp, y, c)msm.cost(x, xp, y, c)
x |
first element |
xp |
element before first element |
y |
second element |
c |
constant value > should be evaluated experimentally with the set of {0.01, 0.1, 1, 10, 100} |
msm cost
: date: 2023-10-24
: rch
calculates the msm distance between two elements
msm.dist(x, y)msm.dist(x, y)
x |
element 1 |
y |
element 2 |
msm distance
applies warp.type warping on time series for multiple warp length. It returns a list of series that are warped (negative time shift, i.e. warped ts present features ahead in time to the given ts) by 'warp.len'.
multi.warp.series(ts, warp.len, warp.type)multi.warp.series(ts, warp.len, warp.type)
ts |
vector: time series to warp |
warp.len |
vector with given warp length |
warp.type |
['const', 'sweep']: const: constant shift of given ts |
wrp.ts: list of warped time series
wrp.size: list of series with number of warping steps for each point in time
multi.warp.series(ts = 1:150, warp.len = c(5,10,20), warp.type = 'sweep')multi.warp.series(ts = 1:150, warp.len = c(5,10,20), warp.type = 'sweep')
angle (phi) between two nD vectors
n.vect.phi(x, v2 = NULL, cos = FALSE)n.vect.phi(x, v2 = NULL, cos = FALSE)
x |
data.frame of vectors [v1, v2] (then v2 == NULL), else single vector |
v2 |
vector: second vector c(...). Optional if x is single vector i.e. c(x1,y1,z1,...) |
cos |
bool: if cosine(phi) returned, default: FALSE |
phi or cosine(phi) of signed difference between vector arguments
n.vect.phi(data.frame(v1 = c(1,5,2), v2 = c(6,3,5)))n.vect.phi(data.frame(v1 = c(1,5,2), v2 = c(6,3,5)))
removes offset to the minimum. It is applied to positive and negative values.
rm.min(ts)rm.min(ts)
ts |
time series to apply |
offset removed time series with x is element of natural numbers.
rm.min(c(1,2,3,4,5))rm.min(c(1,2,3,4,5))
a robust min-max normalizing function that ignores outliers
robust.minmax( x, l.lim = 0, u.lim = 1, lower = 0.01, upper = 0.99, mean.set = NA )robust.minmax( x, l.lim = 0, u.lim = 1, lower = 0.01, upper = 0.99, mean.set = NA )
x |
vector: input series to apply min-max |
l.lim |
float: lower scale limit |
u.lim |
float: upper scale limit |
lower |
float: lower percentile |
upper |
float: upper percentile |
mean.set |
float: subtracted mean offset |
min-max normalized series
robust.minmax(x = runif(20))robust.minmax(x = runif(20))
normalize data to range [0,1] based on a reduced set excluding outliers. The factor for normalization is applied on full series including outliers
scale_quant_range(x, range = 0.95)scale_quant_range(x, range = 0.95)
x |
vector: data set (time series) to normalize |
range |
default: 0.95: percentage range of considered data for excluding outliers |
normalized data including outliers where given band (excluding outliers) is in the range [0,1].
scale_quant_range(x = runif(20))scale_quant_range(x = runif(20))
used for testing the function dewarp.idx.univar
test.dewarp.idx()test.dewarp.idx()
Implementation of the ALoT algorithm
alot texture extraction
alot texture extraction for passed vector and window size
text_extr(x, w)text_extr(x, w)
x |
vector to extract textures from |
w |
window size for texture extraction |
extracted textures for input vector x
: date: 2023-10-17
: rch
angle (phi) between two 2D vectors
vect.phi(x, v2 = NULL, cos = FALSE)vect.phi(x, v2 = NULL, cos = FALSE)
x |
data.frame of vectors [$x, $y] (then v2 == NULL) or single vector with x-y component c(x,y) |
v2 |
vector with x-y component c(x,y). Optional if x is single vector i.e. c(x,y) |
cos |
bool: if cosine(phi) returned, default: FALSE |
phi or cosine(phi) of signed difference between vector arguments
vect.phi(data.frame(x = c(2,5,3), y = c(1,2,7)))vect.phi(data.frame(x = c(2,5,3), y = c(1,2,7)))
draws vectors in a new plot. it is restricted to 'positive' vectors (i.e. abs(x) >= abs(xo) & abs(y) >= abs(yo))
vectors.draw( x, y, xo = 0, yo = 0, vectors, xlim = NA, ylim = NA, lty = NA, colors = 1, vlines = FALSE, zabline = TRUE, arc.r = NA, symbols = c(), add.notes = NA )vectors.draw( x, y, xo = 0, yo = 0, vectors, xlim = NA, ylim = NA, lty = NA, colors = 1, vlines = FALSE, zabline = TRUE, arc.r = NA, symbols = c(), add.notes = NA )
x |
vector: with x-end coordinates |
y |
vector: with y-end coordinates |
xo |
vector: with x-origin coordinates. Filled up with 0 if not of length x - default: 0 |
yo |
vector: with y-origin coordinates. Filled up with 0 if not of length y - default: 0 |
vectors |
list of vectors [[dx1,dy1], [dx2,dy2], [dx3,dy3]] |
xlim |
x-limits c(start, end) - default: range(xo,x) |
ylim |
y-limits c(start, end) - default: range(yo,y) |
lty |
line type for vectors: default: NA |
colors |
vector: colors for vectors - default: NA |
vlines |
vertical dash lines from vector end to base line: default F |
zabline |
boolean: if set, it draws a horizontal grey30 line on level y=0 - default: T |
arc.r |
vector: radius for angle arc (only applicable if symbols available). default length of 0.33 * min(x, y) is used if 0 - default: NA |
symbols |
vector: of expressions to enclose two vectors. iterating through vector list while starting with v1-v2 - default: c() |
add.notes |
list with additional notes list(c(x, y, str), c(x, y, str)) - default: NA |
creates a plot containing all passed vectors.
vectors.draw(x = c(3,2.1), y = c(5,9.3))vectors.draw(x = c(3,2.1), y = c(5,9.3))
creates a vector of size x.len with warping indices. By the results, data series can be warped using the resulting indices. Indices will be calculated with warping ahead in time following a sweep like sine function. Data points will be deleted for deletions and interpolated for insertions. In case of constant warping (i.e. phase shift) the series length is reduced by 'max.warp'. The sweep increases frequency from omega=1 to omega=3. The sweep keeps a safe tail of n=warp.max unchanged to prevent NA for high frequencies.
warp.idx(x.len, warp.max = 10, warp.fnc = "sweep", n.period = 3)warp.idx(x.len, warp.max = 10, warp.fnc = "sweep", n.period = 3)
x.len |
length of warping: i.e. the size of the series to be warped |
warp.max |
int: maximum warping width |
warp.fnc |
keyword: warping function {'sweep', 'const'} |
n.period |
int: number of full periods for sweep function - default: 3 |
w.stp: the warping steps for every single element of the warping index
w.idx: the index to access the warped element of the original series
warp.idx(x.len = 150)warp.idx(x.len = 150)