<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://jensdhondt.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://jensdhondt.com/" rel="alternate" type="text/html" /><updated>2026-09-14T14:23:58+00:00</updated><id>https://jensdhondt.com/feed.xml</id><title type="html">Jens E. d’Hondt, PhD</title><subtitle>Jens d&apos;Hondt, postdoctoral scientist at the Barcelona Supercomputing Center: ML downscaling of atmospheric simulations and multivariate time-series search.</subtitle><author><name>Jens E. d&apos;Hondt, PhD</name><email>jens.dhondt@bsc.es</email></author><entry><title type="html">Which distance measure should you use for multivariate time series?</title><link href="https://jensdhondt.com/blog/distance-measures-multivariate-time-series/" rel="alternate" type="text/html" title="Which distance measure should you use for multivariate time series?" /><published>2026-09-14T00:00:00+00:00</published><updated>2026-09-14T00:00:00+00:00</updated><id>https://jensdhondt.com/blog/distance-measures-multivariate-time-series</id><content type="html" xml:base="https://jensdhondt.com/blog/distance-measures-multivariate-time-series/"><![CDATA[<p><strong>TL;DR</strong> If you need a distance measure for multivariate time series and have no time to experiment, start with the channel-dependent Shape-based Distance (SBD-D): in our SIGMOD 2025 study it gave the best accuracy for its runtime, and it has no parameters to tune. If speed is everything, use Lorentzian distance instead of Euclidean; if accuracy is everything and you can afford days of compute, use a tuned channel-independent elastic measure like MSM-I. And do not assume z-score normalization helps: on the 30 datasets we tested, not normalizing at all ranked first.</p>

<h2 id="why-this-is-a-harder-question-than-it-looks">Why this is a harder question than it looks</h2>

<p>For a univariate time series, a distance measure only has to decide how to deal with time. Two recordings of the same event can be shifted, stretched, or noisy, and the measure either corrects for those distortions or it does not. Decades of work have gone into this, and we have a good idea of what works.</p>

<p>Multivariate time series add a second question: how do you deal with the channels? You can treat every channel as its own univariate series, compute a distance per channel, and add them up. We call that the <strong>channel-independent</strong> model. Or you can treat the whole matrix as one object, so that a shift or a warping is shared by all channels. That is the <strong>channel-dependent</strong> model. For DTW these are the well-known DTW-I and DTW-D variants, and the same split exists for almost every other measure, and for normalization too: do you z-score each channel on its own, or with statistics over the whole series?</p>

<p>Almost all earlier work on multivariate distances only ever tried per-channel z-score, and only compared lock-step and elastic measures. That left a lot of the design space untested, which is what motivated the study.</p>

<h2 id="the-families-of-measures-in-plain-words">The families of measures, in plain words</h2>

<p>The survey we wrote with John Paparrizos’ group groups more than 100 measures into seven categories. The SIGMOD study uses the same categories, plus ensembles as an eighth.</p>

<ul>
  <li><strong>Lock-step measures</strong> compare value <em>i</em> of one series with value <em>i</em> of the other and add up the differences. Euclidean is the obvious example; Lorentzian and L1 are others. Fast, but blind to misalignment in time.</li>
  <li><strong>Sliding measures</strong> try every global shift between the two series and keep the best one. SBD, the distance behind k-Shape clustering, is the standard example.</li>
  <li><strong>Elastic measures</strong> allow one-to-many mappings between time points, so they absorb local stretching and compression. DTW is the famous one; newer members include MSM, TWE, ERP, and LCSS.</li>
  <li><strong>Kernel measures</strong> implicitly map series to a higher-dimensional space through a kernel function, such as GAK or SINK.</li>
  <li><strong>Feature-based measures</strong> replace a series with a vector of statistics (mean, entropy, slope, and so on) and compare those. Catch22 and TSFresh are the common feature sets.</li>
  <li><strong>Model-based measures</strong> fit a probabilistic model, such as a Gaussian or an HMM, to each series and compare the models, for example with KL divergence.</li>
  <li><strong>Embedding measures</strong> learn a new representation and compute a distance there. Deep learning methods like TS2Vec live here, alongside GRAIL and PCA-based measures.</li>
</ul>

<h2 id="what-the-study-did">What the study did</h2>

<p>We evaluated 30 standalone measures across these 8 categories, each in channel-independent and channel-dependent form where that makes sense (46 variants in total), combined with 13 normalization methods plus the option of not normalizing. Accuracy was measured with a 1-NN classifier on all 30 datasets of the UEA archive, both with supervised parameter tuning (leave-one-out cross-validation) and with a single default setting, and the main comparisons were repeated on clustering (UEA) and anomaly detection (the TSB-AD-M archive, 200 series). Differences were checked with Wilcoxon and Friedman-Nemenyi tests rather than eyeballed. The code is on GitHub as <a href="https://github.com/TheDatumOrg/MTSDistEval">MTSDistEval</a>.</p>

<h2 id="a-practical-decision-guide">A practical decision guide</h2>

