Repository navigation
Fix TensorFlow/Keras 3 compatibility for exported .h5 models - #13
Merged
Merged
Conversation
Teachable Machine's exported .h5 models embed a legacy DepthwiseConv2D
layer config ('groups': 1) that current Keras (Keras 3, bundled by
default since TensorFlow >= 2.16) rejects during deserialization:
TypeError/ValueError: Unrecognized keyword arguments passed to
DepthwiseConv2D: {'groups': 1}
This has broken `pip install teachable-machine` on any current
TensorFlow install since setup.py never pinned an upper/lower bound.
Fixes #2.
- Add a _CompatDepthwiseConv2D shim passed via custom_objects in
load_model(), so exported models load on current TF/Keras without
pinning an old TensorFlow version.
- Add regression tests: a direct unit test for the shim, and an
end-to-end test that builds a model, tampers its saved .h5 config to
reproduce Teachable Machine's legacy shape, and verifies it still
loads and classifies. Verified both that it fails without the fix
and passes with it, against a real TensorFlow 2.21.0 install.
- Bump install_requires to tensorflow>=2.16; raise python_requires to
>=3.9 to match current TensorFlow's supported range; refresh the
(previously stale, UTF-16 encoded) requirements.txt.
- Bump version to 1.3.0; add CHANGELOG.md (mirrored into docs site).
- Update README and docs site with a compatibility note and the new
Python requirement.
- Add GitHub Actions workflows: run tests on push/PR across Python
3.10-3.13, and publish to PyPI via Trusted Publishing when a GitHub
Release is published.
Contributor
|
|
Overall Grade |
Security Reliability Complexity Hygiene |
Code Review Summary
| Analyzer | Status | Updated (UTC) | Details |
|---|---|---|---|
| Python | Sep 12, 2026 5:57p.m. | Review ↗ |
Important
AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.
Docs deployment was entirely manual: someone runs mkdocs build locally and commits the compiled HTML into a separate `documentation` branch's /docs folder, which legacy GitHub Pages serves from. That branch hasn't been touched since Aug 2024, so the live docs site predates this PR's changes (and everything else merged to main since). This workflow builds the site with mkdocs on every push to main that touches docs/mkdocs.yml/src, and deploys it via actions/deploy-pages. Verified `python -m mkdocs build` locally: mkdocstrings correctly renders the TeachableMachine class API docs (confirms tensorflow/numpy/ PIL imports resolve during the build), no warnings. Requires a one-time manual step (documented in the workflow's comments): switch the repo's Pages source from "Deploy from a branch" to "GitHub Actions" in Settings -> Pages.
show_prediction_on_image() had two latent bugs that surface together on
Windows with recent Pillow:
- ImageFont.truetype("DejaVuSans-Bold.ttf", ...) assumes that font is
resolvable by bare name, which only holds on platforms where Pillow's
bundled test font happens to be on the search path. On Windows it raises
OSError: cannot open resource. Now falls back to
ImageFont.load_default(size=...) when the named font can't be found.
- ImageDraw.textsize() was removed in Pillow 10.0.0 (this repo pulls
Pillow 12.x), so the very next line would raise AttributeError once the
font issue above is fixed. Replaced with textbbox(), which returns the
same width/height via the bounding box.
textbbox()'s (left, top, right, bottom) are offsets from the point passed in, and that offset -- particularly `top`, coming from font ascent -- is usually not zero. The rectangle was built by measuring the text's extent at the origin (0, 0) and then reusing that width/height as if the glyphs started exactly at `position`, which shifts the box up and clips the bottom of descenders (e.g. "g", "%"). Re-measure the bbox at the actual draw position instead, and pad it by a few pixels so the highlight comfortably covers the text.
MeqdadDev
added this pull request to stack #15
September 12, 2026 17:50
Fix annotation crash: missing font on Windows + removed Pillow API
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #2. Teachable Machine's exported
.h5models embed a legacyDepthwiseConv2Dlayer config ('groups': 1) that current Keras (Keras 3, bundled by default since TensorFlow >= 2.16) rejects during deserialization:Since
setup.pynever pinned an upper/lower bound ontensorflow,pip install teachable-machinecurrently pulls the latest TensorFlow and breaks out of the box for the package's core (and only) use case.Changes
_CompatDepthwiseConv2Dshim passed viacustom_objectsinload_model(), so exported models load correctly on current TF/Keras without requiring users to pin an old TensorFlow version..h5config to reproduce Teachable Machine's legacy shape, and verifies it loads/classifies correctly. Confirmed the new test fails without the fix and passes with it, against a real TensorFlow 2.21.0 install.install_requiresnow specifiestensorflow>=2.16;python_requiresraised to>=3.9(matches current TensorFlow's supported Python range); refreshed the stale (UTF-16 encoded,2.12.0rc0-pinned)requirements.txt.1.3.0; addedCHANGELOG.md(also mirrored into the docs site nav).docs/index.md,docs/requirements.md) get a new "Compatibility with recent TensorFlow/Keras releases" section and the updated Python requirement..github/workflows/tests.ymlruns the test suite on push/PR across Python 3.10-3.13;.github/workflows/publish.ymlpublishes to PyPI via Trusted Publishing when a GitHub Release is published (setup instructions in the workflow's comments — needs a one-time trusted publisher added on PyPI before it will work).Verification
Ran the full suite against a clean venv with TensorFlow 2.21.0 (latest as of this PR): all 8 tests pass. Verified the new regression test fails with the pre-fix loader (reproducing the exact error from #2) and passes with the fix.
🤖 Generated with Claude Code