Incremental Classification ECOC Fit — Machine Learning/Incremental Learning
Machine_Learning/Incremental_Learning/Incremental_Classification_ECOC_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 ECOC Fit
Machine Learning / Incremental Learning
Fits a K-class classifier online from L binary linear classifiers (error-correcting output codes), and puts the model on a bus every step. Column l of the coding matrix M [K,L] says which classes learner l calls positive (+1), negative (−1) or ignores (0); each step the rows of x are relabelled for each learner in turn and fitted by MATLAB's scale-invariant solver on the hinge loss, as Simulink's IncrementalClassificationECOC Fit block runs it. Feed the bus to an Incremental Classification ECOC Predict block.
Ports
- x – n observations of the P predictors, a matrix [n,P]: one row per observation. P and n are read off its size.
- y – their labels, [n,1], each one of the Class Names. A label that is not a class name keeps that row's class from the previous step, as Simulink's block does.
- mdl (
bus) – the model after this step, a bus of nine elements in Simulink's order: AllBeta [P,L] and AllBias [L,1], the learners' coefficients; AllMu and AllSigma [P,L], the standardization each used (0 and 1 without it); AllMajorityClass (u8) [L,1], 1 or 2, the side each learner has seen more of; AllCanPredict (bool) [L,1]; IsWarm (bool); MajorityClass (u16), the index of the most frequent class so far; and SeenBothClasses (bool) [L,1].
Parameters
- Class Names – the K labels, [1 2 3] by default, two or more different numbers.
- Coding – the coding design:
- onevsone (the default) – one learner per pair of classes, in MATLAB's order (1 against 2, 1 against 3, …, 2 against 3, …), the first of the pair positive;
- onevsall – one learner per class, that class against the rest;
- custom – the Coding Matrix.
- Coding Matrix – a K-by-L matrix of −1, 0 and +1, read when Coding is custom; every column needs a +1 and a −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; it applies only with Standardize on. A batch that would run past it is not used for estimation: the period is declared full and the batch trains, as Simulink's block does.
- Metrics Warmup Period – how many observations make the model warm (IsWarm), 1000 by default, counted from the first.
- Shuffle – on (the default) or off: the order each learner trains on a step's rows, sorted by draws of MATLAB's twister seeded 5489 at the start of the run, as the Simulink block's private stream is.
- 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
Class Names that are not two or more different numbers, a coding matrix that is not K-by-L of −1, 0 and +1 with a +1 and a −1 in every column, a negative or fractional period, Standardize on with an Estimation Period of 0, and a y whose height is not x's.
Code export
Six targets: Python, MATLAB, Java, Rust, C and C++, each carrying the learner's whole state and the twister's, and running the same step as the live block in the same arithmetic order. 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 incrementalClassificationECOC 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
- ⚠ The L learners are ONE learner. As in Simulink's block, a
single linear learner is fitted L times a step, once per coding column, and
AllBeta(:,l) is that learner after call l – learner 1 at the next step
continues from learner L. Fitting L independent learners, as MATLAB's
fitdoes, gives a different model (measured: 0.51 in Beta). - The bus at a step has already learnt that step's rows, as in Simulink.
- Measured quirks kept: IsWarm counts every observation with no estimation offset; MajorityClass is the first index of the largest class count; SeenBothClasses looks at the last positive and the last negative class of each column; while a class's share is zero the binary learner drops its positive rows (Simulink's zero-prior filter); and standardization divides by a zero standard deviation unguarded, so a constant predictor turns Beta NaN for good – all as Simulink's block does.
- Svm learners only (the hinge loss): Simulink's mask refuses a logistic template, so there is nothing to follow.
- Any n of 1 or more: Simulink's block needs two rows or more, and this block gives the same answer whenever it runs.
- Verified against R2026a: the learner, bookkeeping and decoding transcribed here matched Simulink's Fit and Predict blocks with max |diff| = 0 on every bus element over 23 runs (one-vs-one, one-vs-all and a ternary coding; 2, 3 and 4 rows a step; standardized with every estimation-period remainder; labels outside the class names; no shuffle), and the incremental_ecoc suite pins this block against those runs.
Code facts#
| Fact | Value |
|---|---|
| registered type | Machine_Learning/Incremental_Learning/Incremental_Classification_ECOC_Fit |
| family | Machine_Learning/Incremental_Learning |
| solver environment class | ICoreBlock_0_Machine_Learning_1_Incremental_Learning_2_Incremental_Classification_ECOC_Fit |
| source | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Machine_Learning/Incremental_Learning/Incremental_Classification_ECOC_Fit/ICoreBlock_0_Machine_Learning_1_Incremental_Learning_2_Incremental_Classification_ECOC_Fit.cpp |
| header | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Machine_Learning/Incremental_Learning/Incremental_Classification_ECOC_Fit/ICoreBlock_0_Machine_Learning_1_Incremental_Learning_2_Incremental_Classification_ECOC_Fit.h |
| default size on canvas | 170 × 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 |
|---|---|---|
Class Names | [1 2 3] | — |
Coding | onevsone%~%onevsall%~%custom~~onevsone | — |
Coding Matrix | [1 1 0; -1 0 1; 0 -1 -1] | — |
Standardize | off%~%on~~off | — |
Estimation Period | 1000 | — |
Metrics Warmup Period | 1000 | — |
Shuffle | on%~%off~~on | — |
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/ECOC/IncrementalClassificationECOC Fit |
| port-count rule | PortsParam::None |
SampleTime parameter | yes |
Caveat (shown to the user): no bridge: Simulink's IncrementalClassificationECOC Fit block takes its learner as InitialLearner, the NAME of an incrementalClassificationECOC 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).
IncrementalClassificationECOC Fit -- K classes from L binary linear learners, fitted online, the model on a bus statsIncremental/Classification/ECOC/IncrementalClassificationECOC Fit, MEASURED on R2026a 2026-10-03 (BLOCKS_TO_ADD_TOOLBOXES.md statsIncremental, on FEATURES_TO_ADD.md BF1). Simulink's block takes its learner as InitialLearner, the name of an incrementalClassificationECOC object in the MATLAB workspace; here the learner's options are configs: Class Names, the Coding (one-vs-one, one-vs-all or a matrix of your own), Standardize, Estimation Period, Metrics Warmup Period and Shuffle. P is x's width and n, the rows a step, its height.
The arithmetic and the measured behaviour -- ONE learner shared by all L binary problems, each step's L calls of it on the batch in a shuffled row order from a private MT19937, the per-call bookkeeping, the unguarded standardization -- are ICoreIncrementalEcocSupport's, which followed the Simulink block with max |diff| = 0 on every bus element over 23 runs.
A label that is not a class name keeps that row's class from the previous step, as the Simulink block does (0 -- no class -- on the first step).
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 | -2 | -2 | {'AllBeta': [0, 0, 0], 'AllBias': [0, 0, 0], 'AllMu': [0, 0, 0], 'AllSigma': [1, 1, 1], 'AllMajorityClass': [2, 2, 2], 'AllCanPredict': [1, 1, 1], 'IsWarm': 0, 'MajorityClass': 1, 'SeenBothClasses': [0, 0, 0]} |
| 0.4 | 0.5 | 0.5 | {'AllBeta': [0, 0, 0], 'AllBias': [0, 0, 0], 'AllMu': [0, 0, 0], 'AllSigma': [1, 1, 1], 'AllMajorityClass': [2, 2, 2], 'AllCanPredict': [1, 1, 1], 'IsWarm': 0, 'MajorityClass': 1, 'SeenBothClasses': [0, 0, 0]} |
| 0.8 | -2 | -2 | {'AllBeta': [-0.04444444444, -0.04444444444, -0.04444444444], 'AllBias': [0, 0, 0], 'AllMu': [0, 0, 0], 'AllSigma': [1, 1, 1], 'AllMajorityClass': [2, 2, 2], 'AllCanPredict': [1, 1, 1], 'IsWarm': 0, 'MajorityClass': 3, 'SeenBothClasses': [0, 0, 0]} |
| 1.2 | 0.5 | 0.5 | {'AllBeta': [-0.04444444444, -0.04444444444, -0.04444444444], 'AllBias': [0, 0, 0], 'AllMu': [0, 0, 0], 'AllSigma': [1, 1, 1], 'AllMajorityClass': [2, 2, 2], 'AllCanPredict': [1, 1, 1], 'IsWarm': 0, 'MajorityClass': 3, 'SeenBothClasses': [0, 0, 0]} |
| 1.6 | -2 | -2 | {'AllBeta': [0.01665702718, 0.01665702718, 0.01665702718], 'AllBias': [0.1151177576, 0.1151177576, 0.1151177576], 'AllMu': [0, 0, 0], 'AllSigma': [1, 1, 1], 'AllMajorityClass': [2, 2, 2], 'AllCanPredict': [1, 1, 1], 'IsWarm': 0, 'MajorityClass': 3, 'SeenBothClasses': [0, 0, 0]} |
| 2 | 0.5 | 0.5 | {'AllBeta': [0.01665702718, 0.01665702718, 0.01665702718], 'AllBias': [0.1151177576, 0.1151177576, 0.1151177576], 'AllMu': [0, 0, 0], 'AllSigma': [1, 1, 1], 'AllMajorityClass': [2, 2, 2], 'AllCanPredict': [1, 1, 1], 'IsWarm': 0, 'MajorityClass': 3, 'SeenBothClasses': [0, 0, 0]} |
| 2.4 | -2 | -2 | {'AllBeta': [0.03181567111, 0.03181567111, 0.03181567111], 'AllBias': [0.160472333, 0.160472333, 0.160472333], 'AllMu': [0, 0, 0], 'AllSigma': [1, 1, 1], 'AllMajorityClass': [2, 2, 2], 'AllCanPredict': [1, 1, 1], 'IsWarm': 0, 'MajorityClass': 3, 'SeenBothClasses': [0, 0, 0]} |
| 2.8 | 0.5 | 0.5 | {'AllBeta': [0.03181567111, 0.03181567111, 0.03181567111], 'AllBias': [0.160472333, 0.160472333, 0.160472333], 'AllMu': [0, 0, 0], 'AllSigma': [1, 1, 1], 'AllMajorityClass': [2, 2, 2], 'AllCanPredict': [1, 1, 1], 'IsWarm': 0, 'MajorityClass': 3, 'SeenBothClasses': [0, 0, 0]} |
| 3.2 | -2 | -2 | {'AllBeta': [0.04222834665, 0.04222834665, 0.04222834665], 'AllBias': [0.1785217182, 0.1785217182, 0.1785217182], 'AllMu': [0, 0, 0], 'AllSigma': [1, 1, 1], 'AllMajorityClass': [2, 2, 2], 'AllCanPredict': [1, 1, 1], 'IsWarm': 0, 'MajorityClass': 3, 'SeenBothClasses': [0, 0, 0]} |
| 3.6 | 0.5 | 0.5 | {'AllBeta': [0.04222834665, 0.04222834665, 0.04222834665], 'AllBias': [0.1785217182, 0.1785217182, 0.1785217182], 'AllMu': [0, 0, 0], 'AllSigma': [1, 1, 1], 'AllMajorityClass': [2, 2, 2], 'AllCanPredict': [1, 1, 1], 'IsWarm': 0, 'MajorityClass': 3, 'SeenBothClasses': [0, 0, 0]} |
| 4 | -2 | -2 | {'AllBeta': [0.0522824452, 0.0522824452, 0.0522824452], 'AllBias': [0.199294742, 0.199294742, 0.199294742], 'AllMu': [0, 0, 0], 'AllSigma': [1, 1, 1], 'AllMajorityClass': [2, 2, 2], 'AllCanPredict': [1, 1, 1], 'IsWarm': 0, 'MajorityClass': 3, 'SeenBothClasses': [0, 0, 0]} |
| 4.4 | 0.5 | 0.5 | {'AllBeta': [0.0522824452, 0.0522824452, 0.0522824452], 'AllBias': [0.199294742, 0.199294742, 0.199294742], 'AllMu': [0, 0, 0], 'AllSigma': [1, 1, 1], 'AllMajorityClass': [2, 2, 2], 'AllCanPredict': [1, 1, 1], 'IsWarm': 0, 'MajorityClass': 3, 'SeenBothClasses': [0, 0, 0]} |
| 4.8 | -2 | -2 | {'AllBeta': [0.05377150527, 0.05377150527, 0.05377150527], 'AllBias': [0.2224425007, 0.2224425007, 0.2224425007], 'AllMu': [0, 0, 0], 'AllSigma': [1, 1, 1], 'AllMajorityClass': [2, 2, 2], 'AllCanPredict': [1, 1, 1], 'IsWarm': 0, 'MajorityClass': 3, 'SeenBothClasses': [0, 0, 0]} |
| 5.2 | 0.5 | 0.5 | {'AllBeta': [0.05377150527, 0.05377150527, 0.05377150527], 'AllBias': [0.2224425007, 0.2224425007, 0.2224425007], 'AllMu': [0, 0, 0], 'AllSigma': [1, 1, 1], 'AllMajorityClass': [2, 2, 2], 'AllCanPredict': [1, 1, 1], 'IsWarm': 0, 'MajorityClass': 3, 'SeenBothClasses': [0, 0, 0]} |
Every 4th of 60 samples, from the table 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) | — |
ramp | Ramp: slope 1 from t = 0 | — |
sine | Sine Wave: amplitude 1, 2 rad/s, no phase, no bias | — |
step | Step: 0 -> 1 at t = 1 s | — |
Plotted: table — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample
Category static · sample time 0.1 · 60 steps · commit 6e08e972e · produced by docsSample --out <folder> --blocks Incremental_Classification_ECOC_Fit Incremental_Classification_ECOC_Predict --steps 60 · data docs/generated/samples/Machine_Learning__Incremental_Learning__Incremental_Classification_ECOC_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).