<p>The table below is my reading of Table 11 and Section 6 of the paper.</p>

<table>
  <thead>
    <tr>
      <th>If your situation is…</th>
      <th>Start with</th>
      <th>Why</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Classification, clustering, or pattern matching, and you have no time to experiment</td>
      <td><strong>SBD-D</strong> (channel-dependent sliding)</td>
      <td>Best accuracy-to-runtime trade-off; no parameters</td>
    </tr>
    <tr>
      <td>Runtime is the hard constraint (sub-millisecond per comparison)</td>
      <td><strong>Lorentzian</strong> (lock-step)</td>
      <td>Significantly more accurate than Euclidean at the same cost</td>
    </tr>
    <tr>
      <td>Accuracy is all that matters and you have labeled data plus days of compute</td>
      <td><strong>MSM-I with tuned parameters</strong> (channel-independent elastic)</td>
      <td>Only tuned MSM-I and TWE-I beat SBD-D significantly</td>
    </tr>
    <tr>
      <td>You already picked an elastic measure and wonder about I versus D</td>
      <td><strong>Channel-independent</strong></td>
      <td>Independent alignment wins significantly for elastic measures</td>
    </tr>
    <tr>
      <td>You picked anything other than an elastic measure</td>
      <td><strong>Channel-dependent</strong></td>
      <td>Dependent variants win significantly for sliding and kernel measures</td>
    </tr>
    <tr>
      <td>Anomaly detection, where the distortion <em>is</em> the signal</td>
      <td><strong>Euclidean</strong> (lock-step)</td>
      <td>Beat every sliding and elastic measure we tested</td>
    </tr>
  </tbody>
</table>

<p>The main findings behind that table:</p>

<ul>
  <li><strong>Sliding measures are the sweet spot.</strong> SBD-D significantly outperformed the best lock-step measure on classification (average accuracy 0.68 versus 0.63 for Lorentzian) and on clustering (Rand index 0.75 versus 0.66 for Euclidean). On runtime, SBD-D took about 0.05 seconds on the AtrialFibrillation dataset, against 4982 seconds for MSM-I and 297 seconds for DTW-D: four to five orders of magnitude for roughly one percentage point of accuracy (0.65 versus about 0.66). SBD-D is O(CT log CT); elastic measures are O(CT^2).</li>
  <li><strong>Newer elastic measures beat DTW, but only when tuned.</strong> With leave-one-out tuning, MSM-I and TWE-I were the only measures in the whole study that significantly beat SBD-D. With fixed default parameters, no elastic measure did, and DTW-I never did in either setting.</li>
  <li><strong>Z-score is not automatically the right normalization.</strong> Per-channel z-score, the default in almost all multivariate work, ranked 12th out of 14 options in the overall meta-ranking. Not normalizing ranked first and was in the top four for every family except kernel measures. The Friedman-Nemenyi test found no normalization significantly better than the rest, which suggests the current methods, all direct extensions of univariate ones, are simply not designed for multivariate data.</li>
  <li><strong>Independent channel treatment only helps elastic measures.</strong> Pooled over all measures, the two channel models tie. Per family: dependent wins significantly for sliding and kernel measures, independent wins significantly for elastic measures. Our explanation is that global shifts (what sliding measures fix) tend to hit all sensors at once, whereas local jitter (what elastic measures fix) tends to hit one channel at a time.</li>
  <li><strong>Euclidean is not your best lock-step choice, except for anomaly detection.</strong> Lorentzian, L1, and L1,avg,inf all significantly beat Euclidean on classification. For anomaly detection with a 1-NN detector the ranking flipped: Euclidean significantly beat Lorentzian, SBD-D, DTW-D, DTW-I, and SBD-I. When you are looking for distortions, you do not want a measure that corrects them away.</li>
  <li><strong>Deep-learning embeddings did not win.</strong> TS2Vec and GRAIL beat Euclidean, but none of the embedding, feature-based, model-based, or kernel measures matched SBD-D.</li>
</ul>

<h2 id="dtw-versus-euclidean-in-one-paragraph">DTW versus Euclidean, in one paragraph</h2>

<p>Because this is the comparison people actually search for: on multivariate classification, DTW-I and DTW-D scored higher than Euclidean on average, but DTW never significantly beat the parameter-free SBD-D, and it costs hours to days of compute on the larger UEA datasets. About to reach for DTW by default? Try SBD-D first. About to reach for Euclidean? Try Lorentzian.</p>

<h2 id="code-one-lock-step-and-one-elastic-distance-in-python">Code: one lock-step and one elastic distance in Python</h2>

<p>I used <a href="https://www.aeon-toolkit.org/">aeon</a> 1.1.0 here because it ships multivariate versions of Euclidean, DTW, MSM, and SBD out of the box. Series are arrays of shape <code class="language-plaintext highlighter-rouge">(n_channels, n_timepoints)</code>.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="n">np</span>
<span class="kn">from</span> <span class="nn">aeon.distances</span> <span class="kn">import</span> <span class="n">euclidean_distance</span><span class="p">,</span> <span class="n">msm_distance</span><span class="p">,</span> <span class="n">sbd_distance</span>

<span class="n">rng</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">random</span><span class="p">.</span><span class="n">default_rng</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">rng</span><span class="p">.</span><span class="n">normal</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">100</span><span class="p">))</span>  <span class="c1"># 3 channels, 100 time points
</span><span class="n">y</span> <span class="o">=</span> <span class="n">rng</span><span class="p">.</span><span class="n">normal</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">100</span><span class="p">))</span>

<span class="c1"># Lock-step: Euclidean over all channels and time points.
# Channel-independent and channel-dependent variants are identical here.
</span><span class="n">d_lock</span> <span class="o">=</span> <span class="n">euclidean_distance</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>

<span class="c1"># Elastic: Move-Split-Merge. independent=True gives MSM-I, the variant
# the study recommends when accuracy matters. c is the split/merge cost;
# c=0.5 was the default that worked best across the UEA archive.
</span><span class="n">d_msm_i</span> <span class="o">=</span> <span class="n">msm_distance</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="mf">0.5</span><span class="p">,</span> <span class="n">independent</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="n">d_msm_d</span> <span class="o">=</span> <span class="n">msm_distance</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="mf">0.5</span><span class="p">,</span> <span class="n">independent</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span>

<span class="c1"># Sliding: aeon's multivariate SBD averages per-channel SBD, so this is
# SBD-I. For SBD-D (one shift shared by all channels, computed with a 2D
# FFT) see the MTSDistEval repository linked above.
</span><span class="n">d_sbd_i</span> <span class="o">=</span> <span class="n">sbd_distance</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">standardize</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span>
</code></pre></div></div>

<p>Note the <code class="language-plaintext highlighter-rouge">standardize=False</code>: aeon z-scores each series inside <code class="language-plaintext highlighter-rouge">sbd_distance</code> by default, which is exactly the normalization the study found no benefit from on multivariate data.</p>

<h2 id="where-to-go-next">Where to go next</h2>

<ul>
  <li>The full paper: <a href="/publication/sigmod_2025">A Structured Study of Multivariate Time-Series Distance Measures</a>, SIGMOD 2025, <a href="https://doi.org/10.1145/3725258">doi:10.1145/3725258</a>. The guidelines are in Section 6.</li>
  <li>The earlier, smaller version: <a href="/publication/icde_jens_talk">Beyond the Dimensions</a>, ICDE 2024 MulTiSa workshop. That study compared 12 measures on the UEA archive and found no single winner; the SIGMOD paper is what happened when we added the missing families, normalizations, tasks, and statistics.</li>
  <li>Background reading: <a href="/publication/book_chapter_2024">A Survey on Time-Series Distance Measures</a>, covering the 100+ measures and 7 categories the study draws from.</li>
</ul>

<h2 id="cite-this">Cite this</h2>

<div class="language-bibtex highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">@article</span><span class="p">{</span><span class="nl">dhondt2025structured</span><span class="p">,</span>
  <span class="na">author</span>    <span class="p">=</span> <span class="s">{d'Hondt, Jens E. and Li, Haojun and Yang, Fan and Papapetrou, Odysseas and Paparrizos, John}</span><span class="p">,</span>
  <span class="na">title</span>     <span class="p">=</span> <span class="s">{A Structured Study of Multivariate Time-Series Distance Measures}</span><span class="p">,</span>
  <span class="na">journal</span>   <span class="p">=</span> <span class="s">{Proceedings of the ACM on Management of Data}</span><span class="p">,</span>
  <span class="na">volume</span>    <span class="p">=</span> <span class="s">{3}</span><span class="p">,</span>
  <span class="na">number</span>    <span class="p">=</span> <span class="s">{3}</span><span class="p">,</span>
  <span class="na">articleno</span> <span class="p">=</span> <span class="s">{121}</span><span class="p">,</span>
  <span class="na">pages</span>     <span class="p">=</span> <span class="s">{1--29}</span><span class="p">,</span>
  <span class="na">year</span>      <span class="p">=</span> <span class="s">{2025}</span><span class="p">,</span>
  <span class="na">month</span>     <span class="p">=</span> <span class="nv">jun</span><span class="p">,</span>
  <span class="na">publisher</span> <span class="p">=</span> <span class="s">{Association for Computing Machinery}</span><span class="p">,</span>
  <span class="na">doi</span>       <span class="p">=</span> <span class="s">{10.1145/3725258}</span>
<span class="p">}</span>
</code></pre></div></div>]]></content><author><name>Jens E. d&apos;Hondt, PhD</name><email>jens.dhondt@bsc.es</email></author><category term="time series" /><category term="distance measures" /><category term="similarity search" /><summary type="html"><![CDATA[A practical guide to picking a distance measure for multivariate time series, based on our SIGMOD 2025 study of 30 measures on 30 datasets.]]></summary></entry></feed>