Autocorrelation Features — Machine Learning/Feature Engineering
Machine_Learning/Feature_Engineering/Autocorrelation_Features · 1 input / 1 output port(s) at insert · exports to Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text
Description#
The block's own DESCRIPTION_HTML, rendered verbatim — the same text the config dialog's info panel and the library navigator show. Fix a wrong sentence in the block's .cpp (R-D9), never here.
Autocorrelation Features
Machine Learning / Feature Engineering
Correlates the last N samples of the signal with a delayed copy of itself, at each of a configured set of lags. With x[0] the current sample and x[k] the sample k steps back:
r(l) = Σk (x[k] − m)(x[k+l] − m) ÷ Σk (x[k] − m)² – or the unnormalized covariance form, as a mode.
This is the cheap answer to "does this signal repeat, and after how long": a rotating machine's period, a gait cycle or a control loop's oscillation all show up as a peak at the lag that matches them, using multiplies and adds alone where a spectrum needs a transform. Feed the outputs to a Dense Layer or a Decision Tree as features.
Stateful and discrete by nature. The window advances one sample per step and has no derivative to integrate, so the block declares itself discrete-only and always steps at its own rate.
Ports
- u – the input sample, a scalar [1,1]. The lags index TIME, so one block follows one channel; use one block per channel and a Mux to gather the features.
- r – the correlations, [L,1], one entry per configured lag and in the order the lags are written. The height follows the Lags list, so the block resizes its output when you change it.
Parameters
- Window Length – N, the number of samples the correlation is taken over. Every lag is measured inside this one window, so a lag of l leaves N−l overlapping pairs to average: keep N several times the largest lag, or the longest lags rest on a handful of products.
- Lags – the lags to report, as a vector such as
[1; 2; 3]. Each is a whole number of samples from 0 to N−1; lag 0 is the window's own energy (and is exactly 1 in the Coefficient form, which makes it a useful shape check and a useless feature). - Normalization – what the products are divided by. The two are
different code paths rather than a scaling, so each is verified as its own mode:
- Coefficient – divided by the window's own sum of squared
deviations, so every entry lies in [−1, 1] and is comparable across
signals of different amplitude. This is what
statsmodels.acfreturns. - Covariance – the products averaged over N and nothing more, so the result keeps the signal's units squared. Use it when amplitude is itself a feature.
- Coefficient – divided by the window's own sum of squared
deviations, so every entry lies in [−1, 1] and is comparable across
signals of different amplitude. This is what
- Remove Mean – whether the window's mean is subtracted before correlating. On is the usual choice and what the formulas above show; with Off, a signal with a large DC level correlates strongly with itself at every lag and the shape of the curve is buried under it.
- Initial Window Value – what every slot holds before the first sample arrives. The window is full from the very first step rather than growing, for the reason Rolling Statistics gives: a partial window costs a sample counter and a divide-by-count branch in all ten exported languages, for a startup transient a feature pipeline discards anyway.
- Epsilon – a floor on the Coefficient form's denominator. A window that is exactly constant has zero variance and no defined correlation; the floor makes that case return zero in all ten languages instead of a division by zero. It is a floor and not a branch deliberately – the same choice Normalizer makes, and for the same reason: one expression every target has a primitive for, rather than an if-statement re-implemented eleven times.
- Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period. Being discrete-only, a non-positive value falls back to the model's global sampling time rather than to the surrounding rate.
Code export
All ten targets: Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog and PLC Structured Text. The window and every lag's product sum are unrolled at export time – N and the lag list are both known then – so no backend carries a loop bound, a modulo or a ring-buffer index, and each holds the N−1 stored samples in its own persistent form seeded with Initial Window Value.
The three HDL targets split by normalization: Covariance is
genuine synthesizable Q16.16 – multiply-accumulate with the
1/N folded into a constant at export time, so no divider appears –
while Coefficient divides by the window's own variance, a signal-dependent
divisor that cannot be precomputed, and is therefore emitted as
simulation-only real arithmetic. That mode simulates
correctly and quantizes at the port boundary; it is not offered as
synthesizable.
Simulink bridge
None. dspstat3/Autocorrelation exists in the installed DSP
System Toolbox, but it emits the whole sequence up to a maximum lag, while
this block reports a chosen SET of lags – there is no parameter on it that
a Lags list maps onto, and an entry claiming otherwise would export a
different function under this block's name. The bridge reports the block rather
than dropping it silently, and it has no parity testbench, which is the
documented consequence of Support::None. Code export verification
still covers it across all ten languages.
Notes
- Stateful: the answer depends on the N−1 samples before the current one. The window is re-seeded at the start of every run.
- No state space: the correlation is quadratic in the input, so no A/B/C/D describes it and model reduction correctly refuses the block.
- The state is read before it is written. Every lag is computed from the window as it stood, and only then does the window shift – on the three HDL targets that comes free from the registered write, and the other seven shift from the far end downwards.
- Not a spectrum. For frequency content use FFT Magnitude; this block answers periodicity with no transform, which is what makes it affordable on a PLC or in fixed point.
Code facts#
| Fact | Value |
|---|---|
| registered type | Machine_Learning/Feature_Engineering/Autocorrelation_Features |
| family | Machine_Learning/Feature_Engineering |
| solver environment class | ICoreBlock_0_Machine_Learning_1_Feature_Engineering_2_Autocorrelation_Features |
| source | src/ICoreSDK/ICoreBlockLibrary/Blocks/Machine_Learning/Feature_Engineering/Autocorrelation_Features/ICoreBlock_0_Machine_Learning_1_Feature_Engineering_2_Autocorrelation_Features.cpp |
| header | src/ICoreSDK/ICoreBlockLibrary/Blocks/Machine_Learning/Feature_Engineering/Autocorrelation_Features/ICoreBlock_0_Machine_Learning_1_Feature_Engineering_2_Autocorrelation_Features.h |
| default size on canvas | 132 × 84 px |
| ports at insert | 1 in, 1 out |
| code generators implemented | Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text |
Ports#
| # | Direction | Signal type | Description label |
|---|---|---|---|
| 1 | in | ICoreDouble | u |
| 2 | out | ICoreDouble | r |
Ports the constructor creates. A block whose port list changes with its configuration adds or removes ports at load time; the count above is the one a freshly inserted block has.
Configuration variables#
| Config variable | Default | Simulink parameter |
|---|---|---|
Window Length | 8 | — |
Lags | [1; 2; 3] | — |
Normalization | Coefficient%~%Covariance~~Coefficient | — |
Remove Mean | On%~%Off~~On | — |
Initial Window Value | 0 | — |
Epsilon | 1e-12 | — |
Every block also carries Sampling Time (s) from ICoreBlockSolverEnvironment: zero or less inherits the solver's rate, a positive value runs the block at that period.
Simulink bridge#
| support | Support::None |
| Simulink path | — |
| port-count rule | PortsParam::None |
SampleTime parameter | yes |
Caveat (shown to the user): no mappable Simulink equivalent: dspstat3/Autocorrelation emits the WHOLE sequence up to a maximum lag, while this block reports a chosen SET of lags -- it has no parameter a Lags list maps onto, so any entry would export a different function under this block's name
Catalog contract: src/ICoreSDK/ICoreCoder/ICoreCommandSystem/SimulinkBridge/ICoreSimulinkBlockCatalog.h
Description vs code#
The lists agree. check_block_descriptions.py finds no disagreement between the description's Ports, Parameters, Code export and Simulink bridge lists and the code's.
The verdict above is
tools/docs/check_block_descriptions.py(P7.1), which compares LISTS. It cannot read a sentence: "stateless" on a block with a state, an initial-value semantic the recursion does not implement, a "not synthesizable" caveat the HDL banner contradicts. That is the agent audit (P7.3) on BLOCK_DESCRIPTION_AUDIT.md, and this tool's green is not a substitute for one.
File banner (developer view)#
The top comment of the block's .cpp — the maths, the realization and the export strategy, addressed to whoever changes it. It must not contradict the description above (P7.5).
Autocorrelation Features — the ACF of the last N samples, at a chosen set of lags num(l) = SUM_{k=0..N-1-l} (x[k] - m)(x[k+l] - m) x[0] the current sample r(l) = num(l) / max( SUM_k (x[k] - m)^2 , Epsilon ) ... Coefficient c(l) = num(l) * (1/N) ... Covariance
Read the header before this file: it records the scalar-input decision, the shared window surface with Rolling_Statistics, the per-mode HDL split, and why the denominator is floored rather than branched.
⚠ The window is UNROLLED at export time and the mean is INLINED into every deviation rather than held in a temporary, for the reason Rolling_Statistics gives: VHDL's Coefficient path is real-typed and has no real local to put it in, and one emission path shared by ten backends is worth more than the repeated text. N is small by design (8 by default) so it stays so.
Sample results#
The same rig also ran:
| Stimulus | What it is | Output range |
|---|---|---|
impulse | Impulse: one sample of 1 at k = 5, 0 elsewhere (Repeating Sequence Stair) | -0.1607 … 0 |
ramp | Ramp: slope 1 from t = 0 | -0.01786 … 0.6616 |
sine | Sine Wave: amplitude 1, 2 rad/s, no phase, no bias | -0.01786 … 0.6878 |
table | Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample | -0.02126 … 0.5502 |
Plotted: step — Step: 0 -> 1 at t = 1 s
Category dynamic · sample time 0.1 · 60 steps · commit ccf005c8 · produced by docsSample --out <folder> --steps 60 · data docs/generated/samples/Machine_Learning__Feature_Engineering__Autocorrelation_Features.json · the SVG is generated from those numbers by tools/docs/plot_svg.py, so it is a run and not a drawing (R-D10).