mirror of
https://github.com/luxfi/torus-ml.git
synced 2026-10-30 15:15:23 +00:00
The distribution called itself torus-ml while shipping a package directory named concrete, so the name a user installs and the name they import disagreed — and most of the tree already said torus.ml, which could not resolve against src/concrete. Moved src/concrete to src/torus and pointed the include at it. The dependency was Zama's concrete-python from their index. It is torus-fhe from ours, which is what luxfhe/torus already ships: that frontend declares torus-fhe and ships a torus/fhe module, so every 'from torus.fhe' in this tree was already naming our compiler and only the dependency lagged. Two distributions share one namespace, which is the shape the upstream this forked from used and the reason the split works: torus-fhe gives torus.fhe, torus-ml gives torus.ml. Swept every other spelling — identifiers, enum members, workflow variables, filenames, notebooks. LICENSE and NOTICE keep the upstream attribution a fork owes; the figures carry the old name in JPEG metadata a text sweep cannot reach.
17 KiB
17 KiB
In [1]:
import time
import pandas as pd
from sklearn.datasets import make_classification
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split
from torus.ml.sklearn import KNeighborsClassifier as TorusKNeighborsClassifierIn [2]:
X, y = make_classification(
n_samples=15, n_features=3, n_informative=3, n_redundant=0, n_classes=2, n_clusters_per_class=1
)
# Split the data-set into a train and testing sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=42)In [3]:
n_neighbors = 3
torus_knn = TorusKNeighborsClassifier(n_bits=3, n_neighbors=n_neighbors)
# Fit both the Torus ML and its equivalent float estimator on clear data
torus_knn, sklearn_model = torus_knn.fit_benchmark(X_train, y_train)In [4]:
time_begin = time.time()
circuit = torus_knn.compile(X)
print(f"Compilation time: {time.time() - time_begin:.2f} seconds")Compilation time: 1.90 seconds
In [5]:
print(f"Maximum bit-width reached in the circuit: {circuit.graph.maximum_integer_bit_width()}")Maximum bit-width reached in the circuit: 8
In [6]:
# For circuits exceeding 8-bits, the key generation process might take up to an hour
time_begin = time.time()
circuit.client.keygen()
print(f"Key generation time: {time.time() - time_begin:.2f} seconds")Key generation time: 29.11 seconds
In [7]:
# a- Clear inference
pred_cml_clear = torus_knn.predict(X_test, fhe="disable")
score_cml_clear = accuracy_score(y_test, pred_cml_clear)
# b- FHE simulation inference
pred_cml_simulate = torus_knn.predict(X_test, fhe="simulate")
score_cml_simulate = accuracy_score(y_test, pred_cml_simulate)
# c- FHE inference
time_begin = time.time()
pred_cml_fhe = torus_knn.predict(X_test, fhe="execute")
print(f"FHE inference execution time: {(time.time() - time_begin) / len(X_test):.2f}s per sample")
score_cml_fhe = accuracy_score(y_test, pred_cml_fhe)FHE inference execution time: 22.42s per sample
In [8]:
# scikit-learn inference
predict_sklearn = sklearn_model.predict(X_test)
score_sklearn = accuracy_score(y_test, predict_sklearn)In [9]:
print(f"Sckit-learn accuracy: {score_sklearn:.2%}")
print(f"Torus ML (clear) accuracy: {score_cml_clear:.2%}")
print(f"Torus ML (FHE simulation) accuracy: {score_cml_simulate:.2%}")
print(f"Torus ML FHE accuracy: {score_cml_fhe:.2%}")Sckit-learn accuracy: 50.00% Torus ML (clear) accuracy: 37.50% Torus ML (FHE simulation) accuracy: 37.50% Torus ML FHE accuracy: 37.50%
In [10]:
# Retieve topk labels for the scikit-learn model
distance, topk_args = sklearn_model.kneighbors(X_test)
topk_labels_sk = y_train[topk_args]
# Retieve topk labels for the torus model
# `get_topk_labels` method is like `predict` method, but instead of returning the most common labels
# it provides the top K labels.
topk_labels_cml = torus_knn.get_topk_labels(X_test, fhe="simulate")In [11]:
def highlight_diff(row):
"""Custom style function to highlight mismatched predictions."""
return [
(
"background-color: yellow"
if row["Majority vote (Torus ML)"] != row["Majority vote (scikit-learn)"]
else ""
)
] * len(row)
df = pd.DataFrame(
{
"Distance": distance[:, 0],
f"Top{n_neighbors} (scikit-learn)": [list(row) for row in topk_labels_sk],
"Majority vote (scikit-learn)": predict_sklearn,
f"Top{n_neighbors} (Torus ML)": [list(row) for row in topk_labels_cml],
"Majority vote (Torus ML)": pred_cml_simulate,
"Ground truth": y_test,
}
)
df.style.apply(highlight_diff, axis=1)Out [11]:
| Distance | Top3 (scikit-learn) | Majority vote (scikit-learn) | Top3 (Torus ML) | Majority vote (Torus ML) | Ground truth | |
|---|---|---|---|---|---|---|
| 0 | 0.620442 | [1, 0, 0] | 0 | [1, 0, 0] | 0 | 0 |
| 1 | 1.098326 | [0, 1, 0] | 0 | [0, 1, 0] | 0 | 1 |
| 2 | 0.664202 | [0, 1, 0] | 0 | [0, 1, 1] | 1 | 0 |
| 3 | 2.122685 | [1, 0, 0] | 0 | [1, 0, 0] | 0 | 1 |
| 4 | 0.544631 | [0, 1, 0] | 0 | [0, 1, 0] | 0 | 0 |
| 5 | 1.728898 | [1, 0, 0] | 0 | [1, 0, 0] | 0 | 1 |
| 6 | 0.827317 | [1, 0, 0] | 0 | [1, 0, 0] | 0 | 1 |
| 7 | 2.644477 | [1, 1, 0] | 1 | [0, 1, 1] | 1 | 1 |