Skip to content

sklearn bridge

concrete_fhe_toolkit.ml.sklearn_bridge

Convert trained scikit-learn models into toolkit FHE models.

These helpers kill the manual scaling ritual: train with sklearn on clear data as usual, convert once, and run encrypted inference with the toolkit. scikit-learn is imported lazily, so it stays an optional dependency.

For linear models, scale quantizes coefficients. Inputs stay in the training coordinate system by default. To encode real inputs as integers, pass a separate input_scale and feed round(value * input_scale). Tree conversion uses its scale parameter for input thresholds.

from_sklearn_linear

from_sklearn_linear(model: Any, *, scale: int = 100, input_scale: int = 1) -> Any

[Client-Side Helper] Convert a fitted sklearn linear model into an FHE model.

LogisticRegression (binary) becomes an :class:FHELogisticRegression; LinearRegression (and other regressors exposing coef_/intercept_) become an :class:FHELinearRegression whose predictions are scaled by scale * input_scale. With the default input_scale=1, use integer features in exactly the coordinate system used during training. If you trained on already quantized data, do not quantize those inputs again.

Parameters:

Name Type Description Default
model Any

A fitted sklearn estimator with coef_ and intercept_.

required
scale int

The scaling factor applied to the fixed-point representation.

100
input_scale int

The fixed-point scaling factor of the input. inference. Bias and output scale account for both factors.

1

Returns:

Type Description
Any

A ready-to-compile toolkit model.

Example
from sklearn.linear_model import LogisticRegression
from concrete_fhe_toolkit.ml.sklearn_bridge import from_sklearn_linear

clf = LogisticRegression().fit(X_scaled, y)
fhe_model = from_sklearn_linear(clf, scale=100, input_scale=10)
# quantized_inputset/sample contain round(training_space_value * 10)
fhe_model.compile(quantized_inputset)
fhe_model.predict(quantized_sample)
Source code in src/concrete_fhe_toolkit/ml/sklearn_bridge.py
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
@client_side_helper
def from_sklearn_linear(
    model: Any, *, scale: int = 100, input_scale: int = 1
) -> Any:
    """[Client-Side Helper] Convert a fitted sklearn linear model into an FHE model.

    ``LogisticRegression`` (binary) becomes an
    :class:`FHELogisticRegression`; ``LinearRegression`` (and other
    regressors exposing ``coef_``/``intercept_``) become an
    :class:`FHELinearRegression` whose predictions are scaled by
    ``scale * input_scale``. With the default ``input_scale=1``, use integer
    features in exactly the coordinate system used during training. If you
    trained on already quantized data, do not quantize those inputs again.

    Args:
        model: A fitted sklearn estimator with ``coef_`` and ``intercept_``.
        scale: The scaling factor applied to the fixed-point representation.
        input_scale: The fixed-point scaling factor of the input.
            inference. Bias and output scale account for both factors.

    Returns:
        A ready-to-compile toolkit model.

    Example:
        ```python
        from sklearn.linear_model import LogisticRegression
        from concrete_fhe_toolkit.ml.sklearn_bridge import from_sklearn_linear

        clf = LogisticRegression().fit(X_scaled, y)
        fhe_model = from_sklearn_linear(clf, scale=100, input_scale=10)
        # quantized_inputset/sample contain round(training_space_value * 10)
        fhe_model.compile(quantized_inputset)
        fhe_model.predict(quantized_sample)
        ```
    """
    normalized_scale = validate_integer("scale", scale, minimum=1)
    source_scale = validate_integer("input_scale", input_scale, minimum=1)
    if not hasattr(model, "coef_") or not hasattr(model, "intercept_"):
        raise ValueError("model must be a fitted sklearn linear estimator")

    import numpy as np

    coefficients = np.atleast_2d(np.asarray(model.coef_))
    intercepts = np.atleast_1d(np.asarray(model.intercept_))
    if coefficients.shape[0] != 1:
        raise ValueError(
            "only binary/single-output linear models are supported; "
            "use one converted model per class for multi-class"
        )

    weights = [int(round(value * normalized_scale)) for value in coefficients[0]]
    bias = int(round(float(intercepts[0]) * normalized_scale * source_scale))

    is_classifier = hasattr(model, "classes_")
    if is_classifier:
        return FHELogisticRegression(
            weights, bias, 
            input_scale=source_scale, 
            output_scale=normalized_scale * source_scale
        )
    return FHELinearRegression(
        weights, bias, 
        input_scale=source_scale, 
        output_scale=normalized_scale * source_scale
    )

from_sklearn_tree

from_sklearn_tree(model: Any, *, scale: int = 1, leaf_scale: int = 1) -> Any

[Client-Side Helper] Convert a fitted sklearn decision tree into an :class:FHEDecisionTree.

