Skip to content

v-code01/saxpivot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

saxpivot

tslearn's 1d-SAX represents each segment by an average symbol and a slope symbol and reconstructs the segment as the line avg + slope * (t - pivot). The 1d-SAX distance is defined as the Euclidean distance between the two reconstructed piecewise-linear series, which the estimator produces with inverse_transform. The reconstruction and the slope fit use the segment centroid t0 + (seg_sz-1)/2 as the pivot, but the distance uses t0 + seg_sz/2, half a timestep off. So OneD_SymbolicAggregateApproximation.distance disagrees with the Euclidean distance between the model's own reconstructions whenever two segments differ in slope, by a bias proportional to the slope difference.

The code

tslearn, tslearn/metrics/cysax.py, 0.9.0 and current main (byte-identical):

# cyslopes (line 107-121): the slope is fit over the indices t0 .. t0+sz-1, centroid t0 + (sz-1)/2
vec_t = np.arange(t0, t0 + sz).reshape((-1, 1))

# cydist_1d_sax (line 174): the distance pivot is t0 + seg_sz/2
t_middle = float(t0) + 0.5 * seg_sz
... s += (avg1 + slope1 * (tt - t_middle) - (avg2 + slope2 * (tt - t_middle))) ** 2

# inv_transform_1d_sax (line 217): the reconstruction pivot is t0 + (seg_sz-1)/2
t_middle = float(t0) + 0.5 * (seg_sz - 1)

The slope is measured about the centroid t0 + (seg_sz-1)/2, and the reconstruction places it there, but the distance evaluates the line about t0 + seg_sz/2, half a step later. The difference of the two reconstructions at sample t is (avg1-avg2) + (slope1-slope2)*(t - pivot), so the half-step pivot shift changes it by (slope1-slope2)/2 at every sample. The distance is therefore self-inconsistent with the reconstruction that defines it; the term vanishes only when the two slopes are equal.

What it does

Driving the real estimator (fp64):

distance_1d_sax 4.83954 vs reconstruction L2 4.34056 (11.5% error)
buggy pivot reproduces est.distance: True
corrected pivot matches reconstruction L2: True (4.34056 vs 4.34056)

The 1d-SAX distance between two words is 4.83954, but the Euclidean distance between the estimator's own inverse_transform reconstructions of the same words is 4.34056, an 11.5 percent discrepancy. Recomputing the distance sum with the buggy pivot t0 + seg_sz/2 reproduces the shipped distance exactly, and recomputing it with the reconstruction pivot t0 + (seg_sz-1)/2 matches the reconstruction distance to machine precision. Only the pivot offset changes between the two, so the tree, the breakpoints, and the averaging are exonerated and the half-step pivot is the sole cause; when the segment slopes are equal the offset cancels and the distance is correct.

Scope

OneD_SymbolicAggregateApproximation.distance and .distance_1d_sax are the documented public 1d-SAX distances, and they run on default parameters over ordinary time series, silently: no exception, just a distance that is not the Euclidean distance between the model's own reconstructions whenever segment slopes differ, which is the generic case for real data. The error is a structural half-timestep bias, not floating-point round-off. The fix is t_middle = t0 + 0.5*(seg_sz - 1) at line 174, matching the reconstruction and the slope fit.

Layout

  • excerpt.py: the slope fit, the distance pivot, and the reconstruction pivot quoted with the flags that name the fault (BSD-2).
  • sax.py: the segment distance under both pivots, so the two agree when the slopes are equal and differ by the slope-difference bias otherwise.
  • consequence.py: the real distance_1d_sax against the Euclidean distance of the model's own reconstructions, and the distance recomputed with the buggy and the corrected pivot.
  • test_saxpivot.py: the pivot matters only when slopes differ and the offsets differ by half a step; the real distance disagrees with its reconstruction, the buggy pivot reproduces the estimator, and the corrected pivot matches the reconstruction.

Reproduce

python sax.py
python consequence.py
python test_saxpivot.py

The pivots are quoted from current main; the distances are produced by the real estimator. The fix is to evaluate the distance about the reconstruction pivot t0 + 0.5*(seg_sz - 1), so the 1d-SAX distance equals the Euclidean distance between the reconstructions that define it.

About

tslearn 1d-SAX distance evaluates segment lines about pivot t0+seg_sz/2 while the reconstruction and slope fit use t0+(seg_sz-1)/2; distance_1d_sax disagrees with the L2 of its own inverse_transform by ~11% whenever segment slopes differ

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages