Skill Tracer
Skills › Scientific Agent Skills › aeon › distances.md

distances.md

264 lines · skills/aeon/references/distances.md at 5f2bc03

Open on GitHub
1# Distance Metrics
2
3Aeon provides specialized distance functions for measuring similarity between time series, compatible with both aeon and scikit-learn estimators.
4

Distance Metrics

Aeon provides specialized distance functions for measuring similarity between time series, compatible with both aeon and scikit-learn estimators.

Raw lines 1 to 4
5## Distance Categories
6

Distance Categories

Raw lines 5 to 6
7### Elastic Distances
8
9Allow flexible temporal alignment between series:
11**Dynamic Time Warping Family:**
12- `dtw` - Classic Dynamic Time Warping
13- `ddtw` - Derivative DTW (compares derivatives)
14- `wdtw` - Weighted DTW (penalizes warping by location)
15- `wddtw` - Weighted Derivative DTW
16- `shape_dtw` - Shape-based DTW
18**Edit-Based:**
19- `erp` - Edit distance with Real Penalty
20- `edr` - Edit Distance on Real sequences
21- `lcss` - Longest Common SubSequence
22- `twe` - Time Warp Edit distance
24**Specialized:**
25- `msm` - Move-Split-Merge distance
26- `adtw` - Amerced DTW
27- `sbd` - Shape-Based Distance
29**Use when**: Time series may have temporal shifts, speed variations, or phase differences.

Elastic Distances

Allow flexible temporal alignment between series:

Dynamic Time Warping Family:

  • dtw - Classic Dynamic Time Warping
  • ddtw - Derivative DTW (compares derivatives)
  • wdtw - Weighted DTW (penalizes warping by location)
  • wddtw - Weighted Derivative DTW
  • shape_dtw - Shape-based DTW

Edit-Based:

  • erp - Edit distance with Real Penalty
  • edr - Edit Distance on Real sequences
  • lcss - Longest Common SubSequence
  • twe - Time Warp Edit distance

Specialized:

  • msm - Move-Split-Merge distance
  • adtw - Amerced DTW
  • sbd - Shape-Based Distance

Use when: Time series may have temporal shifts, speed variations, or phase differences.

Raw lines 7 to 30
31### Lock-Step Distances
33Compare time series point-by-point without alignment:
35- `euclidean` - Euclidean distance (L2 norm)
36- `manhattan` - Manhattan distance (L1 norm)
37- `minkowski` - Generalized Minkowski distance (Lp norm)
38- `squared` - Squared Euclidean distance
40**Use when**: Series already aligned, need computational speed, or no temporal warping expected.

Lock-Step Distances

Compare time series point-by-point without alignment:

  • euclidean - Euclidean distance (L2 norm)
  • manhattan - Manhattan distance (L1 norm)
  • minkowski - Generalized Minkowski distance (Lp norm)
  • squared - Squared Euclidean distance

Use when: Series already aligned, need computational speed, or no temporal warping expected.

Raw lines 31 to 41
42## Usage Patterns

Usage Patterns

Raw lines 42 to 43
44### Computing Single Distance
46```python
47from aeon.distances import dtw_distance
49# Distance between two time series
50distance = dtw_distance(x, y)
52# With window constraint (Sakoe-Chiba band)
53distance = dtw_distance(x, y, window=0.1)
54```

Computing Single Distance

from aeon.distances import dtw_distance

# Distance between two time series
distance = dtw_distance(x, y)

# With window constraint (Sakoe-Chiba band)
distance = dtw_distance(x, y, window=0.1)
Raw lines 44 to 55
56### Pairwise Distance Matrix
58```python
59from aeon.distances import dtw_pairwise_distance
61# All pairwise distances in collection
62X = [series1, series2, series3, series4]
63distance_matrix = dtw_pairwise_distance(X)
65# Cross-collection distances
66distance_matrix = dtw_pairwise_distance(X_train, X_test)
67```

