Skip to content

Models

concrete_fhe_toolkit.ml.models

Encrypted inference helpers for simple ML models.

linear_regression_inference

linear_regression_inference(weights: Union[ndarray, List[Any]], bias: Any, features: Union[ndarray, List[Any]]) -> Any

Evaluate a linear regression model (dot product of weights and features plus bias).

Parameters:

Name Type Description Default
weights Union[ndarray, List[Any]]

The pre-trained cleartext model weights used for inference.

required
bias Any

The pre-trained cleartext model bias used for inference.

required
features Union[ndarray, List[Any]]

The encrypted 2D feature matrix containing input samples.

required

Returns:

Type Description
Any

The encrypted evaluation result.

Example
from concrete_fhe_toolkit.ml.models import linear_regression_inference

# Inside an FHE circuit
# prediction = linear_regression_inference(
#     weights=[2, -1], bias=5, features=[enc_f1, enc_f2]
# )
Source code in src/concrete_fhe_toolkit/ml/models.py
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
def linear_regression_inference(weights: Union[np.ndarray, List[Any]], bias: Any, features: Union[np.ndarray, List[Any]]) -> Any:
    """Evaluate a linear regression model (dot product of weights and features plus bias).

    Args:
        weights: The pre-trained cleartext model weights used for inference.
        bias: The pre-trained cleartext model bias used for inference.
        features: The encrypted 2D feature matrix containing input samples.

    Returns:
        The encrypted evaluation result.

    Example:
        ```python
        from concrete_fhe_toolkit.ml.models import linear_regression_inference

        # Inside an FHE circuit
        # prediction = linear_regression_inference(
        #     weights=[2, -1], bias=5, features=[enc_f1, enc_f2]
        # )
        ```
    """
    product = dot_product(weights, features)
    return bias + product

logistic_regression_inference

logistic_regression_inference(weights: Union[ndarray, List[Any]], bias: Any, features: Union[ndarray, List[Any]], *, threshold: int = 0) -> Any

Evaluate a logistic regression classifier on encrypted features.

Computes the linear score weights . features + bias and returns the binary class score >= threshold. Because the sigmoid is monotonic, thresholding the raw score at 0 is equivalent to thresholding the probability at 0.5, so no sigmoid lookup is needed for classification. Quantize weights and features to integers before calling. Bias and any nonzero threshold must use the product of the weight and feature scales.

Parameters:

Name Type Description Default
weights Union[ndarray, List[Any]]

The pre-trained cleartext model weights used for inference.

required
bias Any

The pre-trained cleartext model bias used for inference.

required
features Union[ndarray, List[Any]]

The encrypted 2D feature matrix containing input samples.

required
threshold int

The threshold for classification. Defaults to 0.

0

Returns:

Type Description
Any

The binary class prediction.

Example
from concrete_fhe_toolkit.ml.models import logistic_regression_inference

# Inside an FHE circuit
# class_pred = logistic_regression_inference(
#     weights=[3, 1], bias=-10, features=[enc_f1, enc_f2], threshold=0
# )
Source code in src/concrete_fhe_toolkit/ml/models.py
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
def logistic_regression_inference(
    weights: Union[np.ndarray, List[Any]],
    bias: Any,
    features: Union[np.ndarray, List[Any]],
    *,
    threshold: int = 0,
) -> Any:
    """Evaluate a logistic regression classifier on encrypted features.

    Computes the linear score ``weights . features + bias`` and returns the
    binary class ``score >= threshold``. Because the sigmoid is monotonic,
    thresholding the raw score at 0 is equivalent to thresholding the
    probability at 0.5, so no sigmoid lookup is needed for classification.
    Quantize weights and features to integers before calling. Bias and any
    nonzero threshold must use the product of the weight and feature scales.

    Args:
        weights: The pre-trained cleartext model weights used for inference.
        bias: The pre-trained cleartext model bias used for inference.
        features: The encrypted 2D feature matrix containing input samples.
        threshold: The threshold for classification. Defaults to 0.

    Returns:
        The binary class prediction.

    Example:
        ```python
        from concrete_fhe_toolkit.ml.models import logistic_regression_inference

        # Inside an FHE circuit
        # class_pred = logistic_regression_inference(
        #     weights=[3, 1], bias=-10, features=[enc_f1, enc_f2], threshold=0
        # )
        ```
    """
    score = linear_regression_inference(weights, bias, features)
    return threshold_activation(score, threshold)

decision_tree_node

decision_tree_node(feature_val: Any, threshold: Any, left_branch: Any, right_branch: Any) -> Any

Evaluate a single decision tree node.

Returns left_branch when feature_val >= threshold, otherwise right_branch. Branch values may be arbitrary bounded integers.

Parameters:

Name Type Description Default
feature_val Any

The feature value to compare.

required
threshold Any

The threshold to compare against.

required
left_branch Any

The value to return if feature_val >= threshold.

required
right_branch Any

The value to return if feature_val < threshold.

required

Returns:

Type Description
Any

The selected branch value.

Example
from concrete_fhe_toolkit.ml.models import decision_tree_node