Classification trees keep their majority-class integer leaves; regression trees get leaves quantized by leaf_scale. Thresholds are quantized by scale — quantize inference features with the same factor.

Parameters:

Name Type Description Default
model Any

A fitted sklearn decision tree model.

required
scale int

The scaling factor applied to the fixed-point representation.

1
leaf_scale int

Factor for quantizing leaf values. Defaults to 1.

1

Returns:

Name Type Description
Any Any

A ready-to-compile FHEDecisionTree model.

Raises:

Type Description
ValueError

If model is not a fitted sklearn decision tree.

Example
from sklearn.tree import DecisionTreeClassifier
from concrete_fhe_toolkit.ml.sklearn_bridge import from_sklearn_tree

clf = DecisionTreeClassifier(max_depth=3).fit(X_int, y)
fhe_tree = from_sklearn_tree(clf)
fhe_tree.compile(inputset)
Source code in src/concrete_fhe_toolkit/ml/sklearn_bridge.py
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
@client_side_helper
def from_sklearn_tree(model: Any, *, scale: int = 1, leaf_scale: int = 1) -> Any:
    """[Client-Side Helper] Convert a fitted sklearn decision tree into an :class:`FHEDecisionTree`.

    Classification trees keep their majority-class integer leaves;
    regression trees get leaves quantized by ``leaf_scale``. Thresholds are
    quantized by ``scale`` — quantize inference features with the same
    factor.

    Args:
        model (Any): A fitted sklearn decision tree model.
        scale (int, optional): The scaling factor applied to the fixed-point representation.
        leaf_scale (int, optional): Factor for quantizing leaf values. Defaults to 1.

    Returns:
        Any: A ready-to-compile FHEDecisionTree model.

    Raises:
        ValueError: If model is not a fitted sklearn decision tree.

    Example:
        ```python
        from sklearn.tree import DecisionTreeClassifier
        from concrete_fhe_toolkit.ml.sklearn_bridge import from_sklearn_tree

        clf = DecisionTreeClassifier(max_depth=3).fit(X_int, y)
        fhe_tree = from_sklearn_tree(clf)
        fhe_tree.compile(inputset)
        ```
    """
    normalized_scale = validate_integer("scale", scale, minimum=1)
    normalized_leaf_scale = validate_integer("leaf_scale", leaf_scale, minimum=1)
    if not hasattr(model, "tree_"):
        raise ValueError("model must be a fitted sklearn decision tree")
    tree_dict = _convert_tree_node(
        model.tree_, 0, scale=normalized_scale, leaf_scale=normalized_leaf_scale
    )
    return FHEDecisionTree(tree_dict)

from_sklearn_forest

from_sklearn_forest(model: Any, *, scale: int = 1) -> Any

[Client-Side Helper] Convert a fitted sklearn random-forest classifier into an :class:FHERandomForest (binary labels, majority vote).

Parameters:

Name Type Description Default
model Any

A fitted sklearn random forest model.

required
scale int

The scaling factor applied to the fixed-point representation.

1

Returns:

Name Type Description
Any Any

A ready-to-compile FHERandomForest model.

Raises:

Type Description
ValueError

If model is not a fitted sklearn forest.

Example
from sklearn.ensemble import RandomForestClassifier
from concrete_fhe_toolkit.ml.sklearn_bridge import from_sklearn_forest

clf = RandomForestClassifier(n_estimators=5, max_depth=3).fit(X_int, y)
fhe_forest = from_sklearn_forest(clf)
Source code in src/concrete_fhe_toolkit/ml/sklearn_bridge.py
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
@client_side_helper
def from_sklearn_forest(model: Any, *, scale: int = 1) -> Any:
    """[Client-Side Helper] Convert a fitted sklearn random-forest classifier into an
    :class:`FHERandomForest` (binary labels, majority vote).

    Args:
        model (Any): A fitted sklearn random forest model.
        scale (int, optional): The scaling factor applied to the fixed-point representation.

    Returns:
        Any: A ready-to-compile FHERandomForest model.

    Raises:
        ValueError: If model is not a fitted sklearn forest.

    Example:
        ```python
        from sklearn.ensemble import RandomForestClassifier
        from concrete_fhe_toolkit.ml.sklearn_bridge import from_sklearn_forest

        clf = RandomForestClassifier(n_estimators=5, max_depth=3).fit(X_int, y)
        fhe_forest = from_sklearn_forest(clf)
        ```
    """
    if not hasattr(model, "estimators_"):
        raise ValueError("model must be a fitted sklearn forest")
    trees: List[Any] = [
        from_sklearn_tree(estimator, scale=scale).tree
        for estimator in model.estimators_
    ]
    return FHERandomForest(trees)