Open source / cross-runtime inference

A trained model should not need its training stack to make one prediction.

lgbm-to-code turns a supported LightGBM ensemble into readable Python, C++17, or JavaScript. The important part is not emitting source. It is checking that the emitted source follows the same tree paths and returns the same raw score.

03generated target languages
1e−12relative and absolute tolerance
09current repository tests
00generated runtime dependencies

Keep training in LightGBM. Move only the learned decisions.

Training still belongs in Python with LightGBM. At deployment, the package reads the fitted model’s dumped trees and writes ordinary conditionals for the target runtime.

01Trainfit in LightGBM
02Dumpread tree structure
03Emitplain source code
04Executecompare raw scores

The output is intentionally plain. A generated function accepts an ordered feature vector and adds the leaf value reached in each tree. There is no serialized model loader and no inference package to install in the target environment.

Generated code is tested by running it.

The current suite trains a 17-tree LightGBM regression model on 120 rows, preserves 40 rows for comparison, and includes missing values. It generates all three targets, then executes or compiles each one.

PYTHON

Execute the generated function

Load the emitted source into an isolated namespace and score every held-out row.

C++17

Compile before comparing

Build the emitted source with g++ and parse its double-precision output.

JAVASCRIPT

Run the ES module in Node

Restore missing values as NaN and execute every row through the generated module.

THE ASSERTION

Each result is compared with LightGBM’s predict(..., raw_score=True) using both relative and absolute tolerances of 1e−12. This verifies the tested model and rows; it is not a claim that every possible LightGBM model is supported.

Return the raw score. Do not guess the objective transform.

Tree traversal and output semantics are separate responsibilities. The generated function returns the ensemble’s raw score so the caller chooses the correct transform.

Regression

  • Raw score is ordinarily the prediction
  • Every tree contributes one leaf value
  • Full double-precision literals are retained

Binary classification

  • Raw score is the logit
  • The generated function does not claim probability
  • The caller applies the appropriate objective transform

The default branch is part of the model.

A threshold alone does not describe a LightGBM split. The generated condition must also preserve how that node treats NaN or zero and which child receives missing input.

NAN

Use the runtime’s NaN check

Python, C++17, and JavaScript each receive an explicit missing-value expression.

ZERO

Treat zero and NaN as missing

Nodes marked zero-as-missing route both values through the recorded default branch.

DIRECTION

Preserve default-left exactly

The emitted comparison changes with the node’s missing-value direction.

A narrow promise is easier to test honestly.

Accepted today

  • One-output LightGBM Booster objects
  • Fitted sklearn-style estimators
  • Numerical less-than-or-equal splits
  • None, NaN, and Zero missing routing
  • Validated generated function names

Rejected explicitly

  • Multiclass ensembles
  • Categorical splits
  • Malformed or unfitted models
  • Unknown missing-value modes
  • Unsupported target languages
CALLER RESPONSIBILITY

Generated code favors auditability and portability, not minimum code size or maximum throughput. The caller still owns feature ordering, schema validation, objective transforms, and deployment-specific performance testing.

06 / INSPECT IT

Read the conditionals and rerun the parity suite.

The current repository contains the cross-runtime verification work described here. PyPI hosts the earlier packaged release, so review the changelog and repository state when choosing which behavior to depend on.