# Inside an FHE circuit
# out = decision_tree_node(enc_feature, threshold=5, left_branch=1, right_branch=0)
Source code in src/concrete_fhe_toolkit/ml/models.py
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
def decision_tree_node(feature_val: Any, threshold: Any, left_branch: Any, right_branch: Any) -> Any:
    """Evaluate a single decision tree node.

    Returns ``left_branch`` when ``feature_val >= threshold``, otherwise
    ``right_branch``. Branch values may be arbitrary bounded integers.

    Args:
        feature_val: The feature value to compare.
        threshold: The threshold to compare against.
        left_branch: The value to return if feature_val >= threshold.
        right_branch: The value to return if feature_val < threshold.

    Returns:
        The selected branch value.

    Example:
        ```python
        from concrete_fhe_toolkit.ml.models import decision_tree_node

        # Inside an FHE circuit
        # out = decision_tree_node(enc_feature, threshold=5, left_branch=1, right_branch=0)
        ```
    """
    control = greater_equal(feature_val, threshold)
    return select(control, left_branch, right_branch)

majority_votes

majority_votes(predictions: Union[ndarray, List[Any]]) -> Any

Perform majority voting for an ensemble of binary predictions.

Parameters:

Name Type Description Default
predictions Union[ndarray, List[Any]]

A list or array of binary predictions.

required

Returns:

Type Description
Any

The majority vote result (1 if sum > len/2 else 0).

Example
from concrete_fhe_toolkit.ml.models import majority_votes

