Skip to content

Ajb/tde notebook - #3765

Draft
TonyBagnall wants to merge 46 commits into
mainfrom
ajb/tde_notebook
Draft

Ajb/tde notebook#3765
TonyBagnall wants to merge 46 commits into
mainfrom
ajb/tde_notebook

Conversation

@TonyBagnall

Copy link
Copy Markdown
Contributor

holder for TDE notebook

TonyBagnall and others added 30 commits July 9, 2026 10:55
- SFA._transform_case: build whole word bags in single njit calls
  (_create_bag_flat/_create_bag_pyramid) instead of per-window typed
  Dict operations from Python
- TDE nearest neighbour: convert bags once to sorted key/value arrays
  and compute histogram intersections with numba merge kernels instead
  of per-pair dict lookups
- SFA._mcb: vectorise rounding; SFA._binning_dft: replace
  linspace/np.split with direct slicing
- TDE fit 12.8s -> 1.5s on a 120x250 benchmark, outputs verified
  bit-identical across univariate/multivariate, levels 1-3, IGB/MCB,
  typed/untyped, loocv train estimates

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- loocv_train_acc: whole LOOCV in one numba call computing each
  symmetric pair intersection once (upper triangle), preserving the
  sequential early-abandon semantics; used by _individual_train_acc
  and _select_dims
- replace StandardScaler + KernelRidge parameter selection with the
  same computation in plain numpy (_kernel_ridge_preds), and keep a
  float array mirror of the candidate parameters instead of
  re-converting the list every iteration
- trig lookup tables (cos/sin of (n*i) mod w) in _binning_dft_all and
  the first-window DFT of _mft_all, removing all per-term trig calls
- predict: one nn_similarities_all call per member for all test cases
  instead of a joblib task per case, and lazy tie-break rng
  construction (seeding a RandomState per test case dominated predict)
- _combine_dim_bags: numba k-way merge of the already-sorted
  per-dimension bags instead of per-case double stable argsorts

Evaluated and rejected: flat levels==1 NN kernels (~6% kernel gain
only) and an ensemble-level per-window DFT cache (slower at both 40
and 250 parameter samples once the trig tables landed).

Benchmark (120x250 univariate 40 members / BasicMotions 10 members):
uni fit 703 -> 234 ms, uni predict 686 -> 449 ms, mv fit 147 -> 55 ms,
mv predict 36 -> 21 ms. Outputs verified identical on univariate and
multivariate train/test probabilities; all TDE, expected-output,
ordinal and estimator-check suites pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- fix typos (lcoefficients, TemporalDictinaryEnsemble, 'to use to use',
  contacting, para space, each dimensions) and call histogram
  intersection a similarity rather than a distance
- update the typed_dict parameter descriptions: it has no effect on
  newly fitted models and is retained for unpickling older models
- deprecate IndividualTDE alphabet_size (fixed to 4 by the new SFA,
  other values ignored): docstring .. deprecated:: note plus a
  DeprecationWarning in fit when a non-default value is used, removal
  targeted for v1.7.0

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Rework the earlier deprecations to match
docs/developer_guide/deprecation.md: sentinel 'deprecated' defaults, a
FutureWarning raised in __init__ only when a value is passed, TODO
removal comments for v1.7.0, and plain docstring deprecation notes.
The ensemble no longer forwards either parameter to its members, and
the unused _alphabet_size attribute is removed.

Also correct the parameter selection description: TDE uses kernel
ridge regression (the reference paper describes this step as a
Gaussian process regressor).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- test_tde.py: cover the loocv train estimate path plus ensemble
  predict/predict_proba, the deprecated alphabet_size/typed_dict
  FutureWarnings, numerical equivalence of the numpy kernel ridge
  helper with sklearn StandardScaler + KernelRidge, and agreement of
  the per-case LOOCV fallback with the symmetric kernel (via the new
  _SYMMETRIC_LOOCV_MAX_N constant); pickle test now also checks
  predictions survive the round trip and no longer passes the
  deprecated typed_dict; multivariate test made deterministic with
  dim_threshold=0
- test_tde_sfa.py: direct tests for loocv_train_acc (hand-checked
  predictions, accuracy count and the early-abandon sentinel),
  nn_similarities_all (full test x train matrix) and combine_dim_bags
  (levels > 1 key shifting including the -1 bigram tag, and flat
  dimension tagging)
- remove the now-unused nn_similarities kernel (superseded by
  nn_similarities_all)

Coverage with NUMBA_DISABLE_JIT=1: _tde_sfa.py 99% (0 lines missed),
_tde.py 55% with remaining gaps confined to legacy typed-Dict pickle
paths and branches exercised by the global estimator checks.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- test_tde.py: module and per-test docstrings now state what behaviour
  each test pins down and why (oob voting, validation/correction on
  fit, histogram intersection input types, imbalanced subsampling)
