Generated reference › Min Max Scaler — Machine Learning/Preprocessing
kind: generated#block#machine-learning-preprocessing

Min Max Scaler — Machine Learning/Preprocessing

Machine_Learning/Preprocessing/Min_Max_Scaler · 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.

Min-Max Scaler

Machine Learning / Preprocessing

Per-feature rescaling to a fixed range, scikit-learn's MinMaxScaler at inference:

X_std = (u − data_min) ÷ (data_max − data_min), then y = X_std × (f_max − f_min) + f_min.

Reach for this rather than the Standard Scaler when the network was trained on inputs squashed to a fixed interval – image-style [0,1] features, or the [−1,1] a tanh front end expects. Internally the four fitted numbers collapse to the two sklearn itself stores, scale_ and min_, so a feature costs one multiply and one add.

Ports

  • u – the feature column, [m,1], where m is the number of entries in Data Min and Data Max. The size is checked rather than broadcast.
  • Outputy, the same [m,1] shape: this block rescales a signal, it never changes its dimensions.

Parameters

  • Data Minscaler.data_min_, an [m,1] column: the smallest value each feature took while fitting.
  • Data Maxscaler.data_max_, an [m,1] column. A feature whose max EQUALS its min has no range; its denominator is replaced by one, matching scikit-learn's own rule, so a constant feature maps to f_min instead of making the whole vector infinite.
  • Feature Range – the target interval as a [2,1] column, [f_min; f_max]. This is sklearn's feature_range, whose default is [0; 1]; [−1; 1] is the other common fit. f_max must be greater than f_min.
  • Clip
    • Off – a sample outside the fitted range maps outside the feature range too, in proportion. This is sklearn's default.
    • On – the output is clamped into [f_min, f_max], which is sklearn's clip=True. This is what a deployed scaler is usually fitted with, because live data does leave the range seen during training and a network given an out-of-range input is extrapolating.
    Clip applies to the forward transform only. With Direction set to Inverse it is inactive rather than an error: scikit-learn's inverse_transform does not clamp either, and clamping a recovered engineering value to the SCALED range would pin it to the wrong quantity.
  • Direction
    • Standardize – y = u × scale + off, the forward transform that feeds a model.
    • Inverse – recovers the engineering value from a scaled one, which is what takes a deployed regression's output back into real units. Without it a model in this library predicts in scaled numbers, which is the wrong thing to hand a controller.
  • Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period.

Code export

All ten targets: Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog and PLC Structured Text. The two derived constants are baked into the generated code as literals at full precision; there is no tunable parameter, because a fitted statistic is not something to retune on the target.

The three HDL targets are genuine Q16.16 fixed point and synthesizable: the division that turns the fitted range into a scale happens once, when the configuration is loaded, so the datapath is a multiply, an add and – in Clip mode – two comparisons. The same constants are used by the block itself, so the exported core and the in-app run compute bit-identical values.

Simulink bridge

None, and the first reason is about this installation rather than about Simulink: neither the Statistics and Machine Learning Toolbox nor the Deep Learning Toolbox is installed here, so a bridge could not be run against a parity testbench even if one were written. Base Simulink also offers no fitted-scaler block – the nearest thing is a Gain, a Bias and a Saturation wired together, and mapping this block onto any one of the three would assert an equivalence false for the other two. The bridge reports the block rather than dropping it silently, and it has no parity testbench, which is the documented consequence of Support::None rather than a gap. Code export verification still covers it across all ten languages.

Notes

  • Algebraic and stateless: the output depends only on the current input, so the block cannot break an algebraic loop.
  • No state space, deliberately – the map is affine, and y = C·x + D·u has nowhere to put the offset. Model reduction reports the block as unmergeable, which is the honest answer.
  • Compared with the Standard Scaler: that one centres on the mean and divides by the standard deviation, leaving the output unbounded; this one pins the fitted range onto a chosen interval. Neither is a substitute for the other, and a model expects the one it was trained with.

Code facts#

FactValue
registered typeMachine_Learning/Preprocessing/Min_Max_Scaler
familyMachine_Learning/Preprocessing
solver environment classICoreBlock_0_Machine_Learning_1_Preprocessing_2_Min_Max_Scaler
sourcesrc/ICoreSDK/ICoreBlockLibrary/Blocks/Machine_Learning/Preprocessing/Min_Max_Scaler/ICoreBlock_0_Machine_Learning_1_Preprocessing_2_Min_Max_Scaler.cpp
headersrc/ICoreSDK/ICoreBlockLibrary/Blocks/Machine_Learning/Preprocessing/Min_Max_Scaler/ICoreBlock_0_Machine_Learning_1_Preprocessing_2_Min_Max_Scaler.h
default size on canvas120 × 80 px
ports at insert1 in, 1 out
code generators implementedPython, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Ports#

#DirectionSignal typeDescription label
1inICoreDoubleu
2outICoreDoubley

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 variableDefaultSimulink parameter
Data Min[-2; 0; 10]
Data Max[6; 4; 30]
Feature Range[0; 1]
ClipOff%~%On~~Off
DirectionStandardize%~%Inverse~~Standardize

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.

supportSupport::None
Simulink path
port-count rulePortsParam::None
SampleTime parameteryes

Caveat (shown to the user): no verifiable Simulink equivalent. Neither the Statistics and Machine Learning Toolbox nor the Deep Learning Toolbox is installed on this machine, so a bridge could not be run against a parity testbench even if one were written. Base Simulink offers no fitted-scaler block in any case: the nearest thing is a Gain, a Bias and a Saturation wired together, and mapping onto any one of the three would claim an equivalence false for the other two. Re-create the scaler from those blocks, using this block's derived scale and offset

Catalog contract: src/ICoreSDK/ICoreCoder/ICoreCommandSystem/SimulinkBridge/ICoreSimulinkBlockCatalog.h

Description vs code#

The checker has a blind spot here — it could not resolve something (a grouped port bullet, a computed config name), which is reported and never counted as a pass. A reader has to settle it:

  • B0 every stimulus in the sample errored — cross-checks skipped

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).

Min-Max Scaler — sklearn's MinMaxScaler, evaluated at inference y = u * scale + off scale = (f_max - f_min) / (data_max - data_min) off = f_min - data_min * scale Clip mode: y is then clamped to [f_min, f_max]

The four fitted numbers collapse to TWO per feature, exactly as sklearn stores them (scale_ and min_), so a feature costs one multiply and one add. See the header for why that collapse is what keeps the HDL synthesizable and the export bit-identical.

⚠ The CLAMP is the reason Clip is a MODE and not a config flag: it is a different code path in all ten backends, and in three of them it is a different KIND of construct (a sequential if in VHDL, a nested ternary in the two Verilogs, MIN/MAX in ST). A config that merely retunes numbers can share a rig; this cannot.

Sample results#

No stimulus produced a sampled output in this rig — Invalid input size at: ICore Blocks/Home/Min Max Scaler. That is a fact about the single-block rig, not a verdict on the block: an offline batch fit, a block whose output only appears at onSolverFinish, or one that needs a driven environment cannot be exercised alone.

Category unsampled · sample time 0.1 · 60 steps · commit ccf005c8 · produced by docsSample --out <folder> --steps 60

Sample data: docs/generated/samples/Machine_Learning__Preprocessing__Min_Max_Scaler.json