fcd_ks#
- class braintools.fit.losses.fcd_ks(prediction, target, *, window_size=30, step_size=5, midpoints=None, bw_method=None, n_diag=1)#
Compute the Kolmogorov-Smirnov distance between two FCD value distributions.
The functional-connectivity-dynamics (FCD) matrix of each input is computed with
functional_connectivity_dynamics(); the values above then_diag-th diagonal are smoothed into a density onmidpointsby a Gaussian kernel density estimate (jax.scipy.stats.gaussian_kde), and the two densities are compared withks_distance(). Comparing FCD distributions (rather than the matrices) is the standard FCD fitting target [1].- Parameters:
prediction (
Any) – Model output of shape(n_time, n_regions),n_regions >= 2.target (
Any) – Data of shape(n_time', n_regions'). FCD is scale-invariant, so units are not compared.window_size (
int) – Sliding-window length in samples (static).step_size (
int) – Sliding-window stride in samples (static).midpoints (
Any|None) – Grid of FCD values on which the densities are evaluated. Defaults to 100 points on[-0.99, 0.99].bw_method (
Any|None) – KDE bandwidth, forwarded tojax.scipy.stats.gaussian_kde(default: Scott’s rule).n_diag (
int) – Diagonal offset of the upper triangle; 1 excludes the unit diagonal.
- Returns:
Scalar KS distance in
[0, 1].- Return type:
Array- Raises:
ValueError – If an input is not 2-D with at least 2 regions, or its FCD has fewer than 2 values above the diagonal offset.
Notes
Ported from
brainmass.objectives.fcd_ks(...)(a factory there) with identical numerics. The KS statistic is non-smooth; use it for evaluation andfcd_wasserstein()as a gradient-fitting loss. If all FCD values of an input are equal, the KDE is degenerate and the result isnan. Works underjax.jitandjax.vmapwith static window options.Memory. The FCD matrix of
Wwindows hasW**2entries and the KDE sumsW(W-1)/2kernel terms for each of theMmidpoints. TheW(W-1)/2 x Mkernel matrix is never formed whole: midpoints are processed in blocks of at most about 2**20 terms (4 MiB in float32), and each block is recomputed on the backward pass rather than stored, so temporaries grow asO(W**2)rather thanO(W**2 M). For example, 20 regions,T = 5000,window_size=30,step_size=5(995 windows) need about 24 MiB of temporaries forward (previously 192 MiB). Undervmap(e.g. over the starts of a fit) the temporaries scale with the batch size.References
Examples
>>> import numpy as np >>> import jax.numpy as jnp >>> from braintools.fit import losses >>> x = jnp.asarray(np.random.default_rng(0).standard_normal((200, 6))) >>> float(losses.fcd_ks(x, x, window_size=30, step_size=5)) 0.0