- _tde_sfa.py: standard aeon header with __maintainer__ and __all__
- TonyBagnall and MatthewMiddlehurst added as maintainers of both TDE
  modules

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Models pickled with aeon <= 1.5 could not be used with the rewritten
TDE anyway (verified: predict fails on an unpickled old model because
the old SFA transformer output format is no longer handled), so the
code retained for that path was dead:

- __getstate__/__setstate__ typed Dict conversions (array bags pickle
  natively), the _typed_dict attribute and the _bags_cache /
  _get_bag_arrays conversion cache
- the Dict-bag branches of _predict, _train_predict and
  _individual_train_acc, the _test_nn method and the joblib threading
  branch they used
- the eight module-level legacy numba kernels (_bags_to_arrays_*,
  _intersection_*, _nn_index_*, _histogram_intersection_to_all_*)
- the now-unused _is_tde_sfa_bags helper and os/joblib/NumbaList
  imports

The typed_dict parameter docstrings no longer claim old models can be
unpickled. histogram_intersection and its numba helper are kept: they
are public API used by OrdinalTDE and the tests. All test lanes pass
(jit and no-jit), estimator checks pass, and a multivariate pickle
round trip is prediction-identical.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- nogil=True on the predict-path numba kernels: plain njit holds the
  GIL, so the previous joblib threading could never scale
- TemporalDictionaryEnsemble._predict_proba threads members' _predict
  calls (X validated once by the public wrapper); results gathered in
  member order so probabilities are identical for any n_jobs
- IndividualTDE._predict chunks test cases across threads, stacking
  chunk similarity matrices in order
- tie-breaking moved off the hot path exactly: with an integer seed
  every case's fresh RandomState yields the same draw sequence, so one
  precomputed pool + the nn_tie_break kernel resolves all cases in
  numba; unseeded generators keep the sequential python walk but only
  for rows nn_first_max flags as having tie events. This removes ~2000
  GIL-bound RandomState seedings per predict, cutting single-threaded
  predict 495 -> 207 ms on the 120x250 benchmark and letting threads
  scale: 76 ms at n_jobs=2, ~70 ms at n_jobs=8 (7x vs the previous
  sequential predict)
- ensemble members are constructed single threaded (the ensemble owns
  predict parallelism); n_jobs docstrings state fit is single threaded
- new tests: n_jobs equivalence for both classes and unit tests for
  nn_first_max/nn_tie_break; the framework multithreading checks
  (including the MULTITHREAD_TESTING-gated results comparison) pass

Outputs verified identical to the sequential implementation on the
univariate and multivariate snapshots.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
References the TDE paper and describes TDE's role as the dictionary
based component of HIVE-COTE 2.0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Repair the mangled intro sentence, defer the merge mechanics to the
comparison section instead of pre-explaining them in the motivation,
explain why the standalone transform can stand in for the classifier's
in the by-hand prediction, rename the LOOCV reproduction variables to
avoid clashing with the prediction ones, trim the overlapping channel
selection segue and remove a leftover part-number reference.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts:
#	aeon/classification/dictionary_based/_tde.py
@review-notebook-app

Copy link
Copy Markdown

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@aeon-actions-bot aeon-actions-bot Bot added classification Classification package examples Example notebook related labels Aug 28, 2026
@aeon-actions-bot

Copy link
Copy Markdown
Contributor

Thank you for contributing to aeon

I did not find any labels to add based on the title. Please add the [ENH], [MNT], [BUG], [DOC], [REF], [DEP] and/or [GOV] tags to your pull requests titles. For now you can add the labels manually.
I have added the following labels to this PR based on the changes made: [ classification, examples ]. Feel free to change these if they do not properly represent the PR.

The Checks tab will show the status of our automated tests. You can click on individual test runs in the tab or "Details" in the panel below to see more information if there is a failure.

If our pre-commit code quality check fails, please run pre-commit locally and push the fixes to your PR branch.

Don't hesitate to ask questions on the aeon Discord channel if you have any.

PR CI actions

These checkboxes will add labels to enable or disable CI functionality for this PR. This may not take effect immediately, and a new commit may be required to run the new configuration.

  • Run pre-commit checks for all files
  • Run mypy typecheck tests
  • Run all pytest tests and configurations
  • Run all notebook example tests
  • Run numba-disabled codecov tests
  • Disable numba cache loading
  • Regenerate expected results for testing
  • Push an empty commit to re-run CI checks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

classification Classification package examples Example notebook related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant