Generated reference › Gaussian Naive Bayes — Machine Learning/Classical Models
kind: generated#block#machine-learning-classical-models

Gaussian Naive Bayes — Machine Learning/Classical Models

Machine_Learning/Classical_Models/Gaussian_Naive_Bayes · 1 input / 2 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.

Gaussian Naive Bayes

Machine Learning / Classical Models

A fitted Gaussian naive Bayes classifier, evaluated one sample at a time. Each class scores the sample by its own per-feature Gaussian, and the highest score wins:

logp[k] = log(prior[k]) − ½ Σj [ log(2π·var[k][j]) + (u[j] − mu[k][j])² ÷ var[k][j] ]

This is sklearn.naive_bayes.GaussianNB with theta_, var_ and class_prior_ pasted in. It is the cheapest probabilistic classifier there is – no matrix inverse, no kernel, no tree walk – and it reports a calibrated-ish score per class rather than only a decision, which is what lets a controller refuse to act when nothing scored well.

Everything logarithmic is folded at configuration time, so the sample loop is subtract, square and multiply-accumulate and nothing else. That is what keeps this block synthesizable in fixed point.

Ports

  • u – the sample, a [d,1] column, where d is the number of COLUMNS of Class Means. One sample per step; it is checked rather than broadcast.
  • idx[1,1], the winning class, plus Index Base. This is what a controller switches on.
  • logp[K,1], every class's log-score in class order, where K is the number of ROWS of Class Means. The winner's own score is logp[idx], so nothing downstream has to recompute it; feed the whole vector to Softmax for posteriors, or to Confidence Gate or Top K for a decision with a threshold.

Parameters

  • Class Meansmu, a [K,d] matrix, one class per ROW. This is sklearn's theta_ orientation, so it pastes in without transposing. Its shape decides both K and d.
  • Class Variancesvar, [K,d] to match: sklearn's var_. Per class AND per feature – that the features are treated as independent within a class is exactly what makes the model "naive".
  • Class Priors[K,1], sklearn's class_prior_. Every entry must be greater than zero; a class with a zero prior can never win, and the log of it is not a number.
  • Variance Floor – the smallest variance used, applied before the reciprocal is taken. sklearn's var_smoothing exists for the same reason: a feature that never varied in training has zero variance and would divide by zero here. It is applied ONCE at configuration load, so it costs the generated code nothing.
  • Index Base – what the first class is numbered, spelled exactly as Argmax Decision and K Means Assign spell it:
    • Zero-based (PyTorch, numpy) – the first class is 0.
    • One-based (MATLAB) – the first class is 1.
  • 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. Every class's score is unrolled at export time, and the constants baked into it are the FOLDED ones – one c[k] per class carrying the log prior and all d log normalizers together, and one −½/var[k][j] per feature. No logarithm, no division and no exponential survives into the generated code.

The three HDL targets are therefore genuine synthesizable Q16.16, not the simulation-only real arithmetic this family's activation and distance blocks need: what is left in the datapath is a subtract, a square, a multiply and an add per feature, then a comparison chain.

Simulink bridge

None. Simulink's classifier blocks live in the Statistics and Machine Learning Toolbox, which is not installed on this machine – so there is no ClassificationNaiveBayes predict block here to map onto, and a bridge could not be verified even if it were written, since the parity suite would need that toolbox on the machine running it. Independently of that, those blocks take a fitted model OBJECT rather than parameter matrices, which no configuration value can carry across the bridge. The block therefore has no parity testbench, which is the documented consequence of Support::None. Code export verification still covers it across all ten languages.

Notes

  • Stateless and algebraic: the answer depends on the current sample only.
  • No state space: the score is quadratic in the input and the decision is a comparison, so no A/B/C/D describes it and model reduction correctly refuses the block.
  • Ties go to the LOWEST class index. The scan keeps its running best and replaces it only on a strictly greater score – the same rule Argmax Decision states and K Means Assign mirrors for its argmin. Every backend spells the identical scan, because the samples that tie are exactly the ones where two implementations that both "find the maximum" disagree.
  • The index is a DISCONTINUOUS function of the input. The three HDL targets compare Q16.16 values where the reference compares doubles, so two classes whose scores sit within one quantum (about 1.5×10−5) of each other can rank the other way round, and the index then differs by a whole step. That is a property of the block, not of the generated code; the logp output is continuous and does not have it.
  • Naive, and it says so in the name. The features are assumed independent within a class. When they are not, use Mahalanobis Distance or a Gaussian Mixture Model, which carry a full covariance.

Code facts#

FactValue
registered typeMachine_Learning/Classical_Models/Gaussian_Naive_Bayes
familyMachine_Learning/Classical_Models
solver environment classICoreBlock_0_Machine_Learning_1_Classical_Models_2_Gaussian_Naive_Bayes
sourcesrc/ICoreSDK/ICoreBlockLibrary/Blocks/Machine_Learning/Classical_Models/Gaussian_Naive_Bayes/ICoreBlock_0_Machine_Learning_1_Classical_Models_2_Gaussian_Naive_Bayes.cpp
headersrc/ICoreSDK/ICoreBlockLibrary/Blocks/Machine_Learning/Classical_Models/Gaussian_Naive_Bayes/ICoreBlock_0_Machine_Learning_1_Classical_Models_2_Gaussian_Naive_Bayes.h
default size on canvas134 × 88 px
ports at insert1 in, 2 out
code generators implementedPython, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Ports#

#DirectionSignal typeDescription label
1inICoreDoubleu
2outICoreDoubleidx
3outICoreDoublelogp

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
Class Means[0.4 -0.3; -0.6 0.8; 1.1 0.2]
Class Variances[0.5 0.7; 0.6 0.4; 0.8 0.55]
Class Priors[0.35; 0.4; 0.25]
Variance Floor1e-9
Index BaseZero-based (PyTorch, numpy)%~%One-based (MATLAB)~~Zero-ba…

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 Simulink equivalent available here: its naive Bayes predict block lives in the Statistics and Machine Learning Toolbox, which is not installed on this machine, so no mapping could be verified; and those blocks take a fitted model OBJECT rather than the parameter matrices this block configures

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

Gaussian Naive Bayes — a fitted GaussianNB evaluated at inference logp[k] = c[k] + SUM_j w[k][j] * (u[j] - mu[k][j])^2 idx = argmax_k logp[k] + base

Read the header before this file: it records the fold (every log is config-only, so none of it reaches the sample loop and the three HDL targets stay genuine Q16.16), the two-output shape, and the tie rule this block shares with Argmax_Decision and K_Means_Assign.

⚠ The FOLDED tables are what every generator emits -- _c and _w, never _means/_vars directly, and never anything a run has touched. The C++ reference below folds once in loadBlockConfig() and then computes from the same two tables, so the simulation and all ten exports evaluate the identical expression in the identical order.

Sample results#

No stimulus produced a sampled output in this rig — Invalid input size at: ICore Blocks/Home/Gaussian Naive Bayes. 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__Classical_Models__Gaussian_Naive_Bayes.json