Python 3.12 / TensorFlow 2.16+ (Keras 3) Support#194
Open
warptengood wants to merge 1 commit into
Open
Conversation
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
Adds support for Python 3.12 and modern dependency versions (TensorFlow >= 2.16,
which ships Keras 3, NumPy >= 1.21, SciPy >= 1.7, librosa >= 0.10). Drops end‑of‑life
Python 3.8/3.9. All tox environments pass on Python 3.10, 3.11, and 3.12.
The work spans four areas:
tensorflow-macos.Keras 3 changed or removed.
on TF >= 2.16 inference defaults to the bundled TFLite model, served by the modern
ai-edge-litertruntime.CI matrix updated.
Motivation
< 2.15.1,which has no Python 3.12 wheels. TensorFlow 2.16 is the first release with 3.12
support -- but it also makes Keras 3 the default, which is not API‑compatible with the
Keras 2 code the project was written against.
tensorflow-macoshas been deprecated since TF 2.13; Apple‑silicon users now install thestandard
tensorflowpackage.Key Decisions
1. Default to the TFLite model on TF >= 2.16 (instead of the TF SavedModel)
The bundled ICASSP‑2022 SavedModel (
saved_models/icassp_2022/nmp) is a legacyTF2 / Keras‑2 export containing optimizer slot variables. Loading it under TF 2.16+
fails with
AttributeError: '_UserObject' object has no attribute 'add_slot'-- anunfixable‑in‑place artifact incompatibility.
The repo already ships the same model as TFLite, CoreML, and ONNX. The TFLite file
loads cleanly under new TF and its signature matches exactly (input
input_2; outputscontour/note/onset), sopredict()works unchanged.Decision: select the default model format by TF version -- SavedModel on TF < 2.16
(Keras 2), TFLite on TF >= 2.16 (Keras 3). This keeps Python 3.10/3.11 behavior identical
and gives 3.12 a working, numerically‑equivalent path. Re‑exporting the SavedModel in a
Keras‑3 format was rejected as much heavier and risking numerical drift.
2. Serve TFLite via
ai-edge-litert, nottensorflow.liteOn Python 3.12 there is no
tflite_runtimewheel, so the TFLite path would fall back totensorflow.lite.Interpreter, which emits a deprecation warning (scheduled for deletion in TF 2.20; use LiteRT from ai_edge_litert).ai-edge-litertis Google's supportedsuccessor and loads the model identically.
Decision: prefer
ai-edge-litertwhentflite_runtimeis absent, falling back totensorflow.liteonly if neither is installed. Added as a dependency for non‑Windows,Python 3.12+ (where it has wheels and is the default backend).
3. Use
keras.opsfor symbolic ops, not a custom wrapper layerKeras 3 forbids calling raw TensorFlow ops (e.g.
tf.expand_dims) directly on a symbolicKerasTensorduring functional model construction.keras.ops.expand_dimsis thebackend‑agnostic replacement and is valid on
KerasTensors. Keras 2 has nokeras.ops,but raw
tf.expand_dimsworks there and shares the same(x, axis)signature.Decision: alias
keras_ops = tf.keras.ops if hasattr(tf.keras, "ops") else tfand callkeras_ops.expand_dims(...). One line, no new layer class, works on both Keras 2 and 3.4. Declare
tensorboardexplicitlyTensorFlow 2.21 no longer pulls in
tensorboardtransitively, but the training /visualization path uses
tf.summary.audio(provided by tensorboard). Addedtensorboard>=2.4.1to thetfextra so training/visualization works out of the box.5. Drop Python 3.8 / 3.9 entirely
Both are EOL.
requires-pythonis now>=3.10; classifiers, the tox envlist, and the CImatrix were trimmed accordingly. This is a breaking change for anyone on 3.8/3.9.
6. Do not silence upstream deprecation warnings
The remaining warnings originate in third‑party packages that are already at their latest
versions (see Known Remaining Warnings). Rather than filter them, they are left visible
and documented; there is no version bump that resolves them.
Full Changelog
Packaging & Python support (
pyproject.toml)requires-python = ">=3.10".3.8,3.9; added3.12.tensorflow-macos(deprecated since TF 2.13); macOS now usestensorflow.tensorflow>=2.4.1,<2.16.0for non‑Darwin, Python 3.11 (Keras 2).tensorflow>=2.16.0for non‑Darwin, Python 3.12+ (Keras 3).tensorflow>=2.13.0for macOS, Python 3.12+.ai-edge-litert(non‑Windows, Python 3.12+).tensorboard>=2.4.1to thetfextra.librosa>=0.8.0->>=0.10.0numpy>=1.18->>=1.21scipy>=1.4.1->>=1.7.0resampy>=0.2.2,<0.4.3->>=0.2.2(upper pin removed)Keras 3 compatibility (source)
basic_pitch/models.py--tf.expand_dims(...)on symbolic tensors ->keras_ops.expand_dims(...)(via the
keras_ops = tf.keras.ops if hasattr(tf.keras, "ops") else tfalias). Affected theCQT input branch and the reduced‑contour -> notes branch.
basic_pitch/layers/signal.py--input_shape.rank->len(input_shape)(Keras 3 passesbuild()a plain tuple, which has no.rank). Two call sites (Stft.build,NormalizedLog.build).basic_pitch/nn.py-- removedimport tensorflow.keras.backend as K; replaced the removedK.int_shape(x)withx.shape(FlattenAudioCh,FlattenFreqCh).basic_pitch/train.py-- dropped thesample_weight_mode=...argument tomodel.compile()(removed in Keras 3; the value was all‑
None, i.e. the default, so behavior is unchanged).Inference backend
basic_pitch/__init__.py-- default model format is now chosen by TF version:SavedModel (
nmp) on TF < 2.16, TFLite (nmp.tflite) on TF >= 2.16.basic_pitch/inference.py-- TFLite import order is nowtflite_runtime->ai_edge_litert->tensorflow.lite.Tests
tests/test_nn.py-- removed the now‑invalidsample_weight_mode=Nonefrom bothcompile()calls.tests/test_callbacks.py--vc.model = MockModel()->vc.set_model(MockModel())(Keras 3 makes
Callback.modela read‑only property;set_model()works on both Keras 2 and 3).tests/test_inference.py--librosa.get_duration(filename=...)->path=...(renamed in librosa 0.10; old kwarg raised a
FutureWarning).tests/data/conftest.py-- fixture decorator type‑ignores updated from[misc]to[untyped-decorator]to match the current mypy/pytest typing.Tooling & CI
tox.ini-- envlist nowpy310,py311,py312,...;fullanddataenvs pinned topython3.12; lint/format/mypy envs moved topython3.12;blackinvoked with--target-version py312..github/workflows/tox.yml-- CI Python matrix is now3.12, 3.11, 3.10(3.8/3.9 removed),plus a macOS 3.12 job.
README.md-- compatibility line now lists Python3.10, 3.11, 3.12.Behavioral & Compatibility Notes
load the TF SavedModel by default.
existing
test_predictasserts the TFLite output matches the committed reference(
vocadito_10/model_output.npz) toatol=1e-4.predict()and the public API are unchanged. Backend selection is internal.Testing & Verification
All tox environments pass on this machine (3.10/3.11/3.12 installed; 3.8/3.9 removed):
The CI matrix is what proves the migration: the same test suite runs under two genuinely
different stacks, so both code paths are exercised end‑to‑end:
ai-edge-literttest_predicton 3.12 runs entirely through the TFLite path and checks numericalequivalence against the reference output, so no new tests were required.
Known Remaining Warnings (upstream, not fixable by version bump)
audioreaddeprecation warnings (aifc/audioop/sunau): emitted fromaudioread/rawread.py.librosa 0.11.0andaudioread 3.1.0are both the latestreleases; the deprecated‑stdlib imports are hard‑coded upstream (PEP 594 removes those
modules in Python 3.13). No release currently fixes this.
apache_beamPytestCollectionWarningfor itsTestPipelineclass (data tests only):cosmetic, originates in apache‑beam's class naming.
These were intentionally left visible rather than filtered.