Pairwise Distance Matrix

from aeon.distances import dtw_pairwise_distance

# All pairwise distances in collection
X = [series1, series2, series3, series4]
distance_matrix = dtw_pairwise_distance(X)

# Cross-collection distances
distance_matrix = dtw_pairwise_distance(X_train, X_test)
Raw lines 56 to 68
69### Cost Matrix and Alignment Path
71```python
72from aeon.distances import dtw_cost_matrix, dtw_alignment_path
74# Get full cost matrix
75cost_matrix = dtw_cost_matrix(x, y)
77# Get optimal alignment path
78path, cost = dtw_alignment_path(x, y)
79# path is a list of index pairs; cost equals dtw_distance(x, y)
80```

Cost Matrix and Alignment Path

from aeon.distances import dtw_cost_matrix, dtw_alignment_path

# Get full cost matrix
cost_matrix = dtw_cost_matrix(x, y)

# Get optimal alignment path
path, cost = dtw_alignment_path(x, y)
# path is a list of index pairs; cost equals dtw_distance(x, y)
Raw lines 69 to 81
82### Using with Estimators
84```python
85from aeon.classification.distance_based import KNeighborsTimeSeriesClassifier
87# Use DTW distance in classifier
88clf = KNeighborsTimeSeriesClassifier(
89 n_neighbors=5,
90 distance="dtw",
91 distance_params={"window": 0.2}
93clf.fit(X_train, y_train)
94```

Using with Estimators

from aeon.classification.distance_based import KNeighborsTimeSeriesClassifier

# Use DTW distance in classifier
clf = KNeighborsTimeSeriesClassifier(
    n_neighbors=5,
    distance="dtw",
    distance_params={"window": 0.2}
)
clf.fit(X_train, y_train)
Raw lines 82 to 95
96## Distance Parameters

Distance Parameters

Raw lines 96 to 97
98### Window Constraints
100Limit warping path deviation (improves speed and prevents pathological warping):
102```python
103# Sakoe-Chiba band: window as fraction of series length
104dtw_distance(x, y, window=0.1) # Allow 10% deviation
106# Itakura parameter is a fraction in [0, 1], not a raw slope
107dtw_distance(x, y, itakura_max_slope=0.5)
108```

Window Constraints

Limit warping path deviation (improves speed and prevents pathological warping):

# Sakoe-Chiba band: window as fraction of series length
dtw_distance(x, y, window=0.1)  # Allow 10% deviation

# Itakura parameter is a fraction in [0, 1], not a raw slope
dtw_distance(x, y, itakura_max_slope=0.5)
Raw lines 98 to 109
110### Normalization
112Normalize explicitly when shape rather than amplitude is the scientific target. `dtw_distance` has no `normalize` argument; it returns the accumulated squared local cost, without a final square root:
114```python
115import numpy as np
116from aeon.transformations.collection import Normalizer
118# x and y are equal-length univariate arrays here
119xy = Normalizer().fit_transform(np.stack([x, y])[:, None, :])
120distance = dtw_distance(xy[0], xy[1])
121```

Normalization

Normalize explicitly when shape rather than amplitude is the scientific target. dtw_distance has no normalize argument; it returns the accumulated squared local cost, without a final square root:

import numpy as np
from aeon.transformations.collection import Normalizer

# x and y are equal-length univariate arrays here
xy = Normalizer().fit_transform(np.stack([x, y])[:, None, :])
distance = dtw_distance(xy[0], xy[1])
Raw lines 110 to 122
123### Distance-Specific Parameters
125```python
126from aeon.distances import erp_distance, twe_distance, lcss_distance
128# ERP: penalty for gaps
129distance = erp_distance(x, y, g=0.5)
131# TWE: stiffness and penalty parameters
132distance = twe_distance(x, y, nu=0.001, lmbda=1.0)
134# LCSS: epsilon threshold for matching
135distance = lcss_distance(x, y, epsilon=0.5)
136```

