mirror of
https://github.com/luxfhe/ml-sdk.git
synced 2026-10-30 18:13:04 +00:00
Brand-only sweep. Touches READMEs, docs, package metadata, comments,
notebook markdown, requirements.txt files; does NOT yet touch Python
`concrete.*` imports (those are module-level dependencies requiring the
phase-2 Python module port from `concrete` → `torus`).
Substitutions applied:
Concrete ML → TorusML
concrete-ml → torus-ml
Concrete-ML → Torus-ML
concrete_ml → torus_ml
zama-ai/concrete-ml → luxfhe/ml-sdk
zama-ai/concrete → luxfhe/torus
github.com/zama-ai → github.com/luxfhe
docs.zama.ai/concrete-ml → docs.luxfhe.com/ml-sdk
docs.zama.ai/concrete → docs.luxfhe.com/torus
Zama Concrete ML → Lux TorusML
Zama Concrete → Lux Torus
Zama tfhe-rs / Zama TFHE-rs → Lux-FHE
tfhe-rs / TFHE-rs → Lux-FHE
Zama fhEVM / fhEVM → TorusEVM
Concrete framework → Torus framework
Concrete compiler → Torus compiler
Concrete by Zama → Torus by Lux
the Zama team → the Lux Industries team
Zama's → Lux Industries'
(Zama) → (Lux)
CoFHE / Fhenix → (removed)
LICENSE: original Zama copyright RETAINED per BSD-3-Clause-Clear §1-§2
requirements; Lux Industries modifications copyright added. Per §3 no
name of ZAMA used to endorse the derived work — product marketed
exclusively as TorusML.
README image URLs migrated to github.com/luxfhe/ml-sdk/assets to break
the dependency on Zama's CDN.
Hit count: 350 → 295. Residual hits are Python `from concrete.fhe import`
imports referencing the upstream Zama `concrete` PyPI package; these
require module-level port (phase 2):
Phase 2 plan:
1. Fork zama-ai/concrete (the Python compiler) to luxfhe/torus
2. Rename Python module `concrete` → `torus`; PyPI publish as `torus-fhe`
3. Update ml-sdk imports from `concrete.fhe` → `torus.fhe`, etc.
4. Wire `torus.compiler` GPU dispatch through `luxcpp/gpu` vtbl
(lux-private/gpu-kernels for CUDA/Metal/WebGPU/FPGA targets)
5. Port concrete-cuda + concrete-mlir kernels to
lux-private/gpu-kernels/{cuda,metal,wgsl}/ckks/ (matrix-vector
mul, rescale, rotate, bootstrap for TorusML inference)
Phase 3 plan (kernels):
- CKKS/BGV/BFV GPU kernels in lux-private/gpu-kernels/
(currently only TFHE PBS / keyswitch / blind-rotate exist)
- FPGA bitstreams in lux-private/fpga/ (currently scaffold only)
Phase 1 = docs/branding sweep. PR not opened; user reviews and merges.
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 concrete.ml.sklearn import KNeighborsClassifier as ConcreteKNeighborsClassifierIn [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
concrete_knn = ConcreteKNeighborsClassifier(n_bits=3, n_neighbors=n_neighbors)
# Fit both the TorusML and its equivalent float estimator on clear data
concrete_knn, sklearn_model = concrete_knn.fit_benchmark(X_train, y_train)In [4]:
time_begin = time.time()
circuit = concrete_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 = concrete_knn.predict(X_test, fhe="disable")
score_cml_clear = accuracy_score(y_test, pred_cml_clear)
# b- FHE simulation inference
pred_cml_simulate = concrete_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 = concrete_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"TorusML (clear) accuracy: {score_cml_clear:.2%}")
print(f"TorusML (FHE simulation) accuracy: {score_cml_simulate:.2%}")
print(f"TorusML FHE accuracy: {score_cml_fhe:.2%}")Sckit-learn accuracy: 50.00% TorusML (clear) accuracy: 37.50% TorusML (FHE simulation) accuracy: 37.50% TorusML 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 concrete 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 = concrete_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 (TorusML)"] != 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} (TorusML)": [list(row) for row in topk_labels_cml],
"Majority vote (TorusML)": 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 (TorusML) | Majority vote (TorusML) | 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 |