An extensible CLI and Python package for exporting timm models to various deployment formats. Born out of having too many one-off export scripts for fine-tuned timm models — timmx unifies them behind a single command-line interface with a plugin-based backend system.
| Format | Command | Output |
|---|---|---|
| ONNX | timmx export onnx |
.onnx |
| Core ML | timmx export coreml |
.mlpackage / .mlmodel |
| LiteRT / TFLite | timmx export litert |
.tflite |
| ncnn | timmx export ncnn |
directory (.param + .bin) |
| TensorRT | timmx export tensorrt |
.engine |
| ExecuTorch | timmx export executorch |
.pte |
| torch.export | timmx export torch-export |
.pt2 |
| TorchScript | timmx export torchscript |
.pt |
- Python
>=3.11 uv
Core install (includes timm, torch, typer, rich):
pip install timmxInstall with specific backend extras:
pip install 'timmx[onnx]' # ONNX export
pip install 'timmx[coreml]' # Core ML export
pip install 'timmx[litert]' # LiteRT/TFLite export
pip install 'timmx[ncnn]' # ncnn export (via pnnx)
pip install 'timmx[executorch]' # ExecuTorch export (XNNPack, CoreML delegates)
pip install 'timmx[onnx,coreml]' # multiple backendsTensorRT requires CUDA and must be installed separately:
pip install tensorrt # Linux/Windows with CUDA onlyNote: The
executorchandlitertextras have conflicting torch version requirements (executorchneedstorch>=2.10.0,litertneedstorch<2.10.0) and cannot be installed in the same environment.
Check which backends are available:
timmx doctoruv sync --extra onnx --extra coreml --extra ncnn --group dev
uv run timmx doctor
uv run timmx --helpInspect a model's metadata (parameter count, input size, number of classes, etc.) without exporting:
uv run timmx info resnet18 --pretrainedThis displays architecture details, parameter counts, default input size, and whether weights are loaded.
Browse and search available timm models:
uv run timmx list resnet # search by substring
uv run timmx list "resnet*" # search by glob pattern
uv run timmx list --pretrained-only resnet # only models with pretrained weightsuv run timmx export onnx resnet18 --pretrained --output ./artifacts/resnet18.onnxExport a fine-tuned checkpoint with dynamic batching:
uv run timmx export onnx resnet18 \
--checkpoint ./checkpoints/model.pth \
--input-size 3 224 224 \
--dynamic-batch \
--output ./artifacts/resnet18_finetuned.onnxExport with built-in normalization and softmax (the model will expect unnormalized [0, 1] float input and output probabilities):
uv run timmx export onnx resnet18 \
--pretrained \
--normalize --softmax \
--output ./artifacts/resnet18_with_preprocess.onnx
--normalizeembeds the timm model's mean/std normalization into the graph.--softmaxadds a softmax layer on the output. Use both flags together if you want a self-contained export that accepts raw[0, 1]float input and outputs probabilities; use--softmaxalone if your inputs are already normalized.--mean/--stdoverride the embedded normalization and therefore require--normalize.--in-chanscurrently supports only1or3; for grayscale (--in-chans 1) exports, RGB mean/std values are averaged down to a single channel.
Exported models are automatically optimized with onnxslim (constant folding, dead-code elimination, operator fusion). To skip optimization:
uv run timmx export onnx resnet18 --pretrained --no-slim --output ./artifacts/resnet18.onnxuv run timmx export coreml resnet18 \
--pretrained \
--convert-to mlprogram \
--compute-precision float16 \
--output ./artifacts/resnet18.mlpackageUsing torch.export as source (beta):
uv run timmx export coreml resnet18 \
--pretrained \
--source torch-export \
--convert-to mlprogram \
--compute-precision float16 \
--output ./artifacts/resnet18_te.mlpackageFlexible batch size:
uv run timmx export coreml resnet18 \
--dynamic-batch \
--batch-size 2 \
--batch-upper-bound 8 \
--output ./artifacts/resnet18_dynamic.mlpackageWeight quantization (post-conversion, applied to model weights):
# 8-bit k-means quantization (mlpackage)
uv run timmx export coreml resnet18 \
--pretrained \
--convert-to mlprogram \
--compute-precision float16 \
--int8 \
--output ./artifacts/resnet18_int8.mlpackage
# 4-bit k-means quantization (mlpackage only)
uv run timmx export coreml resnet18 \
--pretrained \
--convert-to mlprogram \
--compute-precision float16 \
--int4 \
--output ./artifacts/resnet18_int4.mlpackage
# fp16 weight quantization (neuralnetwork)
uv run timmx export coreml resnet18 \
--pretrained \
--convert-to neuralnetwork \
--half \
--output ./artifacts/resnet18_half.mlmodel
# 8-bit k-means quantization (neuralnetwork)
uv run timmx export coreml resnet18 \
--pretrained \
--convert-to neuralnetwork \
--int8 \
--output ./artifacts/resnet18_int8.mlmodelSupported modes: fp32, fp16, dynamic-int8, int8.
uv run timmx export litert resnet18 \
--mode fp16 \
--output ./artifacts/resnet18_fp16.tfliteINT8 with calibration data (point to an image directory — timm transforms are applied automatically):
uv run timmx export litert resnet18 \
--mode int8 \
--calibration-data ./my-images/ \
--output ./artifacts/resnet18_int8.tfliteLimit the number of calibration images loaded:
uv run timmx export litert resnet18 \
--mode int8 \
--calibration-data ./my-images/ \
--calibration-samples 64 \
--output ./artifacts/resnet18_int8.tfliteFor fine-tuned models with custom normalization, override calibration preprocessing with --mean / --std:
uv run timmx export litert resnet18 \
--mode int8 \
--calibration-data ./my-images/ \
--mean 0.5 0.5 0.5 --std 0.5 0.5 0.5 \
--output ./artifacts/resnet18_int8.tfliteFor image-directory calibration, --in-chans currently supports only 1 or 3; grayscale models
average RGB mean/std values down to one channel automatically.
A pre-saved torch tensor (N, C, H, W) is also accepted:
uv run timmx export litert resnet18 \
--mode int8 \
--calibration-data ./calibration.pt \
--calibration-steps 8 \
--output ./artifacts/resnet18_int8.tfliteUse --random-calibration to skip providing real data (not recommended for production):
uv run timmx export litert resnet18 \
--mode int8 \
--random-calibration \
--output ./artifacts/resnet18_int8.tfliteNHWC input layout:
uv run timmx export litert resnet18 \
--mode fp32 \
--nhwc-input \
--output ./artifacts/resnet18_nhwc.tfliteExports via pnnx and writes a deployment-ready ncnn model directory containing model.ncnn.param, model.ncnn.bin, and model_ncnn.py. pnnx intermediate files are removed automatically.
uv run timmx export ncnn resnet18 \
--pretrained \
--output ./artifacts/resnet18_ncnnExport without fp16 weight quantization:
uv run timmx export ncnn resnet18 \
--pretrained \
--no-fp16 \
--output ./artifacts/resnet18_ncnn_fp32Requires an NVIDIA GPU with CUDA and the tensorrt package (pip install tensorrt).
uv run timmx export tensorrt resnet18 \
--pretrained \
--mode fp16 \
--output ./artifacts/resnet18_fp16.engineINT8 with calibration (image directory or torch tensor):
uv run timmx export tensorrt resnet18 \
--pretrained \
--mode int8 \
--calibration-data ./my-images/ \
--output ./artifacts/resnet18_int8.engineOverride calibration normalization for fine-tuned models with --mean / --std:
uv run timmx export tensorrt resnet18 \
--pretrained \
--mode int8 \
--calibration-data ./my-images/ \
--mean 0.5 0.5 0.5 --std 0.5 0.5 0.5 \
--output ./artifacts/resnet18_int8.engineDynamic batch size:
uv run timmx export tensorrt resnet18 \
--pretrained \
--dynamic-batch \
--batch-size 4 \
--batch-min 1 \
--batch-max 32 \
--output ./artifacts/resnet18_dynamic.engineExport with XNNPack delegation (default, runs on CPU across all platforms):
uv run timmx export executorch resnet18 \
--pretrained \
--output ./artifacts/resnet18.pteCoreML delegation (macOS — targets Apple Neural Engine / GPU / CPU):
uv run timmx export executorch resnet18 \
--pretrained \
--delegate coreml \
--output ./artifacts/resnet18_coreml.pteCoreML with explicit fp32 compute precision (default is fp16):
uv run timmx export executorch resnet18 \
--pretrained \
--delegate coreml \
--compute-precision float32 \
--output ./artifacts/resnet18_coreml_fp32.pteINT8 quantized with XNNPack:
uv run timmx export executorch resnet18 \
--pretrained \
--mode int8 \
--calibration-data ./my-images/ \
--output ./artifacts/resnet18_int8.pteOverride calibration normalization for fine-tuned models with --mean / --std:
uv run timmx export executorch resnet18 \
--pretrained \
--mode int8 \
--calibration-data ./my-images/ \
--mean 0.5 0.5 0.5 --std 0.5 0.5 0.5 \
--output ./artifacts/resnet18_int8.pteINT8 quantized with CoreML:
uv run timmx export executorch resnet18 \
--pretrained \
--delegate coreml \
--mode int8 \
--random-calibration \
--output ./artifacts/resnet18_coreml_int8.pteDynamic batch size:
uv run timmx export executorch resnet18 \
--pretrained \
--dynamic-batch \
--batch-size 2 \
--output ./artifacts/resnet18_dynamic.pteuv run timmx export torch-export resnet18 \
--pretrained \
--dynamic-batch \
--batch-size 2 \
--output ./artifacts/resnet18.pt2When using
--dynamic-batch, set--batch-sizeto at least2so PyTorch can capture a symbolic batch dimension.
uv run timmx export torchscript resnet18 \
--pretrained \
--output ./artifacts/resnet18.ptExport with built-in normalization (model accepts unnormalized [0, 1] float input):
uv run timmx export torchscript resnet18 \
--pretrained \
--normalize \
--output ./artifacts/resnet18_normalized.ptFor fine-tuned models with custom normalization, override with --mean / --std:
uv run timmx export torchscript resnet18 \
--pretrained \
--normalize \
--mean 0.5 0.5 0.5 --std 0.5 0.5 0.5 \
--output ./artifacts/resnet18_custom_norm.ptGrayscale TorchScript export behaves the same as ONNX here: --in-chans is currently limited to
1 or 3, and RGB mean/std values are averaged down to one channel for --in-chans 1.
Use torch.jit.script instead of the default trace:
uv run timmx export torchscript resnet18 \
--pretrained \
--method script \
--output ./artifacts/resnet18_scripted.ptRun timmx info <model> to inspect any model's metadata, or timmx doctor to check your installation and see which backends are available:
timmx doctorThis shows the timmx version, Python/torch versions, and a table of backend availability with install hints for any missing dependencies.
- ONNX
- Core ML
- LiteRT / TFLite
- ncnn
- torch.export
- TensorRT
- TorchScript
- ExecuTorch (XNNPack + CoreML delegates)
- OpenVINO
- TensorFlow (SavedModel / .pb)
- TensorFlow.js
- TFLite Edge TPU
- RKNN
- MNN
- PaddlePaddle
uv sync --extra onnx --extra coreml --extra ncnn --group dev # install extras + pytest
uvx ruff format . # format
uvx ruff check . # lint
uv run pytest # test
uv build # buildSee CONTRIBUTING.md for a step-by-step guide on implementing and registering a new export backend.
This project is developed with the assistance of AI tools. The original export logic comes from various standalone scripts I wrote for exporting fine-tuned timm models to different deployment formats. The process of consolidating these scripts into a unified CLI tool has been aided by AI, with my oversight at every step, reviewing generated code, manually fixing issues during backend porting, and validating that exports produce correct results.