jev-tune decision head
A 168 KB ONNX model that reads a closed-loop step response and returns one bounded PID gain step in 0.19 ms on a single CPU thread.
It is the runtime policy of jev-tune. It emits the three Jev-style primitives rather than text:
| output | shape | meaning |
|---|---|---|
choice |
3 × 7 | multiplicative step for Kp, Ki, Kd (×0.50 … ×2.00) |
score |
5 | how good the current response is (used for early stopping) |
noul |
1 | calibrated P(the step keeps the loop healthy) |
Inputs
| name | shape | description |
|---|---|---|
feats |
(B, 20) |
hand-crafted response descriptors (overshoot, rise, settling, ess, log IAE/ITAE, oscillations, saturation, previous action and its effect, Ku/Kp, Tu/h …) |
curves |
(B, 2, 64) |
resampled and normalised y(t) and u(t) |
Usage
import numpy as np, onnxruntime as ort
sess = ort.InferenceSession("jev_head.onnx", providers=["CPUExecutionProvider"])
choice, score, noul = sess.run(None, {"feats": feats, "curves": curves})
The reference implementation, the feature extraction and the closed-loop driver
are in the repository. models/jev_head_weights.mat is the same network
exported for MATLAB, so the tuner can run inside Simulink without Python.
Measured behaviour
| value | |
|---|---|
| decision latency (1 thread, batch 1) | 0.19 ms p50 / 0.24 ms p99 |
| calibration (ECE after temperature fit) | 0.01 – 0.03 |
| held-out plants, median final cost | 0.468 (CMA-ES 1.813 at the same budget) |
| plants that ended worse than the start | 0 / 200 |
Limits
Trained on a synthetic zoo (six plant families, including actuator saturation).
It is not magic: dead bands, inverse response and open-loop unstable plants
need a specialist fine-tune (scripts/10_specialize.py, ~2 min of CPU), and
tracking/disturbance objectives need new metrics and a retrain. See
docs/APPLICABILITY.md in the repository.
Licence
MIT © JIAWEI LI. Trained in this project on synthetic data; no third-party weights are involved.