# Inside an FHE circuit
# final_pred = majority_votes([enc_pred1, enc_pred2, enc_pred3])
Source code in src/concrete_fhe_toolkit/ml/models.py
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
def majority_votes(predictions: Union[np.ndarray, List[Any]]) -> Any:
    """Perform majority voting for an ensemble of binary predictions.

    Args:
        predictions: A list or array of binary predictions.

    Returns:
        The majority vote result (1 if sum > len/2 else 0).

    Example:
        ```python
        from concrete_fhe_toolkit.ml.models import majority_votes

        # Inside an FHE circuit
        # final_pred = majority_votes([enc_pred1, enc_pred2, enc_pred3])
        ```
    """
    sum_predictions = array_sum(predictions)
    return greater(sum_predictions, len(predictions) // 2)

knn_inference

knn_inference(test_sample: Union[ndarray, List[Any]], train_samples: Union[ndarray, List[List[Any]]], train_labels: Union[ndarray, List[Any]], *, k: int = 1, max_distance: int = 15) -> Any

Evaluate a k-nearest-neighbor model on an encrypted test sample.

max_distance must be an upper bound on the squared Euclidean distance between the test sample and any training sample. The argmin reductions are built for that range, so distances above the bound silently corrupt the result.

With k=1 the nearest label is returned directly and labels may be arbitrary bounded integers. With k > 1 the labels must be binary (0/1) and the majority vote of the k nearest labels is returned; use an odd k to avoid ties (a tie resolves to 0).

The k > 1 path runs k argmin rounds, masking each selected neighbor with a distance penalty, so circuit cost grows linearly with k.

Parameters:

Name Type Description Default
test_sample Union[ndarray, List[Any]]

The encrypted test sample to classify.

required
train_samples Union[ndarray, List[List[Any]]]

The public training samples.

required
train_labels Union[ndarray, List[Any]]

The public training labels.

required
k int

The number of nearest neighbors to consider. Defaults to 1.

1
max_distance int

An upper bound on the squared Euclidean distance. Defaults to 15.

15

Returns:

Type Description
Any

The predicted label for the test sample.

Example
from concrete_fhe_toolkit.ml.models import knn_inference

# Inside an FHE circuit
# label = knn_inference(
#     enc_test_sample, public_train_samples, public_train_labels, k=3
# )
Source code in src/concrete_fhe_toolkit/ml/models.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
170
171
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
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
def knn_inference(
    test_sample: Union[np.ndarray, List[Any]],
    train_samples: Union[np.ndarray, List[List[Any]]],
    train_labels: Union[np.ndarray, List[Any]],
    *,
    k: int = 1,
    max_distance: int = 15,
) -> Any:
    """Evaluate a k-nearest-neighbor model on an encrypted test sample.

    ``max_distance`` must be an upper bound on the squared Euclidean distance
    between the test sample and any training sample. The argmin reductions
    are built for that range, so distances above the bound silently corrupt
    the result.

    With ``k=1`` the nearest label is returned directly and labels may be
    arbitrary bounded integers. With ``k > 1`` the labels must be binary
    (0/1) and the majority vote of the k nearest labels is returned; use an
    odd ``k`` to avoid ties (a tie resolves to 0).

    The k > 1 path runs k argmin rounds, masking each selected neighbor with
    a distance penalty, so circuit cost grows linearly with ``k``.

    Args:
        test_sample: The encrypted test sample to classify.
        train_samples: The public training samples.
        train_labels: The public training labels.
        k: The number of nearest neighbors to consider. Defaults to 1.
        max_distance: An upper bound on the squared Euclidean distance. Defaults to 15.

    Returns:
        The predicted label for the test sample.

    Example:
        ```python
        from concrete_fhe_toolkit.ml.models import knn_inference

        # Inside an FHE circuit
        # label = knn_inference(
        #     enc_test_sample, public_train_samples, public_train_labels, k=3
        # )
        ```
    """
    maximum_distance = validate_integer("max_distance", max_distance, minimum=1)
    normalized_k = validate_integer("k", k, minimum=1)
    if len(train_samples) != len(train_labels):
        raise ValueError("train_samples and train_labels must have the same length")
    if normalized_k > len(train_samples):
        raise ValueError("k cannot exceed the number of training samples")

    distances = [
        euclidean_distance_squared(row, test_sample)
        for row in train_samples
    ]

    if normalized_k == 1:
        argmin_func = make_argmin(len(distances), 0, maximum_distance)
        min_index = argmin_func(distances)

        prediction = 0
        for index, label in enumerate(train_labels):
            prediction += equal(index, min_index) * label

        return prediction

    # k > 1: iterated argmin. Each round the selected neighbor's distance is
    # pushed above max_distance so it cannot be selected again.
    penalty = maximum_distance + 1
    argmin_func = make_argmin(len(distances), 0, maximum_distance + penalty)
    current_distances = list(distances)
    votes = []

    for _ in range(normalized_k):
        min_index = argmin_func(current_distances)

        vote = 0
        next_distances = []
        for index, (distance, label) in enumerate(zip(current_distances, train_labels)):
            selected = equal(index, min_index)
            vote += selected * label
            next_distances.append(distance + selected * penalty)

        current_distances = next_distances
        votes.append(vote)

    return majority_votes(votes)

decision_tree_inference

decision_tree_inference(features: Union[ndarray, List[Any]], tree: Any) -> Any

Evaluate a full decision tree on encrypted features.

tree is a public structure. An internal node is a dict with keys "feature" (index into features), "threshold" (public integer), "left", and "right" (subtrees); a leaf is a plain integer label or value. The left branch is taken when features[feature] >= threshold.

Every path of the tree is evaluated obliviously, so the visited path is never revealed — circuit cost grows with the total number of nodes.

Parameters:

Name Type Description Default
features Union[ndarray, List[Any]]

The encrypted 2D feature matrix containing input samples.

required
tree Any

The public decision tree structure.

required

Returns:

Type Description
Any

The predicted value or label from the decision tree.

Example
from concrete_fhe_toolkit.ml.models import decision_tree_inference

# Public tree definition (trained offline)
tree = {
    "feature": 0, "threshold": 5, 
    "left": 1, "right": 0
}

# Inside an FHE circuit
# label = decision_tree_inference(enc_features, tree)
Source code in src/concrete_fhe_toolkit/ml/models.py
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
def decision_tree_inference(features: Union[np.ndarray, List[Any]], tree: Any) -> Any:
    """Evaluate a full decision tree on encrypted features.

    ``tree`` is a public structure. An internal node is a dict with keys
    ``"feature"`` (index into ``features``), ``"threshold"`` (public
    integer), ``"left"``, and ``"right"`` (subtrees); a leaf is a plain
    integer label or value. The left branch is taken when
    ``features[feature] >= threshold``.

    Every path of the tree is evaluated obliviously, so the visited path is
    never revealed — circuit cost grows with the total number of nodes.

    Args:
        features: The encrypted 2D feature matrix containing input samples.
        tree: The public decision tree structure.

    Returns:
        The predicted value or label from the decision tree.

    Example:
        ```python
        from concrete_fhe_toolkit.ml.models import decision_tree_inference

        # Public tree definition (trained offline)
        tree = {
            "feature": 0, "threshold": 5, 
            "left": 1, "right": 0
        }

        # Inside an FHE circuit
        # label = decision_tree_inference(enc_features, tree)
        ```
    """
    if not isinstance(tree, dict):
        return validate_integer("leaf value", tree)

    missing = {"feature", "threshold", "left", "right"} - tree.keys()
    if missing:
        raise ValueError(
            f"tree node is missing keys: {', '.join(sorted(missing))}"
        )

    feature_index = validate_integer("feature", tree["feature"], minimum=0)
    if feature_index >= len(features):
        raise ValueError("tree feature index is out of range for the feature vector")
    threshold = validate_integer("threshold", tree["threshold"])

    control = greater_equal(features[feature_index], threshold)
    left_value = decision_tree_inference(features, tree["left"])
    right_value = decision_tree_inference(features, tree["right"])
    return select(control, left_value, right_value)

compile_decision_tree_node

compile_decision_tree_node(min_value: int = -15, max_value: int = 15, *, configuration: Optional[Configuration] = None) -> fhe.Circuit

Compile a single encrypted decision tree node.

Parameters:

Name Type Description Default
min_value int

The lower bound for the encrypted inputs, used to dimension the FHE circuit.

-15
max_value int

The upper bound for the encrypted inputs, used to dimension the FHE circuit.

15
configuration Optional[Configuration]

Optional FHE compiler configuration object.

None

Returns:

Type Description
Circuit

The compiled FHE circuit.

Example
from concrete_fhe_toolkit.ml.models import compile_decision_tree_node

circuit = compile_decision_tree_node(min_value=-10, max_value=10)
# Allows evaluating one tree node completely obliviously
Source code in src/concrete_fhe_toolkit/ml/models.py
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
def compile_decision_tree_node(
    min_value: int = -15,
    max_value: int = 15,
    *,
    configuration: Optional[fhe.Configuration] = None,
) -> fhe.Circuit:
    """Compile a single encrypted decision tree node.

    Args:
        min_value: The lower bound for the encrypted inputs, used to dimension the FHE circuit.
        max_value: The upper bound for the encrypted inputs, used to dimension the FHE circuit.
        configuration: Optional FHE compiler configuration object.

    Returns:
        The compiled FHE circuit.

    Example:
        ```python
        from concrete_fhe_toolkit.ml.models import compile_decision_tree_node

        circuit = compile_decision_tree_node(min_value=-10, max_value=10)
        # Allows evaluating one tree node completely obliviously
        ```
    """
    minimum, maximum = validate_bounds(min_value, max_value)
    return compile_function(
        decision_tree_node,
        {
            "feature_val": "encrypted",
            "threshold": "encrypted",
            "left_branch": "encrypted",
            "right_branch": "encrypted",
        },
        [
            (minimum, minimum, minimum, minimum),
            (minimum, maximum, minimum, maximum),
            (maximum, minimum, maximum, minimum),
            (maximum, maximum, maximum, maximum),
        ],
        configuration,
    )

random_forest_inference

random_forest_inference(features: Union[ndarray, List[Any]], trees: Union[ndarray, List[Any]]) -> Any

Evaluate a random forest with binary (0/1) leaves via majority vote.

Each tree uses the public dict structure accepted by :func:decision_tree_inference. Use an odd number of trees to avoid ties (a tie resolves to 0).

Parameters:

Name Type Description Default
features Union[ndarray, List[Any]]

The encrypted 2D feature matrix containing input samples.

required
trees Union[ndarray, List[Any]]

A list of public decision trees.

required

Returns:

Type Description
Any

The predicted label from the random forest via majority voting.

Example
from concrete_fhe_toolkit.ml.models import random_forest_inference

# public_trees is a list of tree dictionaries
# Inside an FHE circuit
# label = random_forest_inference(enc_features, public_trees)
Source code in src/concrete_fhe_toolkit/ml/models.py
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
def random_forest_inference(features: Union[np.ndarray, List[Any]], trees: Union[np.ndarray, List[Any]]) -> Any:
    """Evaluate a random forest with binary (0/1) leaves via majority vote.

    Each tree uses the public dict structure accepted by
    :func:`decision_tree_inference`. Use an odd number of trees to avoid
    ties (a tie resolves to 0).

    Args:
        features: The encrypted 2D feature matrix containing input samples.
        trees: A list of public decision trees.

    Returns:
        The predicted label from the random forest via majority voting.

    Example:
        ```python
        from concrete_fhe_toolkit.ml.models import random_forest_inference

        # public_trees is a list of tree dictionaries
        # Inside an FHE circuit
        # label = random_forest_inference(enc_features, public_trees)
        ```
    """
    if not trees:
        raise ValueError("trees must contain at least one tree")
    predictions = [decision_tree_inference(features, tree) for tree in trees]
    return majority_votes(predictions)

mlp_inference

mlp_inference(features: Union[ndarray, List[Any]], layers: Union[ndarray, List[Any]]) -> Union[np.ndarray, List[Any]]

Evaluate a small multilayer perceptron with public integer weights.

layers is a list of (weights_matrix, biases) pairs. Hidden layers apply ReLU; the final layer stays linear and returns the raw score vector. Weights, biases, and features must share one integer scale; note that every layer multiplies scales together, so keep the network shallow or rescale between layers.

Parameters:

Name Type Description Default
features Union[ndarray, List[Any]]

The encrypted 2D feature matrix containing input samples.

required
layers Union[ndarray, List[Any]]

A list of (weights, biases) tuples for each layer.

required

Returns:

Type Description
Union[ndarray, List[Any]]

The output scores from the network.

Example
from concrete_fhe_toolkit.ml.models import mlp_inference

# layers = [(W1, b1), (W2, b2)] where Wi and bi are public lists
# Inside an FHE circuit
# scores = mlp_inference(enc_features, layers)
Source code in src/concrete_fhe_toolkit/ml/models.py
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
def mlp_inference(features: Union[np.ndarray, List[Any]], layers: Union[np.ndarray, List[Any]]) -> Union[np.ndarray, List[Any]]:
    """Evaluate a small multilayer perceptron with public integer weights.

    ``layers`` is a list of ``(weights_matrix, biases)`` pairs. Hidden
    layers apply ReLU; the final layer stays linear and returns the raw
    score vector. Weights, biases, and features must share one integer
    scale; note that every layer multiplies scales together, so keep the
    network shallow or rescale between layers.

    Args:
        features: The encrypted 2D feature matrix containing input samples.
        layers: A list of (weights, biases) tuples for each layer.

    Returns:
        The output scores from the network.

    Example:
        ```python
        from concrete_fhe_toolkit.ml.models import mlp_inference

        # layers = [(W1, b1), (W2, b2)] where Wi and bi are public lists
        # Inside an FHE circuit
        # scores = mlp_inference(enc_features, layers)
        ```
    """
    if not layers:
        raise ValueError("layers must contain at least one (weights, biases) pair")

    activations_vector = features
    for layer_index, (weights, biases) in enumerate(layers):
        if len(weights) != len(biases):
            raise ValueError("each layer needs one bias per output row")
        scores = np.matmul(weights, activations_vector)
        scores = np.add(scores, biases)
        if layer_index < len(layers) - 1:
            scores = np.maximum(scores, 0)
        activations_vector = scores
    return activations_vector

nearest_centroid_inference

nearest_centroid_inference(sample: Union[ndarray, List[Any]], centroids: Union[ndarray, List[List[Any]]], labels: Optional[Union[ndarray, List[Any]]] = None, *, max_distance: int = 15) -> Any

Assign an encrypted sample to the nearest public centroid (k-means step).

Returns the centroid index, or the matching label when labels is given. max_distance must bound the squared distance to any centroid.

Parameters:

Name Type Description Default
sample Union[ndarray, List[Any]]

The encrypted sample.

required
centroids Union[ndarray, List[List[Any]]]

A list of public centroids.

required
labels Optional[Union[ndarray, List[Any]]]

Optional labels for each centroid.

None
max_distance int

An upper bound on the squared distance. Defaults to 15.

15

Returns:

Type Description
Any

The index of the nearest centroid, or its corresponding label.

Example
from concrete_fhe_toolkit.ml.models import nearest_centroid_inference

# Inside an FHE circuit
# cluster_idx = nearest_centroid_inference(
#     enc_sample, public_centroids, max_distance=100
# )
Source code in src/concrete_fhe_toolkit/ml/models.py
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
def nearest_centroid_inference(
    sample: Union[np.ndarray, List[Any]],
    centroids: Union[np.ndarray, List[List[Any]]],
    labels: Optional[Union[np.ndarray, List[Any]]] = None,
    *,
    max_distance: int = 15,
) -> Any:
    """Assign an encrypted sample to the nearest public centroid (k-means step).

    Returns the centroid index, or the matching label when ``labels`` is
    given. ``max_distance`` must bound the squared distance to any centroid.

    Args:
        sample: The encrypted sample.
        centroids: A list of public centroids.
        labels: Optional labels for each centroid.
        max_distance: An upper bound on the squared distance. Defaults to 15.

    Returns:
        The index of the nearest centroid, or its corresponding label.

    Example:
        ```python
        from concrete_fhe_toolkit.ml.models import nearest_centroid_inference

        # Inside an FHE circuit
        # cluster_idx = nearest_centroid_inference(
        #     enc_sample, public_centroids, max_distance=100
        # )
        ```
    """
    maximum_distance = validate_integer("max_distance", max_distance, minimum=1)
    if not centroids:
        raise ValueError("centroids must contain at least one centroid")
    if labels is not None and len(labels) != len(centroids):
        raise ValueError("labels and centroids must have the same length")

    distances = [
        euclidean_distance_squared(centroid, sample)
        for centroid in centroids
    ]
    arg_min = make_argmin(len(distances), 0, maximum_distance)
    nearest_index = arg_min(distances)

    if labels is None:
        return nearest_index

    prediction: Any = 0
    for index, label in enumerate(labels):
        prediction = prediction + equal(index, nearest_index) * label
    return prediction

argmax_inference

argmax_inference(scores: Union[ndarray, List[Any]], min_score: int, max_score: int) -> Any

Return the index of the highest class score (multi-class head).

Parameters:

Name Type Description Default
scores Union[ndarray, List[Any]]

A list of scores to find the argmax of.

required
min_score int

The minimum possible score value.

required
max_score int

The maximum possible score value.

required

Returns:

Type Description
Any

The index of the maximum score.

Example
from concrete_fhe_toolkit.ml.models import argmax_inference

# Inside an FHE circuit
# pred_class = argmax_inference(enc_scores, min_score=0, max_score=50)
Source code in src/concrete_fhe_toolkit/ml/models.py
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
def argmax_inference(scores: Union[np.ndarray, List[Any]], min_score: int, max_score: int) -> Any:
    """Return the index of the highest class score (multi-class head).

    Args:
        scores: A list of scores to find the argmax of.
        min_score: The minimum possible score value.
        max_score: The maximum possible score value.

    Returns:
        The index of the maximum score.

    Example:
        ```python
        from concrete_fhe_toolkit.ml.models import argmax_inference

        # Inside an FHE circuit
        # pred_class = argmax_inference(enc_scores, min_score=0, max_score=50)
        ```
    """
    items = list(scores)
    if not items:
        raise ValueError("scores must contain at least one score")
    arg_max = make_argmax(len(items), min_score, max_score)
    return arg_max(items)

naive_bayes_inference

naive_bayes_inference(features: Union[ndarray, List[Any]], log_prob_tables: Union[ndarray, List[List[List[int]]]], priors: Union[ndarray, List[Any]], *, min_feature: int = 0) -> Any

Evaluate a categorical naive Bayes classifier on encrypted features.

log_prob_tables[class][feature] is a public list of scaled integer log-probabilities indexed by feature_value - min_feature; priors holds the scaled log-priors per class. Returns the encrypted index of the best class. Score bounds for the final argmax are derived from the public tables.

Parameters:

Name Type Description Default
features Union[ndarray, List[Any]]

The encrypted 2D feature matrix containing input samples.

required
log_prob_tables Union[ndarray, List[List[List[int]]]]

The lookup tables for log probabilities.

required
priors Union[ndarray, List[Any]]

The prior probabilities for each class.

required
min_feature int

The minimum value of features for offsetting the table. Defaults to 0.

0

Returns:

Type Description
Any

The predicted class index.

Example
from concrete_fhe_toolkit.ml.models import naive_bayes_inference

# Inside an FHE circuit
# pred_class = naive_bayes_inference(
#     enc_features, public_log_prob_tables, public_priors
# )
Source code in src/concrete_fhe_toolkit/ml/models.py
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
def naive_bayes_inference(
    features: Union[np.ndarray, List[Any]],
    log_prob_tables: Union[np.ndarray, List[List[List[int]]]],
    priors: Union[np.ndarray, List[Any]],
    *,
    min_feature: int = 0,
) -> Any:
    """Evaluate a categorical naive Bayes classifier on encrypted features.

    ``log_prob_tables[class][feature]`` is a public list of scaled integer
    log-probabilities indexed by ``feature_value - min_feature``; ``priors``
    holds the scaled log-priors per class. Returns the encrypted index of
    the best class. Score bounds for the final argmax are derived from the
    public tables.

    Args:
        features: The encrypted 2D feature matrix containing input samples.
        log_prob_tables: The lookup tables for log probabilities.
        priors: The prior probabilities for each class.
        min_feature: The minimum value of features for offsetting the table. Defaults to 0.

    Returns:
        The predicted class index.

    Example:
        ```python
        from concrete_fhe_toolkit.ml.models import naive_bayes_inference

        # Inside an FHE circuit
        # pred_class = naive_bayes_inference(
        #     enc_features, public_log_prob_tables, public_priors
        # )
        ```
    """
    if len(log_prob_tables) != len(priors):
        raise ValueError("log_prob_tables and priors must have the same length")
    if len(log_prob_tables) == 0:
        raise ValueError("at least one class is required")
    minimum_feature = validate_integer("min_feature", min_feature)

    scores = []
    lower_bounds = []
    upper_bounds = []
    for class_index, tables in enumerate(log_prob_tables):
        if len(tables) != len(features):
            raise ValueError("each class needs one table per feature")
        prior = validate_integer("prior", priors[class_index])
        score: Any = prior
        low = prior
        high = prior
        for feature_index, table in enumerate(tables):
            values = [validate_integer("log probability", value) for value in table]
            lookup = make_unary_lookup(values, minimum_feature)
            score = score + lookup(features[feature_index])
            low += min(values)
            high += max(values)
        scores.append(score)
        lower_bounds.append(low)
        upper_bounds.append(high)

    return argmax_inference(scores, min(lower_bounds), max(upper_bounds))

svm_inference

svm_inference(weights: Union[ndarray, List[Any]], bias: Any, features: Union[ndarray, List[Any]]) -> Any

Evaluate a linear Support Vector Machine (SVM) on encrypted features.

Returns 1 if the sample is on the positive side of the hyperplane, -1 if it's on the negative side, and 0 if it lies exactly on the boundary.

Parameters:

Name Type Description Default
weights Union[ndarray, List[Any]]

The pre-trained cleartext model weights used for inference.

required
bias Any

The pre-trained cleartext model bias used for inference.

required
features Union[ndarray, List[Any]]

The encrypted 2D feature matrix containing input samples.

required

Returns:

Type Description
Any

The predicted sign (-1, 0, or 1).

Example
from concrete_fhe_toolkit.ml.models import svm_inference

# Inside an FHE circuit
# sign_pred = svm_inference(public_weights, public_bias, enc_features)
Source code in src/concrete_fhe_toolkit/ml/models.py
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
def svm_inference(weights: Union[np.ndarray, List[Any]], bias: Any, features: Union[np.ndarray, List[Any]]) -> Any:
    """Evaluate a linear Support Vector Machine (SVM) on encrypted features.

    Returns 1 if the sample is on the positive side of the hyperplane,
    -1 if it's on the negative side, and 0 if it lies exactly on the boundary.

    Args:
        weights: The pre-trained cleartext model weights used for inference.
        bias: The pre-trained cleartext model bias used for inference.
        features: The encrypted 2D feature matrix containing input samples.

    Returns:
        The predicted sign (-1, 0, or 1).

    Example:
        ```python
        from concrete_fhe_toolkit.ml.models import svm_inference

        # Inside an FHE circuit
        # sign_pred = svm_inference(public_weights, public_bias, enc_features)
        ```
    """
    regression_result = linear_regression_inference(weights, bias, features)
    return sign(regression_result)

pca_inference

pca_inference(features: Union[ndarray, List[Any]], means: Union[ndarray, List[Any]], components: Union[ndarray, List[List[Any]]]) -> Union[np.ndarray, List[Any]]

Apply Principal Component Analysis (PCA) to reduce dimensionality of encrypted data.

Parameters:

Name Type Description Default
features Union[ndarray, List[Any]]

The encrypted 2D feature matrix containing input samples.

required
means Union[ndarray, List[Any]]

The public mean vector (list of integers).

required
components Union[ndarray, List[List[Any]]]

The public principal components matrix (list of lists of integers).

required

Returns:

Type Description
Union[ndarray, List[Any]]

The encrypted principal components vector (list of encrypted integers).

Example
from concrete_fhe_toolkit.ml.models import pca_inference

# Inside an FHE circuit
# enc_pca_features = pca_inference(enc_features, public_mean, public_components)
Source code in src/concrete_fhe_toolkit/ml/models.py
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
def pca_inference(features: Union[np.ndarray,List[Any]], means: Union[np.ndarray,List[Any]],components: Union[np.ndarray, List[List[Any]]]) -> Union[np.ndarray,List[Any]]:
    """Apply Principal Component Analysis (PCA) to reduce dimensionality of encrypted data.

    Args:
        features: The encrypted 2D feature matrix containing input samples.
        means: The public mean vector (list of integers).
        components: The public principal components matrix (list of lists of integers).

    Returns:
        The encrypted principal components vector (list of encrypted integers).

    Example:
        ```python
        from concrete_fhe_toolkit.ml.models import pca_inference

        # Inside an FHE circuit
        # enc_pca_features = pca_inference(enc_features, public_mean, public_components)
        ```
    """
    diffs = np.subtract(features,means)
    return np.matmul(components,diffs)

xgboost_inference

xgboost_inference(features: Union[ndarray, List[Any]], trees: Union[ndarray, List[Any]]) -> Any

Evaluate a XGBoost classifier on encrypted features.

Parameters:

Name Type Description Default
features Union[ndarray, List[Any]]

The encrypted 2D feature matrix containing input samples.

required
trees Union[ndarray, List[Any]]

The list of encrypted decision trees.

required

Returns:

Type Description
Any

The encrypted prediction of the XGBoost classifier.

Example
from concrete_fhe_toolkit.ml.models import xgboost_inference

# Inside an FHE circuit
# pred = xgboost_inference(enc_features, public_trees)
Source code in src/concrete_fhe_toolkit/ml/models.py
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
def xgboost_inference(features: Union[np.ndarray, List[Any]],trees: Union[np.ndarray, List[Any]]) -> Any:
    """
    Evaluate a XGBoost classifier on encrypted features.

    Args:
        features: The encrypted 2D feature matrix containing input samples.
        trees: The list of encrypted decision trees.

    Returns:
        The encrypted prediction of the XGBoost classifier.

    Example:
        ```python
        from concrete_fhe_toolkit.ml.models import xgboost_inference

        # Inside an FHE circuit
        # pred = xgboost_inference(enc_features, public_trees)
        ```
    """
    tree_sum = array_sum([decision_tree_inference(features, tree) for tree in trees])
    return greater(tree_sum,0)

cnn_inference

cnn_inference(filters: Union[ndarray, List[List[List[Any]]]], bias: Union[ndarray, List[Any]], image: Union[ndarray, List[List[List[Any]]]]) -> Any

Apply a 2D convolutional layer (CNN) to an encrypted image.

Parameters:

Name Type Description Default
filters Union[ndarray, List[List[List[Any]]]]

The convolutional filters.

required
bias Union[ndarray, List[Any]]

The pre-trained cleartext model bias used for inference.

required
image Union[ndarray, List[List[List[Any]]]]

The encrypted input image tensor.

required

Returns:

Type Description
Any

The flattened output feature map.

Example
from concrete_fhe_toolkit.ml.models import cnn_inference

# Inside an FHE circuit
# enc_feature_map = cnn_inference(public_filters, public_bias, enc_image)
Source code in src/concrete_fhe_toolkit/ml/models.py
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
def cnn_inference(filters: Union[np.ndarray, List[List[List[Any]]]], bias: Union[np.ndarray, List[Any]], image: Union[np.ndarray, List[List[List[Any]]]]) -> Any:
    """Apply a 2D convolutional layer (CNN) to an encrypted image.

    Args:
        filters: The convolutional filters.
        bias: The pre-trained cleartext model bias used for inference.
        image: The encrypted input image tensor.

    Returns:
        The flattened output feature map.

    Example:
        ```python
        from concrete_fhe_toolkit.ml.models import cnn_inference

        # Inside an FHE circuit
        # enc_feature_map = cnn_inference(public_filters, public_bias, enc_image)
        ```
    """
    img_tensor = np.expand_dims(image, axis=0)
    filters_tensor = np.expand_dims(filters, axis=1)
    out = fhe.conv(x=img_tensor, weight=filters_tensor, bias=bias)
    return out.flatten()       

max_pooling_2d

max_pooling_2d(image: Union[ndarray, List[List[List[Any]]]]) -> Any

Apply 2D max pooling (2x2 kernel, stride 2) to an encrypted feature map.

Parameters:

Name Type Description Default
image Union[ndarray, List[List[List[Any]]]]

The encrypted input image or feature map.

required

Returns:

Type Description
Any

The flattened pooled output feature map.

Example
from concrete_fhe_toolkit.ml.models import max_pooling_2d

# Inside an FHE circuit
# enc_pooled = max_pooling_2d(enc_image)
Source code in src/concrete_fhe_toolkit/ml/models.py
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
def max_pooling_2d(image: Union[np.ndarray, List[List[List[Any]]]]) -> Any:
    """Apply 2D max pooling (2x2 kernel, stride 2) to an encrypted feature map.

    Args:
        image: The encrypted input image or feature map.

    Returns:
        The flattened pooled output feature map.

    Example:
        ```python
        from concrete_fhe_toolkit.ml.models import max_pooling_2d

        # Inside an FHE circuit
        # enc_pooled = max_pooling_2d(enc_image)
        ```
    """
    img_tensor = np.expand_dims(image, axis=0)
    out = fhe.maxpool(x=img_tensor, kernel_shape=(2,2), strides=(2,2))
    return out.flatten()

avg_pooling_2d

avg_pooling_2d(image: Union[ndarray, List[List[List[Any]]]]) -> Any

Apply 2D average pooling (2x2 kernel, stride 2) to an encrypted feature map.

Parameters:

Name Type Description Default
image Union[ndarray, List[List[List[Any]]]]

The encrypted input image or feature map.

required

Returns:

Type Description
Any

The flattened pooled output feature map.

Example
from concrete_fhe_toolkit.ml.models import avg_pooling_2d

# Inside an FHE circuit
# enc_pooled = avg_pooling_2d(enc_image)
Source code in src/concrete_fhe_toolkit/ml/models.py
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
def avg_pooling_2d(image: Union[np.ndarray, List[List[List[Any]]]]) -> Any:
    """Apply 2D average pooling (2x2 kernel, stride 2) to an encrypted feature map.

    Args:
        image: The encrypted input image or feature map.

    Returns:
        The flattened pooled output feature map.

    Example:
        ```python
        from concrete_fhe_toolkit.ml.models import avg_pooling_2d

        # Inside an FHE circuit
        # enc_pooled = avg_pooling_2d(enc_image)
        ```
    """
    img_tensor = np.expand_dims(image, axis=0)
    filters_tensor = np.ones((1,1,2,2), dtype=int)
    out = fhe.conv(x=img_tensor, weight=filters_tensor, strides=(2,2)) // 4
    return out.flatten()

auto_quantizer

auto_quantizer(images: Union[ndarray, List[List[List[List[Any]]]]], filters: Union[ndarray, List[List[List[Any]]]], model: Any, mode: str = 'optimal') -> Any

Calculate the optimal scaling factor for quantizing network inputs/weights.

This helps keep intermediate multiplications within the FHE bit-width limit.

Parameters:

Name Type Description Default
images Union[ndarray, List[List[List[List[Any]]]]]

A list of input images.

required
filters Union[ndarray, List[List[List[Any]]]]

The convolutional filters.

required
model Any

The trained ML model.

required
mode str

The quantization mode, either "optimal" or "worst_case". Defaults to "optimal".

'optimal'

Returns:

Type Description
Any

The optimal scaling factor as an integer.

Example
from concrete_fhe_toolkit.ml.models import auto_quantizer

scale_factor = auto_quantizer(plain_images, plain_filters, sklearn_model)
Source code in src/concrete_fhe_toolkit/ml/models.py
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
@client_side_helper
def auto_quantizer(images: Union[np.ndarray, List[List[List[List[Any]]]]], filters: Union[np.ndarray, List[List[List[Any]]]], model: Any, mode: str="optimal") -> Any:
    """Calculate the optimal scaling factor for quantizing network inputs/weights.

    This helps keep intermediate multiplications within the FHE bit-width limit.

    Args:
        images: A list of input images.
        filters: The convolutional filters.
        model: The trained ML model.
        mode: The quantization mode, either "optimal" or "worst_case". Defaults to "optimal".

    Returns:
        The optimal scaling factor as an integer.

    Example:
        ```python
        from concrete_fhe_toolkit.ml.models import auto_quantizer

        scale_factor = auto_quantizer(plain_images, plain_filters, sklearn_model)
        ```
    """
    max_pixel_val = images[0][0][0][0]
    for image in images:
        for channel in image:
            for row in channel:
                for pixel in row:
                    max_pixel_val = max(abs(pixel),max_pixel_val)

    if mode == "optimal":
        weight_power = np.max(np.sum(np.abs(model.coef_), axis=1))
        filter_power = np.sum(np.abs(filters))
        cnn_pixel_count = 1
        num_of_features = 1

    elif mode == "worst_case":
        weight_power = np.max(np.abs(model.coef_))
        filter_power = filters[0][0][0]
        for filt in filters:
            for row in filt:
                for val in row:
                    filter_power = max(abs(val),filter_power)

        cnn_pixel_count = len(filters[0]) * len(filters[0][0])
        num_of_features = len(model.coef_[0])

    else:
        raise ValueError("mode should be optimal or worst_case")    

    max_product = max_pixel_val * filter_power * cnn_pixel_count * num_of_features * weight_power

    return max(1,int(32767 // max_product))