Title: | Forecastable Component Analysis |
---|---|
Description: | Implementation of Forecastable Component Analysis ('ForeCA'), including main algorithms and auxiliary function (summary, plotting, etc.) to apply 'ForeCA' to multivariate time series data. 'ForeCA' is a novel dimension reduction (DR) technique for temporally dependent signals. Contrary to other popular DR methods, such as 'PCA' or 'ICA', 'ForeCA' takes time dependency explicitly into account and searches for the most ''forecastable'' signal. The measure of forecastability is based on the Shannon entropy of the spectral density of the transformed signal. |
Authors: | Georg M. Goerg [aut, cre] |
Maintainer: | Georg M. Goerg <[email protected]> |
License: | GPL-2 |
Version: | 0.2.7 |
Built: | 2024-11-13 03:28:32 UTC |
Source: | https://github.com/gmgeorg/foreca |
Forecastable Component Analysis (ForeCA) is a novel dimension reduction
technique for multivariate time series .
ForeCA finds a linar combination
that is easy to forecast. The measure of
forecastability
(
Omega
) is based on the entropy
of the spectral density of
: higher entropy means
less forecastable, lower entropy is more forecastable.
The main function foreca
runs ForeCA on a
multivariate time series .
Consult NEWS.md
for a history of release notes.
Author and maintainer: Georg M. Goerg <[email protected]>
Goerg, G. M. (2013). “Forecastable Component Analysis”. Journal of Machine Learning Research (JMLR) W&CP 28 (2): 64-72, 2013. Available at http://jmlr.org/proceedings/papers/v28/goerg13.html.
XX <- ts(diff(log(EuStockMarkets))) Omega(XX) plot(log10(lynx)) Omega(log10(lynx)) ## Not run: ff <- foreca(XX, n.comp = 4) ff plot(ff) summary(ff) ## End(Not run)
XX <- ts(diff(log(EuStockMarkets))) Omega(XX) plot(log10(lynx)) Omega(log10(lynx)) ## Not run: ff <- foreca(XX, n.comp = 4) ff plot(ff) summary(ff) ## End(Not run)
Common arguments used in several functions in this package.
series |
a |
U |
a |
mvspectrum.output |
an object of class |
f.U |
multivariate spectrum of class |
algorithm.control |
list; control settings for any iterative ForeCA
algorithm. See |
entropy.control |
list; control settings for entropy estimation.
See |
spectrum.control |
list; control settings for spectrum estimation.
See |
entropy.method |
string; method to estimate the entropy from discrete
probabilities |
spectrum.method |
string; method for spectrum estimation; see |
threshold |
numeric; values of spectral density below |
smoothing |
logical; if |
base |
logarithm base; entropy is measured in “nats” for
|
Completes algorithm, entropy, and spectrum control lists.
complete_algorithm_control( algorithm.control = list(max.iter = 50, num.starts = 10, tol = 0.001, type = "EM") ) complete_entropy_control( entropy.control = list(base = NULL, method = "MLE", prior.probs = NULL, prior.weight = 0.001, threshold = 0), num.outcomes ) complete_spectrum_control( spectrum.control = list(kernel = NULL, method = c("mvspec", "pspectrum", "ar", "pgram"), smoothing = FALSE) )
complete_algorithm_control( algorithm.control = list(max.iter = 50, num.starts = 10, tol = 0.001, type = "EM") ) complete_entropy_control( entropy.control = list(base = NULL, method = "MLE", prior.probs = NULL, prior.weight = 0.001, threshold = 0), num.outcomes ) complete_spectrum_control( spectrum.control = list(kernel = NULL, method = c("mvspec", "pspectrum", "ar", "pgram"), smoothing = FALSE) )
algorithm.control |
list; control parameters for any iterative ForeCA algorithm. |
entropy.control |
list; control settings for entropy estimation. |
num.outcomes |
positive integer; number of outcomes for the discrete probability distribution. Must be specified (no default value). |
spectrum.control |
list; control settings for spectrum estimation. |
A list with fully specified algorithm, entropy, or spectrum controls.
Default values are only added if the input {spectrum,entropy,algorithm}.control
list does not already set this value.
complete_algorithm_control
returns a list containing:
max.iter |
maximum number of iterations; default: |
num.starts |
number of random starts to avoid local optima; default: |
tol |
tolerance for when convergence is reached in any iterative
ForeCA algorithm; default: |
type |
string; type of algorithm. Default: |
complete_entropy_control
returns a list with:
base |
logarithm base for the entropy. |
method |
string; method to estimate entropy; default: |
prior.probs |
prior distribution; default: uniform
|
prior.weight |
weight of the prior distribution; default: |
threshold |
non-negative float; set probabilities below threshold to
zero; default: |
complete_spectrum_control
returns a list containing:
kernel |
R function; function to weigh each Fourier frequency |
method |
string; method to estimate the spectrum; default:
|
smoothing |
logical; default: |
Available methods for spectrum estimation are (alphabetical order)
"ar" |
autoregressive spectrum fit via |
"mvspec" |
smoothed estimate using |
"pgram" |
raw periodogram using |
"pspectrum" |
advanced non-parametric estimation of a tapered power
spectrum using |
Setting smoothing = TRUE
will smooth the estimated spectrum
(again); this option is only available for univariate time series/spectra.
mvspectrum
, discrete_entropy
,
continuous_entropy
Computes the Shannon entropy for a continuous
probability density function (pdf)
using numerical integration.
continuous_entropy(pdf, lower, upper, base = 2)
continuous_entropy(pdf, lower, upper, base = 2)
pdf |
R function for the pdf |
lower , upper
|
lower and upper integration limit. |
base |
logarithm base; entropy is measured in “nats” for
|
The Shannon entropy of a continuous random variable (RV) is defined as
Contrary to discrete RVs, continuous RVs can have negative entropy (see Examples).
scalar; entropy value (real).
Since continuous_entropy
uses numerical integration (integrate()
) convergence
is not garantueed (even if integral in definition of exists).
Issues a warning if
integrate()
does not converge.
# entropy of U(a, b) = log(b - a). Thus not necessarily positive anymore, e.g. continuous_entropy(function(x) dunif(x, 0, 0.5), 0, 0.5) # log2(0.5) # Same, but for U(-1, 1) my_density <- function(x){ dunif(x, -1, 1) } continuous_entropy(my_density, -1, 1) # = log(upper - lower) # a 'triangle' distribution continuous_entropy(function(x) x, 0, sqrt(2))
# entropy of U(a, b) = log(b - a). Thus not necessarily positive anymore, e.g. continuous_entropy(function(x) dunif(x, 0, 0.5), 0, 0.5) # log2(0.5) # Same, but for U(-1, 1) my_density <- function(x){ dunif(x, -1, 1) } continuous_entropy(my_density, -1, 1) # = log(upper - lower) # a 'triangle' distribution continuous_entropy(function(x) x, 0, sqrt(2))
Computes the Shannon entropy
of a discrete RV
taking
values in
with probability
mass function (pmf)
with
for all
and
.
discrete_entropy( probs, base = 2, method = c("MLE"), threshold = 0, prior.probs = NULL, prior.weight = 0 )
discrete_entropy( probs, base = 2, method = c("MLE"), threshold = 0, prior.probs = NULL, prior.weight = 0 )
probs |
numeric; probabilities (empirical frequencies). Must be non-negative and add up to |
base |
logarithm base; entropy is measured in “nats” for
|
method |
string; method to estimate entropy; see Details below. |
threshold |
numeric; frequencies below |
prior.probs |
optional; only used if |
prior.weight |
numeric; how much weight does the prior distribution get in a mixture
model between data and prior distribution? Must be between |
discrete_entropy
uses a plug-in estimator (method = "MLE"
):
If prior.weight > 0
, then it mixes the observed proportions
with a prior distribution
where is the
prior.weight
parameter. By default
the prior is a uniform distribution, i.e., for all i.
Note that this plugin estimator is biased. See References for an overview of alternative methods.
numeric; non-negative real value.
Archer E., Park I. M., Pillow J.W. (2014). “Bayesian Entropy Estimation for Countable Discrete Distributions”. Journal of Machine Learning Research (JMLR) 15, 2833-2868. Available at http://jmlr.org/papers/v15/archer14a.html.
probs.tmp <- rexp(5) probs.tmp <- sort(probs.tmp / sum(probs.tmp)) unif.distr <- rep(1/length(probs.tmp), length(probs.tmp)) matplot(cbind(probs.tmp, unif.distr), pch = 19, ylab = "P(X = k)", xlab = "k") matlines(cbind(probs.tmp, unif.distr)) legend("topleft", c("non-uniform", "uniform"), pch = 19, lty = 1:2, col = 1:2, box.lty = 0) discrete_entropy(probs.tmp) # uniform has largest entropy among all bounded discrete pmfs # (here = log(5)) discrete_entropy(unif.distr) # no uncertainty if one element occurs with probability 1 discrete_entropy(c(1, 0, 0))
probs.tmp <- rexp(5) probs.tmp <- sort(probs.tmp / sum(probs.tmp)) unif.distr <- rep(1/length(probs.tmp), length(probs.tmp)) matplot(cbind(probs.tmp, unif.distr), pch = 19, ylab = "P(X = k)", xlab = "k") matlines(cbind(probs.tmp, unif.distr)) legend("topleft", c("non-uniform", "uniform"), pch = 19, lty = 1:2, col = 1:2, box.lty = 0) discrete_entropy(probs.tmp) # uniform has largest entropy among all bounded discrete pmfs # (here = log(5)) discrete_entropy(unif.distr) # no uncertainty if one element occurs with probability 1 discrete_entropy(c(1, 0, 0))
foreca
performs Forecastable Component Analysis (ForeCA) on
– a
-dimensional time series with
observations. Users should only call
foreca
, rather than foreca.one_weightvector
or
foreca.multiple_weightvectors
.
foreca.one_weightvector
is a wrapper around several algorithms that
solve the ForeCA optimization problem for a single weightvector
and whitened time series
.
foreca.multiple_weightvectors
applies foreca.one_weightvector
iteratively to in order to obtain multiple weightvectors
that yield most forecastable, uncorrelated signals.
foreca(series, n.comp = 2, algorithm.control = list(type = "EM"), ...) foreca.one_weightvector( U, f.U = NULL, spectrum.control = list(), entropy.control = list(), algorithm.control = list(), keep.all.optima = FALSE, dewhitening = NULL, ... ) foreca.multiple_weightvectors( U, spectrum.control = list(), entropy.control = list(), algorithm.control = list(), n.comp = 2, plot = FALSE, dewhitening = NULL, ... )
foreca(series, n.comp = 2, algorithm.control = list(type = "EM"), ...) foreca.one_weightvector( U, f.U = NULL, spectrum.control = list(), entropy.control = list(), algorithm.control = list(), keep.all.optima = FALSE, dewhitening = NULL, ... ) foreca.multiple_weightvectors( U, spectrum.control = list(), entropy.control = list(), algorithm.control = list(), n.comp = 2, plot = FALSE, dewhitening = NULL, ... )
series |
a |
n.comp |
positive integer; number of components to be extracted.
Default: |
algorithm.control |
list; control settings for any iterative ForeCA
algorithm. See |
... |
additional arguments passed to available ForeCA algorithms. |
U |
a |
f.U |
multivariate spectrum of class |
spectrum.control |
list; control settings for spectrum estimation.
See |
entropy.control |
list; control settings for entropy estimation.
See |
keep.all.optima |
logical; if |
dewhitening |
optional; if provided (returned by |
plot |
logical; if |
An object of class foreca
, which is similar to the output from princomp
,
with the following components (amongst others):
center
: sample mean of each
series
,
whitening
: whitening matrix of size
from
whiten
: ;
note that
is centered prior to the whitening transformation,
weightvectors
: orthonormal matrix of size ,
which converts whitened data to
n.comp
forecastable components (ForeCs)
,
loadings
: combination of whitening weightvectors to obtain the final
loadings for the original data:
; again, it centers
first,
loadings.normalized
: normalized loadings (unit norm). Note
though that if you use these normalized loadings the resulting
signals do not have variance 1 anymore.
scores
: n.comp
forecastable components .
They have mean 0, variance 1, and are uncorrelated.
Omega
: forecastability score of each ForeC of .
ForeCs are ordered from most to least forecastable (according to
Omega
).
Estimating Omega directly from the ForeCs can be different
to the reported
$Omega
estimates from foreca
. Here is why:
In theory of a linear combination
can be analytically computed from
the multivariate spectrum
by the
quadratic form
for all
(see
spectrum_of_linear_combination
).
In practice, however, this identity does not hold always exactly since
(often data-driven) control setting for spectrum estimation are not identical
for the high-dimensional, noisy
and the combined univariate time series
(which is usually more smooth, less variable). Thus estimating
directly from
can give slightly different
estimates to computing it as
. Consequently also
Omega
estimates
can be different.
In general, these differences are small and have no relevant implications
for estimating ForeCs. However, in rare occasions the obtained ForeCs can have
smaller Omega
than the maximum Omega
across all original series.
In such a case users should not re-estimate from the resulting
ForeCs
, but access them via
$Omega
provided
by 'foreca'
output (the univariate estimates are stored in $Omega.univ
).
Goerg, G. M. (2013). “Forecastable Component Analysis”. Journal of Machine Learning Research (JMLR) W&CP 28 (2): 64-72, 2013. Available at http://jmlr.org/proceedings/papers/v28/goerg13.html.
XX <- diff(log(EuStockMarkets)) * 100 plot(ts(XX)) ## Not run: ff <- foreca(XX[,1:4], n.comp = 4, plot = TRUE, spectrum.control=list(method="pspectrum")) ff summary(ff) plot(ff) ## End(Not run) ## Not run: PW <- whiten(XX) one.weight.em <- foreca.one_weightvector(U = PW$U, dewhitening = PW$dewhitening, algorithm.control = list(num.starts = 2, type = "EM"), spectrum.control = list(method = "mvspec")) plot(one.weight.em) ## End(Not run) ## Not run: PW <- whiten(XX) ff <- foreca.multiple_weightvectors(PW$U, n.comp = 2, dewhitening = PW$dewhitening) ff plot(ff$scores) ## End(Not run)
XX <- diff(log(EuStockMarkets)) * 100 plot(ts(XX)) ## Not run: ff <- foreca(XX[,1:4], n.comp = 4, plot = TRUE, spectrum.control=list(method="pspectrum")) ff summary(ff) plot(ff) ## End(Not run) ## Not run: PW <- whiten(XX) one.weight.em <- foreca.one_weightvector(U = PW$U, dewhitening = PW$dewhitening, algorithm.control = list(num.starts = 2, type = "EM"), spectrum.control = list(method = "mvspec")) plot(one.weight.em) ## End(Not run) ## Not run: PW <- whiten(XX) ff <- foreca.multiple_weightvectors(PW$U, n.comp = 2, dewhitening = PW$dewhitening) ff plot(ff$scores) ## End(Not run)
A collection of S3 methods for estimated ForeCA results
(class "foreca"
).
summary.foreca
computes summary statistics.
print.foreca
prints a human-readable summary in the console.
biplot.foreca
shows a biplot of the ForeCA loadings
(wrapper around biplot.princomp
).
plot.foreca
shows biplots, screeplots, and white noise tests.
## S3 method for class 'foreca' summary(object, lag = 10, alpha = 0.05, ...) ## S3 method for class 'foreca' print(x, ...) ## S3 method for class 'foreca' biplot(x, ...) ## S3 method for class 'foreca' plot(x, lag = 10, alpha = 0.05, ...)
## S3 method for class 'foreca' summary(object, lag = 10, alpha = 0.05, ...) ## S3 method for class 'foreca' print(x, ...) ## S3 method for class 'foreca' biplot(x, ...) ## S3 method for class 'foreca' plot(x, lag = 10, alpha = 0.05, ...)
lag |
integer; how many lags to test in |
alpha |
significance level for testing white noise in
|
... |
additional arguments passed to
|
x , object
|
an object of class |
# see examples in 'foreca'
# see examples in 'foreca'
foreca.EM.one_weightvector
relies on several auxiliary functions:
foreca.EM.E_step
computes the spectral density of
given the weightvector
and the normalized spectrum estimate
.
A wrapper around
spectrum_of_linear_combination
.
foreca.EM.M_step
computes the minimizing eigenvector
() of the weighted
covariance matrix, where the weights equal the negative logarithm of the
spectral density at the current
.
foreca.EM.E_and_M_step
is a wrapper around foreca.EM.E_step
followed by foreca.EM.M_step
.
foreca.EM.h
evaluates (an upper bound of) the entropy of the spectral density as a function
of (or
). This is the objective funcion that should be
minimize
d.
foreca.EM.E_step(f.U, weightvector) foreca.EM.M_step(f.U, f.current, minimize = TRUE, entropy.control = list()) foreca.EM.E_and_M_step( weightvector, f.U, minimize = TRUE, entropy.control = list() ) foreca.EM.h( weightvector.new, f.U, weightvector.current = weightvector.new, f.current = NULL, entropy.control = list(), return.negative = FALSE )
foreca.EM.E_step(f.U, weightvector) foreca.EM.M_step(f.U, f.current, minimize = TRUE, entropy.control = list()) foreca.EM.E_and_M_step( weightvector, f.U, minimize = TRUE, entropy.control = list() ) foreca.EM.h( weightvector.new, f.U, weightvector.current = weightvector.new, f.current = NULL, entropy.control = list(), return.negative = FALSE )
f.U |
multivariate spectrum of class |
weightvector |
numeric; weights |
f.current |
numeric; spectral density estimate of
|
minimize |
logical; if |
entropy.control |
list; control settings for entropy estimation.
See |
weightvector.new |
weightvector |
weightvector.current |
weightvector |
return.negative |
logical; if |
foreca.EM.E_step
returns the normalized univariate spectral
density (normalized such that its sum
equals ).
foreca.EM.M_step
returns a list with three elements:
matrix
: weighted covariance matrix, where the weights are
the negative log of the spectral density. If density is estimated
by discrete probabilities,
then this matrix
is positive semi-definite, since
for
.
See
weightvector2entropy_wcov
.
vector
: minimizing (or maximizing if
minimize = FALSE
) eigenvector of matrix
,
value
: corresponding eigenvalue.
Contrary to foreca.EM.M_step
, foreca.EM.E_and_M_step
only returns the optimal
weightvector as a numeric.
foreca.EM.h
returns non-negative real value (see References for details):
entropy, if weightvector.new = weightvector.current
,
an upper bound of that entropy for weightvector.new
,
otherwise.
## Not run: XX <- diff(log(EuStockMarkets)) * 100 UU <- whiten(XX)$U ff <- mvspectrum(UU, 'mvspec', normalize = TRUE) ww0 <- initialize_weightvector(num.series = ncol(XX), method = 'rnorm') f.ww0 <- foreca.EM.E_step(ff, ww0) plot(f.ww0, type = "l") ## End(Not run) ## Not run: one.step <- foreca.EM.M_step(ff, f.ww0, entropy.control = list(prior.weight = 0.1)) image(one.step$matrix) requireNamespace(LICORS) # if you have the 'LICORS' package use LICORS::image2(one.step$matrix) ww1 <- one.step$vector f.ww1 <- foreca.EM.E_step(ff, ww1) layout(matrix(1:2, ncol = 2)) matplot(seq(0, pi, length = length(f.ww0)), cbind(f.ww0, f.ww1), type = "l", lwd =2, xlab = "omega_j", ylab = "f(omega_j)") plot(f.ww0, f.ww1, pch = ".", cex = 3, xlab = "iteration 0", ylab = "iteration 1", main = "Spectral density") abline(0, 1, col = 'blue', lty = 2, lwd = 2) Omega(mvspectrum.output = f.ww0) # start Omega(mvspectrum.output = f.ww1) # improved after one iteration ## End(Not run) ## Not run: ww0 <- initialize_weightvector(NULL, ff, method = "rnorm") ww1 <- foreca.EM.E_and_M_step(ww0, ff) ww0 ww1 barplot(rbind(ww0, ww1), beside = TRUE) abline(h = 0, col = "blue", lty = 2) ## End(Not run) ## Not run: foreca.EM.h(ww0, ff) # iteration 0 foreca.EM.h(ww1, ff, ww0) # min eigenvalue inequality foreca.EM.h(ww1, ff) # KL divergence inequality one.step$value # by definition of Omega, they should equal 1 (modulo rounding errors) Omega(mvspectrum.output = f.ww0) / 100 + foreca.EM.h(ww0, ff) Omega(mvspectrum.output = f.ww1) / 100 + foreca.EM.h(ww1, ff) ## End(Not run)
## Not run: XX <- diff(log(EuStockMarkets)) * 100 UU <- whiten(XX)$U ff <- mvspectrum(UU, 'mvspec', normalize = TRUE) ww0 <- initialize_weightvector(num.series = ncol(XX), method = 'rnorm') f.ww0 <- foreca.EM.E_step(ff, ww0) plot(f.ww0, type = "l") ## End(Not run) ## Not run: one.step <- foreca.EM.M_step(ff, f.ww0, entropy.control = list(prior.weight = 0.1)) image(one.step$matrix) requireNamespace(LICORS) # if you have the 'LICORS' package use LICORS::image2(one.step$matrix) ww1 <- one.step$vector f.ww1 <- foreca.EM.E_step(ff, ww1) layout(matrix(1:2, ncol = 2)) matplot(seq(0, pi, length = length(f.ww0)), cbind(f.ww0, f.ww1), type = "l", lwd =2, xlab = "omega_j", ylab = "f(omega_j)") plot(f.ww0, f.ww1, pch = ".", cex = 3, xlab = "iteration 0", ylab = "iteration 1", main = "Spectral density") abline(0, 1, col = 'blue', lty = 2, lwd = 2) Omega(mvspectrum.output = f.ww0) # start Omega(mvspectrum.output = f.ww1) # improved after one iteration ## End(Not run) ## Not run: ww0 <- initialize_weightvector(NULL, ff, method = "rnorm") ww1 <- foreca.EM.E_and_M_step(ww0, ff) ww0 ww1 barplot(rbind(ww0, ww1), beside = TRUE) abline(h = 0, col = "blue", lty = 2) ## End(Not run) ## Not run: foreca.EM.h(ww0, ff) # iteration 0 foreca.EM.h(ww1, ff, ww0) # min eigenvalue inequality foreca.EM.h(ww1, ff) # KL divergence inequality one.step$value # by definition of Omega, they should equal 1 (modulo rounding errors) Omega(mvspectrum.output = f.ww0) / 100 + foreca.EM.h(ww0, ff) Omega(mvspectrum.output = f.ww1) / 100 + foreca.EM.h(ww1, ff) ## End(Not run)
foreca.EM.one_weightvector
finds the optimal weightvector
that gives the most forecastable signal
using an EM-like algorithm (see References).
foreca.EM.one_weightvector( U, f.U = NULL, spectrum.control = list(), entropy.control = list(), algorithm.control = list(), init.weightvector = initialize_weightvector(num.series = ncol(U), method = "rnorm"), ... )
foreca.EM.one_weightvector( U, f.U = NULL, spectrum.control = list(), entropy.control = list(), algorithm.control = list(), init.weightvector = initialize_weightvector(num.series = ncol(U), method = "rnorm"), ... )
U |
a |
f.U |
multivariate spectrum of class |
spectrum.control |
list; control settings for spectrum estimation.
See |
entropy.control |
list; control settings for entropy estimation.
See |
algorithm.control |
list; control settings for any iterative ForeCA
algorithm. See |
init.weightvector |
numeric; starting point |
... |
other arguments passed to |
A list with useful quantities like the optimal weighvector, the corresponding signal, and its forecastability.
foreca.one_weightvector
, foreca.EM-aux
## Not run: XX <- diff(log(EuStockMarkets)[100:200,]) * 100 one.weight <- foreca.EM.one_weightvector(whiten(XX)$U, spectrum.control = list(method = "mvspec")) ## End(Not run)
## Not run: XX <- diff(log(EuStockMarkets)[100:200,]) * 100 one.weight <- foreca.EM.one_weightvector(whiten(XX)$U, spectrum.control = list(method = "mvspec")) ## End(Not run)
S3 methods for the one weightvector optimization in ForeCA
(class "foreca.one_weightvector"
).
summary.foreca.one_weightvector
computes summary statistics.
plot.foreca.one_weightvector
shows the results of an (iterative)
algorithm that obtained the i-th optimal a weightvector
. It
shows trace plots of the objective function and the weightvector, and a time series
plot of the transformed signal
along with its spectral density estimate
.
## S3 method for class 'foreca.one_weightvector' summary(object, lag = 10, alpha = 0.05, ...) ## S3 method for class 'foreca.one_weightvector' plot(x, main = "", cex.lab = 1.1, ...)
## S3 method for class 'foreca.one_weightvector' summary(object, lag = 10, alpha = 0.05, ...) ## S3 method for class 'foreca.one_weightvector' plot(x, main = "", cex.lab = 1.1, ...)
lag |
integer; how many lags to test in |
alpha |
significance level for testing white noise in
|
... |
|
x , object
|
an object of class |
main |
an overall title for the plot: see |
cex.lab |
size of the axes labels. |
# see examples in 'foreca.one_weightvector'
# see examples in 'foreca.one_weightvector'
initialize_weightvector
returns a unit norm (in )
vector
that can be used as the starting
point for any iterative ForeCA algorithm, e.g.,
foreca.EM.one_weightvector
. Several
quickly computable heuristics are available via the method
argument.
initialize_weightvector( U = NULL, f.U = NULL, num.series = ncol(U), method = c("rnorm", "max", "SFA", "PCA", "rcauchy", "runif", "SFA.slow", "SFA.fast", "PCA.large", "PCA.small"), seed = sample(1e+06, 1), ... )
initialize_weightvector( U = NULL, f.U = NULL, num.series = ncol(U), method = c("rnorm", "max", "SFA", "PCA", "rcauchy", "runif", "SFA.slow", "SFA.fast", "PCA.large", "PCA.small"), seed = sample(1e+06, 1), ... )
U |
a |
f.U |
multivariate spectrum of class |
num.series |
positive integer; number of time series |
method |
string; which heuristics should be used to generate a good starting |
seed |
non-negative integer; seed for random initialization which will be returned for reproducibility. By default it sets a random seed. |
... |
additional arguments |
The method
argument specifies the heuristics that is used to get a good
starting vector :
"max"
vector with all s, but a
at the position
of the maximum forecastable series in
U
.
"rcauchy"
random start using rcauchy(k)
.
"rnorm"
random start using rnorm(k, 0, 1)
.
"runif"
random start using runif(k, -1, 1)
.
"PCA.large"
first eigenvector of PCA (largest variance signal).
"PCA.small"
last eigenvector of PCA (smallest variance signal).
"PCA"
checks both small and large, and chooses the one with higher
forecastability as computed by Omega
..
"SFA.fast"
last eigenvector of SFA (fastest signal).
"SFA.slow"
first eigenvector of SFA (slowest signal).
"SFA"
checks both slow and fast, and chooses the one with higher
forecastability as computed by Omega
.
Each vector has length K and is automatically normalized to have unit norm
in .
For the 'SFA*'
methods see sfa
.
Note that maximizing (or minimizing) the lag auto-correlation does
not necessarily yield the most forecastable signal, but it's a good start.
numeric; a vector of length with unit norm in
.
XX <- diff(log(EuStockMarkets)) ## Not run: initialize_weightvector(U = XX, method = "SFA") ## End(Not run) initialize_weightvector(num.series = ncol(XX), method = "rnorm")
XX <- diff(log(EuStockMarkets)) ## Not run: initialize_weightvector(U = XX, method = "SFA") ## End(Not run) initialize_weightvector(num.series = ncol(XX), method = "rnorm")
The spectrum of a multivariate time series is a matrix-valued function of the
frequency , which is symmetric/Hermitian around
.
mvspectrum
estimates it and returns a 3D array of dimension
. Since the spectrum is symmetric/Hermitian around
it is sufficient to store only positive frequencies.
In the implementation in this package we thus usually
consider only positive frequencies (omitting
);
num.freqs
refers
to the number of positive frequencies only.
normalize_mvspectrum
normalizes the spectrum such that
it adds up to over all positive frequencies (by symmetry it will
add up to 1 over the whole range – thus the name normalize).
For a -dimensional time series it adds
up to a Hermitian
matrix with 0.5 in the diagonal and
imaginary elements (real parts equal to
) in the off-diagonal.
Since it is Hermitian the mvspectrum will add up to the identity matrix
over the whole range of frequencies, since the off-diagonal elements
are purely imaginary (real part equals 0) and thus add up to 0.
check_mvspectrum_normalized
checks if the spectrum is normalized
(see normalize_mvspectrum
for the requirements).
mvpgram
computes the multivariate periodogram estimate using
bare-bone multivariate fft (mvfft
). Use
mvspectrum(..., method = 'pgram')
instead of mvpgram
directly.
This function is merely included to have one method that does not require the astsa nor the sapa R packages. However, it is strongly encouraged to install either one of them to get (much) better estimates. See Details.
get_spectrum_from_mvspectrum
extracts the spectrum of one time series from an
"mvspectrum"
object by taking the i-th diagonal entry for each frequency.
spectrum_of_linear_combination
computes the spectrum of the linear
combination of
time series
. This can be efficiently computed by the
quadratic form
for each . This holds for any
(even
– not only for
.
For
(the i-th basis vector)
this is equivalent to
get_spectrum_from_mvspectrum(..., which = i)
.
mvspectrum( series, method = c("mvspec", "pgram", "pspectrum", "ar"), normalize = FALSE, smoothing = FALSE, ... ) normalize_mvspectrum(mvspectrum.output) check_mvspectrum_normalized(f.U, check.attribute.only = TRUE) mvpgram(series) get_spectrum_from_mvspectrum( mvspectrum.output, which = seq_len(dim(mvspectrum.output)[2]) ) spectrum_of_linear_combination(mvspectrum.output, beta)
mvspectrum( series, method = c("mvspec", "pgram", "pspectrum", "ar"), normalize = FALSE, smoothing = FALSE, ... ) normalize_mvspectrum(mvspectrum.output) check_mvspectrum_normalized(f.U, check.attribute.only = TRUE) mvpgram(series) get_spectrum_from_mvspectrum( mvspectrum.output, which = seq_len(dim(mvspectrum.output)[2]) ) spectrum_of_linear_combination(mvspectrum.output, beta)
series |
a |
method |
string; method for spectrum estimation: use |
normalize |
logical; if |
smoothing |
logical; if |
... |
additional arguments passed to |
mvspectrum.output |
an object of class |
f.U |
multivariate spectrum of class |
check.attribute.only |
logical; if |
which |
integer(s); the spectrum of which series whould be extracted. By default, it returns all univariate spectra as a matrix (frequencies in rows). |
beta |
numeric; vector |
For an orthonormal time series the raw periodogram adds up
to
over all (negative and positive) frequencies. Since we only consider
positive frequencies, the normalized multivariate spectrum should add up to
plus a Hermitian imaginary matrix (which will add up to zero
when combined with its symmetric counterpart.)
As we often use non-parametric smoothing for less variance, the spectrum estimates
do not satisfy this identity exactly.
normalize_mvspectrum
thus adjust the
estimates so they satisfy it again exactly.
mvpgram
has no options for improving spectrum estimation whatsoever.
It thus yields very noisy (in fact, inconsistent) estimates of the
multivariate spectrum .
If you want to obtain better estimates then please use other
method
s in
mvspectrum
(this is highly recommended to obtain more
reasonable/stable estimates).
mvspectrum
returns a 3D array of dimension , where
num.freqs is the number of frequencies
K is the number of series (columns in series
).
It also has an "normalized"
attribute, which is
FALSE
if normalize = FALSE
; otherwise TRUE
.
See normalize_mvspectrum
for details.
normalize_mvspectrum
returns a normalized spectrum over
positive frequencies, which:
adds up to ,
adds up to Hermitian matrix
with 0.5 in the diagonal and purely imaginary elements in the off-diagonal.
check_mvspectrum_normalized
throws an error if spectrum is not
normalized correctly.
get_spectrum_from_mvspectrum
returns either a matrix of all univariate spectra,
or one single column (if which
is specified.)
spectrum_of_linear_combination
returns a vector with length equal to
the number of rows of mvspectrum.output
.
See References in spectrum
, pspectrum
,
mvspec
.
set.seed(1) XX <- cbind(rnorm(100), arima.sim(n = 100, list(ar = 0.9))) ss3d <- mvspectrum(XX) dim(ss3d) ss3d[2,,] # at omega_1; in general complex-valued, but Hermitian identical(ss3d[2,,], Conj(t(ss3d[2,,]))) # is Hermitian ## Not run: ss <- mvspectrum(XX[, 1], method="pspectrum", smoothing = TRUE) mvspectrum(XX, normalize = TRUE) ## End(Not run) ss <- mvspectrum(whiten(XX)$U, normalize = TRUE) xx <- scale(rnorm(100), center = TRUE, scale = FALSE) var(xx) sum(mvspectrum(xx, normalize = FALSE, method = "pgram")) * 2 sum(mvspectrum(xx, normalize = FALSE, method = "mvspec")) * 2 ## Not run: sum(mvspectrum(xx, normalize = FALSE, method = "pspectrum")) * 2 ## End(Not run) ## Not run: xx <- scale(rnorm(100), center = TRUE, scale = FALSE) ss <- mvspectrum(xx) ss.n <- normalize_mvspectrum(ss) sum(ss.n) # multivariate UU <- whiten(matrix(rnorm(40), ncol = 2))$U S.U <- mvspectrum(UU, method = "mvspec") mvspectrum2wcov(normalize_mvspectrum(S.U)) ## End(Not run) XX <- matrix(rnorm(1000), ncol = 2) SS <- mvspectrum(XX, "mvspec") ss1 <- mvspectrum(XX[, 1], "mvspec") SS.1 <- get_spectrum_from_mvspectrum(SS, 1) plot.default(ss1, SS.1) abline(0, 1, lty = 2, col = "blue") XX <- matrix(arima.sim(n = 1000, list(ar = 0.9)), ncol = 4) beta.tmp <- rbind(1, -1, 2, 0) yy <- XX %*% beta.tmp SS <- mvspectrum(XX, "mvspec") ss.yy.comb <- spectrum_of_linear_combination(SS, beta.tmp) ss.yy <- mvspectrum(yy, "mvspec") plot(ss.yy, log = TRUE) # using plot.mvspectrum() lines(ss.yy.comb, col = "red", lty = 1, lwd = 2)
set.seed(1) XX <- cbind(rnorm(100), arima.sim(n = 100, list(ar = 0.9))) ss3d <- mvspectrum(XX) dim(ss3d) ss3d[2,,] # at omega_1; in general complex-valued, but Hermitian identical(ss3d[2,,], Conj(t(ss3d[2,,]))) # is Hermitian ## Not run: ss <- mvspectrum(XX[, 1], method="pspectrum", smoothing = TRUE) mvspectrum(XX, normalize = TRUE) ## End(Not run) ss <- mvspectrum(whiten(XX)$U, normalize = TRUE) xx <- scale(rnorm(100), center = TRUE, scale = FALSE) var(xx) sum(mvspectrum(xx, normalize = FALSE, method = "pgram")) * 2 sum(mvspectrum(xx, normalize = FALSE, method = "mvspec")) * 2 ## Not run: sum(mvspectrum(xx, normalize = FALSE, method = "pspectrum")) * 2 ## End(Not run) ## Not run: xx <- scale(rnorm(100), center = TRUE, scale = FALSE) ss <- mvspectrum(xx) ss.n <- normalize_mvspectrum(ss) sum(ss.n) # multivariate UU <- whiten(matrix(rnorm(40), ncol = 2))$U S.U <- mvspectrum(UU, method = "mvspec") mvspectrum2wcov(normalize_mvspectrum(S.U)) ## End(Not run) XX <- matrix(rnorm(1000), ncol = 2) SS <- mvspectrum(XX, "mvspec") ss1 <- mvspectrum(XX[, 1], "mvspec") SS.1 <- get_spectrum_from_mvspectrum(SS, 1) plot.default(ss1, SS.1) abline(0, 1, lty = 2, col = "blue") XX <- matrix(arima.sim(n = 1000, list(ar = 0.9)), ncol = 4) beta.tmp <- rbind(1, -1, 2, 0) yy <- XX %*% beta.tmp SS <- mvspectrum(XX, "mvspec") ss.yy.comb <- spectrum_of_linear_combination(SS, beta.tmp) ss.yy <- mvspectrum(yy, "mvspec") plot(ss.yy, log = TRUE) # using plot.mvspectrum() lines(ss.yy.comb, col = "red", lty = 1, lwd = 2)
S3 methods for multivariate spectrum estimation.
plot.mvspectrum
plots all univariate spectra. Analogouos to
spectrum
when plot = TRUE
.
## S3 method for class 'mvspectrum' plot(x, log = TRUE, ...)
## S3 method for class 'mvspectrum' plot(x, log = TRUE, ...)
x |
an object of class |
log |
logical; if |
... |
additional arguments passed to |
# see examples in 'mvspectrum' SS <- mvspectrum(diff(log(EuStockMarkets)) * 100, spectrum.control = list(method = "mvspec")) plot(SS, log = FALSE)
# see examples in 'mvspectrum' SS <- mvspectrum(diff(log(EuStockMarkets)) * 100, spectrum.control = list(method = "mvspec")) plot(SS, log = FALSE)
mvspectrum2wcov
computes a (weighted) covariance matrix estimate
from the frequency spectrum (see Details).
weightvector2entropy_wcov
computes the weighted covariance
matrix using the negative entropy of the univariate spectrum (given the
weightvector) as kernel weights. This matrix is the objective matrix
for many foreca.*
algorithms.
mvspectrum2wcov(mvspectrum.output, kernel.weights = 1) weightvector2entropy_wcov( weightvector = NULL, f.U, f.current = NULL, entropy.control = list() )
mvspectrum2wcov(mvspectrum.output, kernel.weights = 1) weightvector2entropy_wcov( weightvector = NULL, f.U, f.current = NULL, entropy.control = list() )
mvspectrum.output |
an object of class |
kernel.weights |
numeric; weights for each frequency. By default uses
weights that average out to |
weightvector |
numeric; weights |
f.U |
multivariate spectrum of class |
f.current |
numeric; spectral density estimate of
|
entropy.control |
list; control settings for entropy estimation.
See |
The covariance matrix of a multivariate time series satisfies the identity
A generalized covariance matrix estimate can thus be obtained using a weighted average
where is a kernel symmetric around
which averages out to
over the interval
, i.e.,
.
This allows one to remove or amplify specific frequencies in the covariance matrix
estimation.
For ForeCA mvspectrum2wcov
is especially important as we use
as the weights (their average is not !). This particular kernel
weight is implemented as a wrapper in
weightvector2entropy_wcov
.
A symmetric matrix.
If kernel.weights
, then it is positive semi-definite;
otherwise, it is symmetric but not necessarily positive semi-definite.
nn <- 50 YY <- cbind(rnorm(nn), arima.sim(n = nn, list(ar = 0.9)), rnorm(nn)) XX <- YY %*% matrix(rnorm(9), ncol = 3) # random mix XX <- scale(XX, scale = FALSE, center = TRUE) # sample estimate of covariance matrix Sigma.hat <- cov(XX) dimnames(Sigma.hat) <- NULL # using the frequency spectrum SS <- mvspectrum(XX, "mvspec") Sigma.hat.freq <- mvspectrum2wcov(SS) layout(matrix(1:4, ncol = 2)) par(mar = c(2, 2, 1, 1)) plot(c(Sigma.hat/Sigma.hat.freq)) abline(h = 1) image(Sigma.hat) image(Sigma.hat.freq) image(Sigma.hat / Sigma.hat.freq) # examples for entropy wcov XX <- diff(log(EuStockMarkets)) * 100 UU <- whiten(XX)$U ff <- mvspectrum(UU, "mvspec", normalize = TRUE) ww0 <- initialize_weightvector(num.series = ncol(XX), method = 'rnorm') weightvector2entropy_wcov(ww0, ff, entropy.control = list(prior.weight = 0.1))
nn <- 50 YY <- cbind(rnorm(nn), arima.sim(n = nn, list(ar = 0.9)), rnorm(nn)) XX <- YY %*% matrix(rnorm(9), ncol = 3) # random mix XX <- scale(XX, scale = FALSE, center = TRUE) # sample estimate of covariance matrix Sigma.hat <- cov(XX) dimnames(Sigma.hat) <- NULL # using the frequency spectrum SS <- mvspectrum(XX, "mvspec") Sigma.hat.freq <- mvspectrum2wcov(SS) layout(matrix(1:4, ncol = 2)) par(mar = c(2, 2, 1, 1)) plot(c(Sigma.hat/Sigma.hat.freq)) abline(h = 1) image(Sigma.hat) image(Sigma.hat.freq) image(Sigma.hat / Sigma.hat.freq) # examples for entropy wcov XX <- diff(log(EuStockMarkets)) * 100 UU <- whiten(XX)$U ff <- mvspectrum(UU, "mvspec", normalize = TRUE) ww0 <- initialize_weightvector(num.series = ncol(XX), method = 'rnorm') weightvector2entropy_wcov(ww0, ff, entropy.control = list(prior.weight = 0.1))
An estimator for the forecastability of a univariate time series
.
Currently it uses a discrete plug-in estimator given the empirical spectrum (periodogram).
Omega( series = NULL, spectrum.control = list(), entropy.control = list(), mvspectrum.output = NULL )
Omega( series = NULL, spectrum.control = list(), entropy.control = list(), mvspectrum.output = NULL )
series |
a univariate time series; if it is multivariate, then
|
spectrum.control |
list; control settings for spectrum estimation.
See |
entropy.control |
list; control settings for entropy estimation.
See |
mvspectrum.output |
an object of class |
The forecastability of a stationary process is defined as
(see References)
where is the normalized spectral density of
.
In particular
.
For white noise forecastability
; for a sum of sinusoids it equals
%.
However, empirically it reaches
only if the estimated spectrum has
exactly one peak at some
and
for all
.
In practice, a time series of length T
has Fourier frequencies
which represent a discrete
probability distribution. Hence entropy of
must be
normalized by
, not by
.
Also we can use several smoothing techniques to obtain a less variance estimate of
.
A real-value between and
(%).
means not
forecastable (white noise);
means perfectly forecastable (a
sinusoid).
Goerg, G. M. (2013). “Forecastable Component Analysis”. Journal of Machine Learning Research (JMLR) W&CP 28 (2): 64-72, 2013. Available at http://jmlr.org/proceedings/papers/v28/goerg13.html.
spectral_entropy
, discrete_entropy
,
continuous_entropy
nn <- 100 eps <- rnorm(nn) # white noise has Omega() = 0 in theory Omega(eps, spectrum.control = list(method = "pgram")) # smoothing makes it closer to 0 Omega(eps, spectrum.control = list(method = "mvspec")) xx <- sin(seq_len(nn) * pi / 10) Omega(xx, spectrum.control = list(method = "pgram")) Omega(xx, entropy.control = list(threshold = 1/40)) Omega(xx, spectrum.control = list(method = "mvspec"), entropy.control = list(threshold = 1/20)) # an AR(1) with phi = 0.5 yy <- arima.sim(n = nn, model = list(ar = 0.5)) Omega(yy, spectrum.control = list(method = "mvspec")) # an AR(1) with phi = 0.9 is more forecastable yy <- arima.sim(n = nn, model = list(ar = 0.9)) Omega(yy, spectrum.control = list(method = "mvspec"))
nn <- 100 eps <- rnorm(nn) # white noise has Omega() = 0 in theory Omega(eps, spectrum.control = list(method = "pgram")) # smoothing makes it closer to 0 Omega(eps, spectrum.control = list(method = "mvspec")) xx <- sin(seq_len(nn) * pi / 10) Omega(xx, spectrum.control = list(method = "pgram")) Omega(xx, entropy.control = list(threshold = 1/40)) Omega(xx, spectrum.control = list(method = "mvspec"), entropy.control = list(threshold = 1/20)) # an AR(1) with phi = 0.5 yy <- arima.sim(n = nn, model = list(ar = 0.5)) Omega(yy, spectrum.control = list(method = "mvspec")) # an AR(1) with phi = 0.9 is more forecastable yy <- arima.sim(n = nn, model = list(ar = 0.9)) Omega(yy, spectrum.control = list(method = "mvspec"))
quadratic_form
computes the quadratic form for an
matrix
and an
-dimensional vector
, i.e., a wrapper for
t(x) %*% A %*% x
.
fill_symmetric
and quadratic_form
work with
real and complex valued matrices/vectors.
fill_hermitian
fills up the lower triangular part (NA
)
of an upper triangular matrix to its
Hermitian (symmetric if real matrix) version, such that it satisfies
, where
is the complex
conjugate of
. If the matrix is real-valued this makes it
simply symmetric.
Note that the input matrix must have a real-valued diagonal and
NA
s in the lower triangular part.
quadratic_form(mat, vec) fill_hermitian(mat)
quadratic_form(mat, vec) fill_hermitian(mat)
mat |
numeric; |
vec |
numeric; |
A real/complex value .
## Not run: set.seed(1) AA <- matrix(1:4, ncol = 2) bb <- matrix(rnorm(2)) t(bb) %*% AA %*% bb quadratic_form(AA, bb) ## End(Not run) AA <- matrix(1:16, ncol = 4) AA[lower.tri(AA)] <- NA AA fill_hermitian(AA)
## Not run: set.seed(1) AA <- matrix(1:4, ncol = 2) bb <- matrix(rnorm(2)) t(bb) %*% AA %*% bb quadratic_form(AA, bb) ## End(Not run) AA <- matrix(1:16, ncol = 4) AA[lower.tri(AA)] <- NA AA fill_hermitian(AA)
sfa
performs Slow Feature Analysis (SFA) on a
-dimensional time series with
observations.
Important: This implementation of SFA is just the most basic
version; it is merely included here for convenience in
initialize_weightvector
. If you want to actually use full functionality of SFA in R
use the rSFA package, which has a much more advanced and efficient implementations.
sfa()
here corresponds to sfa1
.
sfa(series, ...)
sfa(series, ...)
series |
a |
... |
additional arguments |
Slow Feature Analysis (SFA) finds slow signals (see References below). The problem has an
analytic solution and thus can be computed quickly using generalized eigen-value solvers.
For ForeCA it is important to know that SFA is equivalent to
finding a linear combination signal with largest lag autocorrelation.
The disadvantage of SFA for forecasting is that, e.g., white noise (WN)
is ranked higher than an AR(1) with negative autocorrelation coefficient
. While it is true that WN is slower, it is not more
forecastable. Thus we are also interested in the fastest signal, i.e.,
the last eigenvector. The so obtained fastest signal corresponds to minimizing
the lag 1 auto-correlation (possibly
).
Note though that maximizing (or minimizing) the lag auto-correlation does
not necessarily yield the most forecastable signal (as measured
by
Omega
), but it is a good start.
An object of class sfa
which inherits methods from princomp
.
Signals are ordered from slowest to fastest.
Laurenz Wiskott and Terrence J. Sejnowski (2002). “Slow Feature Analysis: Unsupervised Learning of Invariances”, Neural Computation 14:4, 715-770.
XX <- diff(log(EuStockMarkets[-c(1:100),])) * 100 plot(ts(XX)) ss <- sfa(XX[,1:4]) summary(ss) plot(ss) plot(ts(ss$scores)) apply(ss$scores, 2, function(x) acf(x, plot = FALSE)$acf[2]) biplot(ss)
XX <- diff(log(EuStockMarkets[-c(1:100),])) * 100 plot(ts(XX)) ss <- sfa(XX[,1:4]) summary(ss) plot(ss) plot(ts(ss$scores)) apply(ss$scores, 2, function(x) acf(x, plot = FALSE)$acf[2]) biplot(ss)
Estimates spectral entropy from a univariate (or multivariate) normalized spectral density.
spectral_entropy( series = NULL, spectrum.control = list(), entropy.control = list(), mvspectrum.output = NULL, ... )
spectral_entropy( series = NULL, spectrum.control = list(), entropy.control = list(), mvspectrum.output = NULL, ... )
series |
univariate time series of length |
spectrum.control |
list; control settings for spectrum estimation.
See |
entropy.control |
list; control settings for entropy estimation.
See |
mvspectrum.output |
optional; one can directly provide an estimate of
the spectrum of |
... |
additional arguments passed to |
The spectral entropy equals the Shannon entropy of the spectral density
of a stationary process
:
where the density is normalized such that
. An estimate of
can be obtained
by the (smoothed) periodogram (see
mvspectrum
); thus using discrete, and
not continuous entropy.
A non-negative real value for the spectral entropy .
Jerry D. Gibson and Jaewoo Jung (2006). “The Interpretation of Spectral Entropy Based Upon Rate Distortion Functions”. IEEE International Symposium on Information Theory, pp. 277-281.
L. L. Campbell, “Minimum coefficient rate for stationary random processes”, Information and Control, vol. 3, no. 4, pp. 360 - 371, 1960.
set.seed(1) eps <- rnorm(100) spectral_entropy(eps) phi.v <- seq(-0.95, 0.95, by = 0.1) kMethods <- c("mvspec", "pgram") SE <- matrix(NA, ncol = length(kMethods), nrow = length(phi.v)) for (ii in seq_along(phi.v)) { xx.tmp <- arima.sim(n = 200, list(ar = phi.v[ii])) for (mm in seq_along(kMethods)) { SE[ii, mm] <- spectral_entropy(xx.tmp, spectrum.control = list(method = kMethods[mm])) } } matplot(phi.v, SE, type = "l", col = seq_along(kMethods)) legend("bottom", kMethods, lty = seq_along(kMethods), col = seq_along(kMethods)) # AR vs MA SE.arma <- matrix(NA, ncol = 2, nrow = length(phi.v)) SE.arma[, 1] <- SE[, 2] for (ii in seq_along(phi.v)){ yy.temp <- arima.sim(n = 1000, list(ma = phi.v[ii])) SE.arma[ii, 2] <- spectral_entropy(yy.temp, spectrum.control = list(method = "mvspec")) } matplot(phi.v, SE.arma, type = "l", col = 1:2, xlab = "parameter (phi or theta)", ylab = "Spectral entropy") abline(v = 0, col = "blue", lty = 3) legend("bottom", c("AR(1)", "MA(1)"), lty = 1:2, col = 1:2)
set.seed(1) eps <- rnorm(100) spectral_entropy(eps) phi.v <- seq(-0.95, 0.95, by = 0.1) kMethods <- c("mvspec", "pgram") SE <- matrix(NA, ncol = length(kMethods), nrow = length(phi.v)) for (ii in seq_along(phi.v)) { xx.tmp <- arima.sim(n = 200, list(ar = phi.v[ii])) for (mm in seq_along(kMethods)) { SE[ii, mm] <- spectral_entropy(xx.tmp, spectrum.control = list(method = kMethods[mm])) } } matplot(phi.v, SE, type = "l", col = seq_along(kMethods)) legend("bottom", kMethods, lty = seq_along(kMethods), col = seq_along(kMethods)) # AR vs MA SE.arma <- matrix(NA, ncol = 2, nrow = length(phi.v)) SE.arma[, 1] <- SE[, 2] for (ii in seq_along(phi.v)){ yy.temp <- arima.sim(n = 1000, list(ma = phi.v[ii])) SE.arma[ii, 2] <- spectral_entropy(yy.temp, spectrum.control = list(method = "mvspec")) } matplot(phi.v, SE.arma, type = "l", col = 1:2, xlab = "parameter (phi or theta)", ylab = "Spectral entropy") abline(v = 0, col = "blue", lty = 3) legend("bottom", c("AR(1)", "MA(1)"), lty = 1:2, col = 1:2)
whiten
transforms a multivariate K-dimensional signal with mean
and covariance matrix
to a whitened
signal
with mean
and
.
Thus it centers the signal and makes it contemporaneously uncorrelated.
See Details.
check_whitened
checks if data has been whitened; i.e., if it has
zero mean, unit variance, and is uncorrelated.
sqrt_matrix
computes the square root of a square matrix
. The matrix
satisfies
.
whiten(data) check_whitened(data, check.attribute.only = TRUE) sqrt_matrix(mat, return.sqrt.only = TRUE, symmetric = FALSE)
whiten(data) check_whitened(data, check.attribute.only = TRUE) sqrt_matrix(mat, return.sqrt.only = TRUE, symmetric = FALSE)
data |
|
check.attribute.only |
logical; if |
mat |
a square |
return.sqrt.only |
logical; if |
symmetric |
logical; if |
whiten
uses zero component analysis (ZCA) (aka zero-phase whitening filters)
to whiten the data; i.e., it uses the
inverse square root of the covariance matrix of (see
sqrt_matrix
) as the whitening transformation.
This means that on top of PCA, the uncorrelated principal components are
back-transformed to the original space using the
transpose of the eigenvectors. The advantage is that this makes them comparable
to the original . See References for details.
The square root of a quadratic matrix
can be computed by using the eigen-decomposition of
where is an
matrix with the eigenvalues
in the diagonal.
The square root is simply
where
.
Similarly, the inverse square root is defined as
, where
(provided that
).
whiten
returns a list with the whitened data, the transformation,
and other useful quantities.
check_whitened
throws an error if the input is not
whiten
ed, and returns (invisibly) the data with an attribute 'whitened'
equal to TRUE
. This allows to simply update data to have the
attribute and thus only check it once on the actual data (slow) but then
use the attribute lookup (fast).
sqrt_matrix
returns an matrix. If
is not semi-positive definite it returns a complex-valued
(since square root of negative eigenvalues are complex).
If return.sqrt.only = FALSE
then it returns a list with:
values |
eigenvalues of |
vectors |
eigenvectors of |
sqrt |
square root matrix |
sqrt.inverse |
inverse of |
See appendix in http://www.cs.toronto.edu/~kriz/learning-features-2009-TR.pdf.
See http://ufldl.stanford.edu/wiki/index.php/Implementing_PCA/Whitening.
## Not run: XX <- matrix(rnorm(100), ncol = 2) %*% matrix(runif(4), ncol = 2) cov(XX) UU <- whiten(XX)$U cov(UU) ## End(Not run)
## Not run: XX <- matrix(rnorm(100), ncol = 2) %*% matrix(runif(4), ncol = 2) cov(XX) UU <- whiten(XX)$U cov(UU) ## End(Not run)