Conversation
export(format="tflite", int8=True, data=...) now runs onnx2tf post-training quantization instead of rejecting the request, and returns the fully integer artifact. Calibration batches are the model's own preprocessed tensors, so onnx2tf is told not to normalize them again. The integer path runs on the tf_converter backend: flatbuffer_direct aborts on any op it cannot keep in int8 end to end, which YOLO9 hits on EQUAL. FP32 export keeps flatbuffer_direct unchanged.
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.
Requested by a user on LinkedIn: YOLOX trained in LibreYOLO,
export --format tflite --int8returned "TFLite INT8 quantization is not supported yet". A GitHub feature request is coming from them separately.What changed
TFLiteExporter.supports_int8 = True; the hard rejection in_validateis gone.export_tflite()takesint8andcalibration_dataand appends-oiqt -cind <input> <calib.npy> 0.0 1.0to the onnx2tf command.CalibrationDataLoader, written out as one NHWC float32.npythrough a memmap. Batch padding is trimmed so no image is weighted twice.(value - mean) / std, and those batches already went through the model's own preprocessing. Any other value calibrates the wrong ranges.tf_converterbackend.flatbuffer_directrefuses strict full-integer quantization on any op it cannot keep in int8 end to end and YOLO9 hits that onEQUAL. FP32 export still usesflatbuffer_direct, unchanged.*_full_integer_quant.tflite, falling back to*_integer_quant.tflite. It never falls back to a float artifact: that would hand back FP32 bytes under int8 metadata.data=is mandatory (default_int8_calibration_data = False, same as TensorRT and OpenVINO). An eight-image default would produce a quietly wrong full-integer graph.NotImplementedErrorfor int8. That family converts through the Python API with a bespoke GridSample fixup that this path was not run against. Its FP32 tflite entry is blocked in the support matrix anyway.No CLI change needed,
--int8 --dataalready plumbed through.Coverage
INT8 is gated on the existing per-family FP32 tflite support entry, so INT8 coverage equals FP32 coverage minus
rfdetr. Today that means 2 of the 13 G0/G1 families:Outside G0/G1, INT8 also becomes callable on every other family whose tflite entry is already validated:
yolox,convnext,efficientnetv2,mobilenetv4,resnet,siglip2(classify and embed),dinov2(embed),pidnet,dexined,teed,realesrgan,swinir. YOLOX is the family the original request came from.What we want: TFLite and TFLite INT8 for every G0 and G1 model
The target is not a wishlist. Every G0 and G1 family should have both FP32 TFLite and TFLite INT8, and the only acceptable reason for a family to be missing is that it is genuinely impossible to lower, not that nobody tried. RF-DETR is explicitly in scope: it is a flagship and it should run on TFLite.
Worth stating plainly, because it is the assumption that would otherwise excuse the DETR line: deformable attention is not what is blocking these families. RF-DETR's GridSample already has a working TFLite rewrite in
libreyolo/export/tflite.py, and its FP32 block is a LiteRT allocation failure on STRIDED_SLICE at the 384x384 canvas. The D-FINE line is blocked on GatherElements and CONCATENATION. Those are converter and allocator defects, not an inherent limit of the architecture.Ordered by expected difficulty:
11 of the 13 have no working TFLite path at any precision, so this is FP32 unblocking work first and INT8 second. It is a separate body of work from this PR, not something this PR narrowed. If a family turns out to be truly unlowerable, that should be recorded as a specific converter or runtime defect with evidence, not left as an unexplained blocked entry.
A probe is running now over the blocked families: FP32 ONNX, converted with both onnx2tf backends on 2.6.8, then checked for LiteRT allocate and invoke. Results will be posted here and will say which of tiers 2 and 3 are actually reachable.
Verified
Real run, YOLO9-t at 640, onnx2tf 2.6.8 + LiteRT 2.1.2, random-init weights on synthetic images:
_full_integer_quant.tflite, sidecarprecision: int8LibreYOLO(artifact)loads and runs it with no backend change:TFLiteBackend._quantize/_dequantizealready handled quantized IO26 unit tests in
tests/unit/test_export_tflite.pypass, plustest_export.pyandtest_export_support.py(229 passed, 3 skipped). Full CI green.Not verified
val()sweep is the follow-up before any support-matrix claim./docs.Reviewer notes
tf_converterbackend switch are the two things worth a close look; both are load-bearing and both are covered by tests.onnxsim. Without it on PATH the INT8 backend fails with an unrelated-looking Keras error, so the code warns up front and adds a hint to the failure message. Worth deciding whether that should instead be a hard preflight check.Code provenance
All code in this PR was written for this PR. No third-party code was copied, adapted, or derived. The change drives the existing
onnx2tfdependency (Apache-2.0, already declared in thetfliteextra) through its documented-oiqt/-cindcommand-line interface; no onnx2tf source was vendored or reimplemented.Opened by an agent. It ran the tests and the conversion above; it did not review or approve the change.