Distance-Specific Parameters

from aeon.distances import erp_distance, twe_distance, lcss_distance

# ERP: penalty for gaps
distance = erp_distance(x, y, g=0.5)

# TWE: stiffness and penalty parameters
distance = twe_distance(x, y, nu=0.001, lmbda=1.0)

# LCSS: epsilon threshold for matching
distance = lcss_distance(x, y, epsilon=0.5)
Raw lines 123 to 137
138## Algorithm Selection

Algorithm Selection

Raw lines 138 to 139
140### By Use Case:
142**Temporal misalignment**: DTW, DDTW, WDTW
143**Speed variations**: DTW with window constraint
144**Shape similarity**: Shape DTW, SBD
145**Edit operations**: ERP, EDR, LCSS
146**Derivative matching**: DDTW
147**Computational speed**: Euclidean, Manhattan
148**Outlier robustness**: Manhattan, LCSS

By Use Case:

Temporal misalignment: DTW, DDTW, WDTW Speed variations: DTW with window constraint Shape similarity: Shape DTW, SBD Edit operations: ERP, EDR, LCSS Derivative matching: DDTW Computational speed: Euclidean, Manhattan Outlier robustness: Manhattan, LCSS

Raw lines 140 to 149
150### By Computational Cost:
152**Fastest**: Euclidean (O(n))
153**Fast**: Constrained DTW (O(nw) where w is window)
154**Medium**: Full DTW (O(n²))
155**Slower**: Complex elastic distances (ERP, TWE, MSM)

By Computational Cost:

Fastest: Euclidean (O(n)) Fast: Constrained DTW (O(nw) where w is window) Medium: Full DTW (O(n²)) Slower: Complex elastic distances (ERP, TWE, MSM)

Raw lines 150 to 156
157## Quick Reference Table
159| Distance | Alignment | Speed | Robustness | Interpretability |
160|----------|-----------|-------|------------|------------------|
161| Euclidean | Lock-step | Very Fast | Low | High |
162| DTW | Elastic | Medium | Medium | Medium |
163| DDTW | Elastic | Medium | High | Medium |
164| WDTW | Elastic | Medium | Medium | Medium |
165| ERP | Edit-based | Slow | High | Low |
166| LCSS | Edit-based | Slow | Very High | Low |
167| Shape DTW | Elastic | Medium | Medium | High |

Quick Reference Table

DistanceAlignmentSpeedRobustnessInterpretability
EuclideanLock-stepVery FastLowHigh
DTWElasticMediumMediumMedium
DDTWElasticMediumHighMedium
WDTWElasticMediumMediumMedium
ERPEdit-basedSlowHighLow
LCSSEdit-basedSlowVery HighLow
Shape DTWElasticMediumMediumHigh
Raw lines 157 to 168
169## Best Practices

Best Practices

Raw lines 169 to 170
171### 1. Normalization
173Most distances sensitive to scale; normalize when appropriate:
175```python
176from aeon.transformations.collection import Normalizer
178normalizer = Normalizer()
179X_normalized = normalizer.fit_transform(X)
180```

1. Normalization

Most distances sensitive to scale; normalize when appropriate:

from aeon.transformations.collection import Normalizer

normalizer = Normalizer()
X_normalized = normalizer.fit_transform(X)
Raw lines 171 to 181
182### 2. Window Constraints
184For DTW variants, use window constraints for speed and better generalization:
186```python
187# Start with 10-20% window
188distance = dtw_distance(x, y, window=0.1)
189```

2. Window Constraints

For DTW variants, use window constraints for speed and better generalization:

# Start with 10-20% window
distance = dtw_distance(x, y, window=0.1)
Raw lines 182 to 190
191### 3. Series Length
193- Equal-length required: Most lock-step distances
194- Unequal-length supported: Elastic distances (DTW, ERP, etc.)

3. Series Length

  • Equal-length required: Most lock-step distances
  • Unequal-length supported: Elastic distances (DTW, ERP, etc.)
