tcn-ae
A temporal convolutional autoencoder for anomaly detection in multivariate time series.
This is a reference implementation of:
Markus Thill, Wolfgang Konen, Hao Wang, Thomas Bäck. Temporal convolutional autoencoder for unsupervised anomaly detection in time series. Applied Soft Computing 112 (2021), 107751.
[!NOTE] Early development — the package is being built up step by step and the public API is not stable yet.
Installation
pip install tcn-ae
This installs Keras with the TensorFlow backend, matching the paper's original implementation.
Keras 3 is multi-backend, so PyTorch can be used instead:
pip install "tcn-ae[torch]"
KERAS_BACKEND=torch python your_script.py
TensorFlow is a required dependency rather than an extra, so tcn-ae[torch] installs both.
To make the backend choice permanent, set "backend": "torch" in ~/.keras/keras.json.
There is one implementation, written against the Keras 3 API — the backend is chosen at install and run time, not by a separate code path.
Documentation
https://markusthill.github.io/tcn-ae/
Citing
If you use this software, please cite the paper above. GitHub reads CITATION.cff, so the "Cite this repository" button produces BibTeX for both the software and the paper.
Development
The project uses uv for environments and packaging. In a Codespace or devcontainer everything below is already provisioned by .devcontainer/post-create.sh.
uv sync # create .venv from uv.lock, incl. the dev group
uv run prek install --hook-type pre-commit --hook-type commit-msg
The dev interpreter is pinned to Python 3.13 (.python-version). The package supports
Python 3.11+, which is what CI's matrix exercises — keep those two numbers distinct.
Everyday commands
| Task | Command |
|---|---|
| Run tests | uv run pytest |
| Tests with coverage gate | uv run pytest --cov |
| Lint | uv run ruff check . |
| Format | uv run ruff format . |
| Type check | uv run pyrefly check |
| Workflow security lint | uv run zizmor .github/workflows |
| Docs preview | uv run --group docs zensical serve |
| Docs build | uv run --group docs zensical build |
Type checking
pyrefly is the authority and gates CI and commits.
ty is also installed and can be run with
uv run ty check, but it is experimental and advisory only — it never blocks a commit or
a build, and where the two disagree, pyrefly wins.
Git hooks (prek)
Hooks are managed by prek, a drop-in replacement for
pre-commit that reads the same .pre-commit-config.yaml.
uv run prek run --all-files # run every hook against the whole repo
uv run prek auto-update # bump pinned hook revisions
On commit this runs file hygiene checks, ruff check --fix, ruff format, pyrefly,
nbstripout (strips notebook outputs), and zizmor. On commit-msg it validates the
message with commitizen.
Commits and releases (commitizen)
Commit messages follow Conventional Commits and are
enforced by the commit-msg hook. Use the prompt if you like:
uv run cz commit # interactive, guided commit message
uv run cz bump # bump version, update CHANGELOG.md, create the v* tag
git push --follow-tags
cz bump derives the new version from the commits since the last tag, writes it to
[project] version in pyproject.toml and to uv.lock (version_provider = "uv"), and
updates CHANGELOG.md. The package exposes that same version at runtime via
importlib.metadata, so there is a single source of truth — do not switch back to a
dynamic/hatch version, it would break cz bump.
Pushing the tag triggers .github/workflows/release.yml, which builds, publishes to PyPI via Trusted Publishing (OIDC — no API token is stored), and creates the GitHub release.
[!WARNING]
annotated_tag = truein[tool.commitizen]is load-bearing.git push --follow-tagspushes annotated tags only, and commitizen creates lightweight ones by default. Without it the bump commit is pushed, the tag silently stays local, and no release ever runs. If you change it, push tags explicitly withgit push origin "v$(uv run cz version --project)".
Publishing setup (one-time)
Both registries use Trusted Publishing, so no API token is ever stored. PyPI supports pending publishers, meaning the project does not have to exist yet.
On pypi.org and test.pypi.org — separate sites needing separate accounts, both with 2FA — go to Publishing → Add a pending publisher:
| Field | PyPI | TestPyPI |
|---|---|---|
| PyPI project name | tcn-ae |
tcn-ae |
| Owner | MarkusThill |
MarkusThill |
| Repository | tcn-ae |
tcn-ae |
| Workflow | release.yml |
release-testpypi.yml |
| Environment | pypi |
testpypi |
Then create matching GitHub environments under Settings → Environments, and enable Pages with "GitHub Actions" as the source.
Rehearsing a release on TestPyPI
TestPyPI exists purely to prove the procedure works before it matters. Run
release-testpypi.yml manually from the Actions tab;
it exercises the same build → twine check → OIDC publish path as a real release.
It does not cover the tag trigger, cz bump, or GitHub release creation — those only run
in release.yml.
Optional, if verifying the upload is installable: an extra index is required, because
TestPyPI's own tensorflow stops at 1.0.0 and keras at 2.0.0.
pip install --index-url https://test.pypi.org/simple/ \
--extra-index-url https://pypi.org/simple/ tcn-ae
Notebooks
Notebooks in notebooks/ are executed in CI with
nbmake so the examples cannot silently rot:
uv run pytest --nbmake notebooks/
Outputs are stripped on commit by nbstripout, so keep notebooks free of large embedded
results in git.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tcn_ae-0.0.2.tar.gz.
File metadata
- Download URL: tcn_ae-0.0.2.tar.gz
- Upload date:
- Size: 150.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
45796562f2928f81cb79ff72763667a583e612fc68d52fcce04fc1f1a2eaccf0
|
|
| MD5 |
21e024559f2deea07711afd716ecb881
|
|
| BLAKE2b-256 |
3423a46acfd8442ab93c92f6ec4bce9d920941a39d93a99bee316018670c0667
|
Provenance
The following attestation bundles were made for tcn_ae-0.0.2.tar.gz:
Publisher:
release.yml on MarkusThill/tcn-ae
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tcn_ae-0.0.2.tar.gz -
Subject digest:
45796562f2928f81cb79ff72763667a583e612fc68d52fcce04fc1f1a2eaccf0 - Sigstore transparency entry: 2328658897
- Sigstore integration time:
-
Permalink:
MarkusThill/tcn-ae@b3d7d270d9cfb1f3df0fa1137c65dc5ef8dc9c6d -
Branch / Tag:
refs/tags/v0.0.2 - Owner: https://github.com/MarkusThill
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b3d7d270d9cfb1f3df0fa1137c65dc5ef8dc9c6d -
Trigger Event:
push
-
Statement type:
File details
Details for the file tcn_ae-0.0.2-py3-none-any.whl.
File metadata
- Download URL: tcn_ae-0.0.2-py3-none-any.whl
- Upload date:
- Size: 5.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
18648fac855e82f5c2f07093a9b6e04ea5569f19348e79cc2f9ec446b351b265
|
|
| MD5 |
f46a13a54192226d29273bb70abe61c8
|
|
| BLAKE2b-256 |
b3177297bf615360da263d7f24fc6be87d6a4c88ae584512bab042bdc34c5ed3
|
Provenance
The following attestation bundles were made for tcn_ae-0.0.2-py3-none-any.whl:
Publisher:
release.yml on MarkusThill/tcn-ae
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tcn_ae-0.0.2-py3-none-any.whl -
Subject digest:
18648fac855e82f5c2f07093a9b6e04ea5569f19348e79cc2f9ec446b351b265 - Sigstore transparency entry: 2328659180
- Sigstore integration time:
-
Permalink:
MarkusThill/tcn-ae@b3d7d270d9cfb1f3df0fa1137c65dc5ef8dc9c6d -
Branch / Tag:
refs/tags/v0.0.2 - Owner: https://github.com/MarkusThill
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b3d7d270d9cfb1f3df0fa1137c65dc5ef8dc9c6d -
Trigger Event:
push
-
Statement type: