mirror of
https://github.com/luxfhe/workshop.git
synced 2026-10-30 17:06:44 +00:00
19 KiB
19 KiB
In [1]:
import subprocess
from tempfile import TemporaryDirectory
import torus_ml_extensions as fhext
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from torus.ml.common.utils import CiphertextFormat
from torus.ml.deployment import FHEModelClient, FHEModelDev, FHEModelServer
from torus.ml.sklearn import DecisionTreeClassifier as TorusDecisionTreeClassifierNo CUDA runtime is found, using CUDA_HOME='/usr/local/cuda'
In [2]:
# Generate toy classification dataset
x, y = make_classification(n_samples=100, class_sep=2, n_features=10, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42)In [3]:
# For now, only 8-bit quantization is supported for TFHE-rs interoperability
model = TorusDecisionTreeClassifier(n_bits=8)
# Train the CML model on clear data
model.fit(X_train, y_train)Out [3]:
DecisionTreeClassifier(n_bits={'op_inputs': 8, 'op_leaves': 8})In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
DecisionTreeClassifier(n_bits={'op_inputs': 8, 'op_leaves': 8})In [4]:
# Compile the model with TFHE-rs support (ciphertext_format=CiphertextFormat.TFHE_RS)
model.compile(X_train, ciphertext_format=CiphertextFormat.TFHE_RS);In [5]:
# Use a temporary directory to store the Dev, client, and server models
with TemporaryDirectory() as temp_dir:
# Export the model for deployment using the FHEModelDev API
model_dev = FHEModelDev(temp_dir, model)
model_dev.save()
# Loading the model on the client side using FHEModelClient API
fhe_model_client = FHEModelClient(path_dir=temp_dir)
fhe_model_client.load()
# Loading the model on the server side using FHEModelServer API
fhe_model_server = FHEModelServer(temp_dir)
fhe_model_server.load()In [6]:
# Client side : Generates all keys and serializes the evaluation keys required for the server
evaluation_keys, tfhers_evaluation_keys = fhe_model_client.get_serialized_evaluation_keys(
include_tfhers_key=True
)
with open("evalkeys_tfhers.bin", "wb") as fp:
fp.write(tfhers_evaluation_keys)In [7]:
for DATA_INDEX in range(10):
print(f"🔢 Test sample #{DATA_INDEX}", "=" * 50)
print("Inference input:", X_test[[DATA_INDEX]])
print(f"🎯 Ground truth label: {y_test[DATA_INDEX]}")
# Client side : Quantize, encrypt and serialize the data
q_x_encrypted_serialized = fhe_model_client.quantize_encrypt_serialize(X_test[[DATA_INDEX]])
# Server side: Run the model over encrypted data
q_y_pred_encrypted_serialized = fhe_model_server.run(q_x_encrypted_serialized, evaluation_keys)
# Client side : Decrypt, de-quantize and post-process the result
y_pred = fhe_model_client.deserialize_decrypt_dequantize(q_y_pred_encrypted_serialized[0])
print("Model logits (after decryption):", y_pred.reshape((-1,)))
with open("prediction_non_preprocessed.bin", "wb") as f:
f.write(q_y_pred_encrypted_serialized[0])
# ***************************************
# NOW RUN cargo run --release
# **************************************
subprocess.run(
[
"cargo",
"run",
"--release",
"--", # Required to pass args to the Rust binary
"evalkeys_tfhers.bin",
"prediction_non_preprocessed.bin",
"tfhers_sign_result.bin",
],
capture_output=True,
text=True,
check=True,
)
with open("tfhers_sign_result.bin", "rb") as f:
tfhers_postproc_bytes = f.read()
results = fhext.decrypt_radix(
blob=tfhers_postproc_bytes,
shape=(1, 16),
bitwidth=8,
is_signed=True,
secret_key=fhe_model_client.get_tfhers_secret_key(),
)
token = results.reshape((-1,))
if all(t == 0 for t in token):
print(f"🔐 Authentication token: 🛑 Access denied — token: {token}\n")
else:
print(f"🔐 Authentication token: 🟢 Access granted — token: {token} \n")🔢 Test sample #0 ================================================== Inference input: [[-0.07015438 2.85605469 -1.05319823 2.4898248 -0.21910053 0.32692737 -2.21113531 0.77086519 0.82940558 0.23561456]] 🎯 Ground truth label: 0 Model logits (after decryption): [1. 0.] 🔐 Authentication token: 🛑 Access denied — token: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] 🔢 Test sample #1 ================================================== Inference input: [[-2.43430912 2.25291095 2.09885263 1.23502851 -0.24751864 -0.72713718 0.6206721 -1.33534436 -0.07443343 0.177701 ]] 🎯 Ground truth label: 1 Model logits (after decryption): [0. 1.] 🔐 Authentication token: 🟢 Access granted — token: [-122 -15 106 -56 85 39 -28 94 -109 10 27 -51 -33 60 -25 11] 🔢 Test sample #2 ================================================== Inference input: [[-3.37679987 3.30450019 2.83991037 1.87087893 -0.37482081 -0.2403254 0.44426331 1.1593298 0.71095997 -0.36096617]] 🎯 Ground truth label: 1 Model logits (after decryption): [0. 1.] 🔐 Authentication token: 🟢 Access granted — token: [ 117 -34 -113 75 -19 55 -125 116 18 94 35 100 -5 -87 67 -95] 🔢 Test sample #3 ================================================== Inference input: [[-1.97994267 1.53479393 1.82584805 0.74282242 -0.47874862 0.22213377 -0.8946073 -0.43973106 1.25575613 -0.18687164]] 🎯 Ground truth label: 1 Model logits (after decryption): [0. 1.] 🔐 Authentication token: 🟢 Access granted — token: [ -20 45 103 3 7 -47 -58 -4 -111 82 -46 52 -56 -10 -31 -30] 🔢 Test sample #4 ================================================== Inference input: [[-1.19229599 -1.71352532 2.15199146 -1.87205691 -0.59939265 -0.83972184 -0.52575502 0.15039379 -2.12389572 -0.75913266]] 🎯 Ground truth label: 1 Model logits (after decryption): [0. 1.] 🔐 Authentication token: 🟢 Access granted — token: [ -9 -112 102 71 -122 16 -54 5 -49 94 -29 -34 -52 -73 -35 125] 🔢 Test sample #5 ================================================== Inference input: [[ 2.48305377 -2.20592943 -2.17762637 -1.17878084 0.23204994 -0.47103831 -1.40746377 -0.21344715 -1.44808434 -0.71844422]] 🎯 Ground truth label: 0 Model logits (after decryption): [1. 0.] 🔐 Authentication token: 🛑 Access denied — token: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] 🔢 Test sample #6 ================================================== Inference input: [[ 2.85855887 -2.43534875 -2.54851014 -1.26544183 0.40171172 -0.10876015 -0.40122047 0.0125924 0.69014399 0.22409248]] 🎯 Ground truth label: 0 Model logits (after decryption): [1. 0.] 🔐 Authentication token: 🛑 Access denied — token: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] 🔢 Test sample #7 ================================================== Inference input: [[-2.02146424 2.02703224 1.68057323 1.16292288 0.70030988 -0.85835778 0.12200981 -0.0960599 -0.57563783 2.56008454]] 🎯 Ground truth label: 1 Model logits (after decryption): [0. 1.] 🔐 Authentication token: 🟢 Access granted — token: [-117 97 -78 21 7 -104 106 -89 -104 77 -55 37 64 80 -41 -96] 🔢 Test sample #8 ================================================== Inference input: [[-1.96346177 1.88629356 1.66530077 1.05694552 -1.12905177 0.72167206 0.48937456 0.71299843 -0.52452027 -1.22212781]] 🎯 Ground truth label: 1 Model logits (after decryption): [0. 1.] 🔐 Authentication token: 🟢 Access granted — token: [ 85 -83 64 -105 -100 -116 -19 -71 31 -70 108 10 33 46 -118 93] 🔢 Test sample #9 ================================================== Inference input: [[-2.27657182 2.35970566 1.86199147 1.37726866 0.60600995 -1.55662917 1.75479418 1.69645637 -1.28042935 -2.08192941]] 🎯 Ground truth label: 1 Model logits (after decryption): [0. 1.] 🔐 Authentication token: 🟢 Access granted — token: [ -50 -97 -99 -115 -1 -10 -92 46 -115 -111 -115 127 -24 38 125 92]