Raw lines 191 to 195
196### 4. Multivariate Series
198Most distances support multivariate time series:
200```python
201# x.shape = (n_channels, n_timepoints)
202distance = dtw_distance(x_multivariate, y_multivariate)
203```

4. Multivariate Series

Most distances support multivariate time series:

# x.shape = (n_channels, n_timepoints)
distance = dtw_distance(x_multivariate, y_multivariate)
Raw lines 196 to 204
205### 5. Performance Optimization
207- Use numba-compiled implementations (default in aeon)
208- Consider lock-step distances if alignment not needed
209- Use windowed DTW instead of full DTW
210- Precompute distance matrices for repeated use

5. Performance Optimization

  • Use numba-compiled implementations (default in aeon)
  • Consider lock-step distances if alignment not needed
  • Use windowed DTW instead of full DTW
  • Precompute distance matrices for repeated use
Raw lines 205 to 211
212### 6. Choosing the Right Distance
214```python
215# Quick decision tree:
216if series_aligned:
217 use_distance = "euclidean"
218elif need_speed:
219 use_distance = "dtw" # with window constraint
220elif temporal_shifts_expected:
221 use_distance = "dtw" # compare with "shape_dtw" by validation
222elif outliers_present:
223 use_distance = "lcss" # compare with "manhattan" by validation
224elif derivatives_matter:
225 use_distance = "ddtw" # compare with "wddtw" by validation
226```

6. Choosing the Right Distance

# Quick decision tree:
if series_aligned:
    use_distance = "euclidean"
elif need_speed:
    use_distance = "dtw"  # with window constraint
elif temporal_shifts_expected:
    use_distance = "dtw"  # compare with "shape_dtw" by validation
elif outliers_present:
    use_distance = "lcss"  # compare with "manhattan" by validation
elif derivatives_matter:
    use_distance = "ddtw"  # compare with "wddtw" by validation
Raw lines 212 to 227
228## Integration with scikit-learn
230Aeon distances work with sklearn estimators:
232```python
233from sklearn.neighbors import KNeighborsClassifier
234from aeon.distances import dtw_pairwise_distance
236# Precompute distance matrix
237X_train_distances = dtw_pairwise_distance(X_train)
239# Use with sklearn
240clf = KNeighborsClassifier(metric='precomputed')
241clf.fit(X_train_distances, y_train)
242X_test_distances = dtw_pairwise_distance(X_test, X_train)
243predictions = clf.predict(X_test_distances) # shape: test cases by train cases
244```

Integration with scikit-learn

Aeon distances work with sklearn estimators:

from sklearn.neighbors import KNeighborsClassifier
from aeon.distances import dtw_pairwise_distance

# Precompute distance matrix
X_train_distances = dtw_pairwise_distance(X_train)

# Use with sklearn
clf = KNeighborsClassifier(metric='precomputed')
clf.fit(X_train_distances, y_train)
X_test_distances = dtw_pairwise_distance(X_test, X_train)
predictions = clf.predict(X_test_distances)  # shape: test cases by train cases
Raw lines 228 to 245
246## Available Distance Functions
248Get list of all available distances:
250```python
251from aeon.distances import get_distance_function_names
253print(get_distance_function_names())
254# ['dtw', 'ddtw', 'wdtw', 'euclidean', 'erp', 'edr', ...]
255```
257Retrieve specific distance function:
259```python
260from aeon.distances import get_distance_function
262distance_func = get_distance_function("dtw")
263result = distance_func(x, y, window=0.1)
264```

Available Distance Functions

Get list of all available distances:

from aeon.distances import get_distance_function_names

print(get_distance_function_names())
# ['dtw', 'ddtw', 'wdtw', 'euclidean', 'erp', 'edr', ...]

Retrieve specific distance function:

from aeon.distances import get_distance_function

distance_func = get_distance_function("dtw")
result = distance_func(x, y, window=0.1)
Raw lines 246 to 264