Incremental Classification Linear Fit — Machine Learning/Incremental Learning
Machine_Learning/Incremental_Learning/Incremental_Classification_Linear_Fit · 2 input / 1 output port(s) at insert · exports to Python, MATLAB, Java, Rust, C, C++
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.
Incremental Classification Linear Fit
Machine Learning / Incremental Learning
Fits a binary linear classifier online, one observation per step, and
puts the model on a bus every step: the score is f = x·β + b, and a
Predict block answers the second class when f ≥ 0. This is MATLAB's
incrementalClassificationLinear learner with its default
scale-invariant solver (Statistics and Machine Learning Toolbox), as Simulink's
IncrementalClassificationLinear Fit block runs it, with labels coded −1
for the first class name and +1 for the second. Under Standardize, the
first Estimation Period observations only estimate the predictors' means
and standard deviations; every other observation updates β and b. Feed the
bus to an IncrementalClassificationLinear Predict block.
Ports
- x – one observation of the P predictors, a row [1,P]. P is read off this width.
- y – its label, [1,1]: one of the two Class Names. Any other label, NaN included, stops the run, as Simulink's block does. A NaN in x skips the observation, where Simulink's block lets it in and its Beta turns NaN for the rest of the run.
- mdl (
bus) – the learner after this observation, a bus of eight elements: Beta [P,1], Bias [1,1], IsWarm (bool), CanPredict (bool, false only while standardization is still being estimated), Mu [P,1] and Sigma [P,1] (0 and 1 when there is no standardization), MajorityClass (u8, 1 or 2, the more frequent label so far) and Prior [2,1] (the two classes' shares of the observations trained on, 0.5 each before the first).
Parameters
- Learner – the loss the solver minimizes:
- svm (the default) – the hinge loss of a support vector machine;
- logistic – the logistic (logit) loss of a logistic regression.
- Class Names – the two labels, [0 1] by default; the first is coded −1 and the second +1.
- Standardize – off (the default) or on: center and scale each predictor by its mean and standard deviation over the estimation period.
- Estimation Period – how many observations the standardization is estimated from, 1000 by default as in MATLAB; it applies only with Standardize on.
- Metrics Warmup Period – how many observations after the estimation period make the model warm (IsWarm), 1000 by default.
- Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period.
When a run is refused
An x that is not a row, a y that is not [1,1], Class Names that are not two different numbers, a negative or fractional period, Standardize on with an Estimation Period of 0, and, during the run, a label that is neither class name (NaN included).
Code export
Six targets: Python, MATLAB, Java, Rust, C and C++, each carrying the learner's whole state and running the same step as the live block, in the same arithmetic order. An exported core does not stop on a foreign label: it takes any label other than the first class name as the second, and skips a NaN one. The hardware targets (VHDL, Verilog, SystemVerilog) and PLC Structured Text carry no bus, so an export to one stops and names the block.
Simulink bridge
None. Simulink's block takes its learner as InitialLearner, the name of an incrementalClassificationLinear object in the MATLAB workspace, rather than as dialog parameters, so there is nothing in its dialog to map these configs onto or read them back from.
Notes
- Stateful: the state is the solver's (four running sums per coefficient), the estimation sums, and the class counts.
- The bus at a step has already learnt that step's observation, as in Simulink.
- It follows Simulink's block, not MATLAB's fit(), in three measured ways: the estimated Mu and Sigma appear one step after the estimation period and IsWarm one step after fit() would set it; while the first class name has not yet been seen, every observation of the second after the first is dropped (neither trained on nor counted in Prior, though it counts toward the warm-up); and MajorityClass counts every labelled observation, the estimation and dropped ones included, ties going to the second class.
- A predictor that does not vary over the estimation period gets Sigma 0 and is left unscaled, as MATLAB's learner leaves it; Simulink's block divides by that zero and its Beta turns NaN.
- One observation per step, two classes, and an empirical Prior; Simulink's optional weights and reset inputs are not offered.
- Verified against R2026a: over 120 steps in four configurations (svm and logistic, standardized or not, class names [0 1] and [2 7], one run opening on the second class), Beta, Bias and Prior agree with Simulink's block within 10−14, and IsWarm, CanPredict, Mu, Sigma and MajorityClass at every step.
Code facts#
| Fact | Value |
|---|---|
| registered type | Machine_Learning/Incremental_Learning/Incremental_Classification_Linear_Fit |
| family | Machine_Learning/Incremental_Learning |
| solver environment class | ICoreBlock_0_Machine_Learning_1_Incremental_Learning_2_Incremental_Classification_Linear_Fit |
| source | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Machine_Learning/Incremental_Learning/Incremental_Classification_Linear_Fit/ICoreBlock_0_Machine_Learning_1_Incremental_Learning_2_Incremental_Classification_Linear_Fit.cpp |
| header | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Machine_Learning/Incremental_Learning/Incremental_Classification_Linear_Fit/ICoreBlock_0_Machine_Learning_1_Incremental_Learning_2_Incremental_Classification_Linear_Fit.h |
| default size on canvas | 160 × 80 px |
| ports at insert | 2 in, 1 out |
| code generators implemented | Python, MATLAB, Java, Rust, C, C++ |
Ports#
| # | Direction | Signal type | Description label |
|---|---|---|---|
| 1 | in | ICoreDouble | x |
| 2 | in | ICoreDouble | y |
| 3 | out | ICoreBus | mdl |
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 |
|---|---|---|
Learner | svm%~%logistic~~svm | — |
Class Names | [0 1] | — |
Standardize | off%~%on~~off | — |
Estimation Period | 1000 | — |
Metrics Warmup Period | 1000 | — |
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 | statsIncremental/Classification/Linear/IncrementalClassificationLinear Fit |
| port-count rule | PortsParam::None |
SampleTime parameter | yes |
Caveat (shown to the user): no bridge: Simulink's IncrementalClassificationLinear Fit block takes its learner as InitialLearner, the NAME of an incrementalClassificationLinear object in the MATLAB workspace, not as dialog parameters -- there is nothing in its dialog to map the learner configs onto, or read them back from
Catalog contract: src/ICoreBlocks/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).
IncrementalClassificationLinear Fit -- an online binary linear classifier, its model on a bus statsIncremental/Classification/Linear/IncrementalClassificationLinear Fit, MEASURED on R2026a 2026-10-02 (BLOCKS_TO_ADD_TOOLBOXES.md statsIncremental, on FEATURES_TO_ADD.md BF1). Simulink's block takes its learner as InitialLearner, the name of an incrementalClassificationLinear object in the MATLAB workspace; here the learner's options are configs: Learner (svm, logistic), Class Names (two numbers), Standardize, EstimationPeriod and MetricsWarmupPeriod. The predictor count is x's width.
The solver is MATLAB's scale-invariant one, on labels coded -1 (the first class name) and +1 (the second), and the block follows the Simulink block's measured behaviour, three points of which differ from the object's fit():
- the estimated Mu and Sigma appear one step after the estimation period, and IsWarm one
step after fit() would set it;
- Prior counts the observations trained on and is taken as known after the first, and
while the first class has not been seen every observation of the second class after the first is dropped (Simulink's zero-prior filter compares the +-1 coded label with the class indices 1 and 2) -- dropped observations still count toward the warm-up;
- MajorityClass is the last index of the larger of two counts of every labelled
observation, the estimation and dropped ones included. Against the Simulink block over 120 steps in four configurations (svm and logistic, standardized or not, class names [0 1] and [2 7], a run that opens on the second class): Beta and Bias within 1e-14, Prior within 1e-14, every flag and MajorityClass exact.
A label that is neither class name, NaN included, stops the run, as Simulink's block does (an assertion inside it, measured with both). A NaN predictor skips the observation, where Simulink's block lets it in and its Beta turns NaN for the rest of the run.
Sample results#
This block carries a ICoreBus signal, whose value is text rather than a number and is not something a plot has an axis for. The samples are in the table below, exactly as the run recorded them.
| t | in ICoreDouble-Out-0 | in ICoreDouble-Out-0 | out ICoreBus-Out-0 |
|---|---|---|---|
| 0 | 0 | 0 | {'Beta': 0, 'Bias': 0, 'IsWarm': 0, 'CanPredict': 1, 'Mu': 0, 'Sigma': 1, 'MajorityClass': 1, 'Prior': [1, 0]} |
| 0.4 | 0 | 0 | {'Beta': 0, 'Bias': -0.4502445628, 'IsWarm': 0, 'CanPredict': 1, 'Mu': 0, 'Sigma': 1, 'MajorityClass': 1, 'Prior': [1, 0]} |
| 0.8 | 0 | 0 | {'Beta': 0, 'Bias': -0.6918226807, 'IsWarm': 0, 'CanPredict': 1, 'Mu': 0, 'Sigma': 1, 'MajorityClass': 1, 'Prior': [1, 0]} |
| 1.2 | 1 | 1 | {'Beta': 0.3608439182, 'Bias': -0.5651679839, 'IsWarm': 0, 'CanPredict': 1, 'Mu': 0, 'Sigma': 1, 'MajorityClass': 1, 'Prior': [0.7692307692, 0.2307692308]} |
| 1.6 | 1 | 1 | {'Beta': 0.56065746, 'Bias': -0.2726509658, 'IsWarm': 0, 'CanPredict': 1, 'Mu': 0, 'Sigma': 1, 'MajorityClass': 1, 'Prior': [0.5882352941, 0.4117647059]} |
| 2 | 1 | 1 | {'Beta': 0.8455080861, 'Bias': 0, 'IsWarm': 0, 'CanPredict': 1, 'Mu': 0, 'Sigma': 1, 'MajorityClass': 2, 'Prior': [0.4761904762, 0.5238095238]} |
| 2.4 | 1 | 1 | {'Beta': 1.024188067, 'Bias': 0.07699016741, 'IsWarm': 0, 'CanPredict': 1, 'Mu': 0, 'Sigma': 1, 'MajorityClass': 2, 'Prior': [0.4, 0.6]} |
| 2.8 | 1 | 1 | {'Beta': 1.024188067, 'Bias': 0.07699016741, 'IsWarm': 0, 'CanPredict': 1, 'Mu': 0, 'Sigma': 1, 'MajorityClass': 2, 'Prior': [0.3448275862, 0.6551724138]} |
| 3.2 | 1 | 1 | {'Beta': 1.024188067, 'Bias': 0.07699016741, 'IsWarm': 0, 'CanPredict': 1, 'Mu': 0, 'Sigma': 1, 'MajorityClass': 2, 'Prior': [0.303030303, 0.696969697]} |
| 3.6 | 1 | 1 | {'Beta': 1.024188067, 'Bias': 0.07699016741, 'IsWarm': 0, 'CanPredict': 1, 'Mu': 0, 'Sigma': 1, 'MajorityClass': 2, 'Prior': [0.2702702703, 0.7297297297]} |
| 4 | 1 | 1 | {'Beta': 1.024188067, 'Bias': 0.07699016741, 'IsWarm': 0, 'CanPredict': 1, 'Mu': 0, 'Sigma': 1, 'MajorityClass': 2, 'Prior': [0.243902439, 0.756097561]} |
| 4.4 | 1 | 1 | {'Beta': 1.024188067, 'Bias': 0.07699016741, 'IsWarm': 0, 'CanPredict': 1, 'Mu': 0, 'Sigma': 1, 'MajorityClass': 2, 'Prior': [0.2222222222, 0.7777777778]} |
| 4.8 | 1 | 1 | {'Beta': 1.024188067, 'Bias': 0.07699016741, 'IsWarm': 0, 'CanPredict': 1, 'Mu': 0, 'Sigma': 1, 'MajorityClass': 2, 'Prior': [0.2040816327, 0.7959183673]} |
| 5.2 | 1 | 1 | {'Beta': 1.024188067, 'Bias': 0.07699016741, 'IsWarm': 0, 'CanPredict': 1, 'Mu': 0, 'Sigma': 1, 'MajorityClass': 2, 'Prior': [0.1886792453, 0.8113207547]} |
Every 4th of 60 samples, from the step stimulus.
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) | — |
Plotted: step — Step: 0 -> 1 at t = 1 s
Category static · sample time 0.1 · 60 steps · commit 68af3e6d2 · produced by docsSample --out <folder> --blocks Incremental_Regression_Linear_Fit Incremental_Regression_Linear_Predict Incremental_Classification_Linear_Fit Incremental_Classification_Linear_Predict --steps 60 · data docs/generated/samples/Machine_Learning__Incremental_Learning__Incremental_Classification_Linear_Fit.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).