mirror of
https://github.com/luxfhe/ml-sdk.git
synced 2026-10-30 18:13:04 +00:00
Files edited: 150 Brand-hit files before: 163 Brand-hit files after: 28 Substitutions: - Zama Concrete ML -> TorusML - Zama Concrete / Concrete-> Torus - Zama fhEVM / fhEVM -> TorusEVM - Zama TFHE-rs / tfhe-rs -> Lux-FHE (github.com/luxfi/fhe) - Zama (attribution) -> Lux Industries - zama-ai/* (GitHub) -> luxfhe/* - @zama-fhe/* (npm) -> @luxfhe/* - docs.zama.ai -> docs.lux.network - Fhenix / CoFHE -> dropped or rewritten to Lux FHE / TorusEVM coprocessor Text-only changes. No runtime code semantics altered.
43 KiB
43 KiB
In [1]:
import time
import matplotlib.pyplot as plt
import numpy as np
from concrete.compiler import check_gpu_available
from joblib import Memory
from sklearn.datasets import fetch_openml
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split
from torch import nn
from concrete.ml.sklearn import NeuralNetClassifier
use_gpu_if_available = False
device = "cuda" if use_gpu_if_available and check_gpu_available() else "cpu"In [2]:
# scikit-learn's fetch_openml method doesn't handle local cache:
# https://github.com/scikit-learn/scikit-learn/issues/18783#issuecomment-723471498
# This is a workaround that prevents downloading the data every time the notebook is ran
memory = Memory("./data/MNIST")
fetch_openml_cached = memory.cache(fetch_openml)
# Fetch the MNIST data-set, with inputs already flattened
mnist_dataset = fetch_openml_cached("mnist_784")________________________________________________________________________________
[Memory] Calling sklearn.datasets._openml.fetch_openml...
fetch_openml('mnist_784')
____________________________________________________fetch_openml - 26.7s, 0.4min
In [3]:
# Define max, mean and std values for the MNIST data-set
max_value = 255
mean = 0.1307
std = 0.3081
# Normalize the training data
data = (mnist_dataset.data) / max_value
data = ((data - mean) / std).round(decimals=4)
# TorusML's NNs do not support: category, str, object types
# FIXME: https://github.com/luxfi/torusml-internal/issues/2990
target = mnist_dataset.target.astype("int")In [4]:
test_size = 10000
x_train, x_test, y_train, y_test = train_test_split(
data, target, test_size=test_size, random_state=0
)In [5]:
def plot_samples(data, targets, n_samples=5, title="Train target"):
# MNIST images are originally of shape 28x28 with grayscale values
samples_to_plot = np.array(data)[:n_samples].reshape((n_samples, 28, 28))
fig = plt.figure(figsize=(30, 30))
for i in range(n_samples):
subplot = fig.add_subplot(1, n_samples, i + 1)
subplot.set_title(f"{title}: {np.array(targets)[i]}", fontsize=15)
subplot.imshow(samples_to_plot[i], cmap="gray", interpolation="nearest")In [6]:
plot_samples(x_train, y_train)In [7]:
params = {
"module__n_layers": 2,
"module__n_w_bits": 4,
"module__n_a_bits": 4,
"module__n_hidden_neurons_multiplier": 0.5,
"module__activation_function": nn.ReLU,
"max_epochs": 7,
}
model = NeuralNetClassifier(**params)In [8]:
model.fit(X=x_train, y=y_train); epoch train_loss valid_acc valid_loss dur
------- ------------ ----------- ------------ ------
1 [36m0.4004[0m [32m0.9316[0m [35m0.2297[0m 4.8741
2 [36m0.2072[0m [32m0.9393[0m [35m0.2139[0m 3.9925
3 [36m0.1842[0m [32m0.9448[0m [35m0.1985[0m 3.9748
4 0.1972 0.9308 0.2337 4.1288
5 0.1864 [32m0.9458[0m 0.2055 4.0457
6 [36m0.1737[0m [32m0.9511[0m 0.2048 4.0543
7 [36m0.1628[0m 0.9412 0.2293 4.0349
In [9]:
y_preds_clear = model.predict(x_test, fhe="disable")
print(f"The test accuracy of the clear model is {accuracy_score(y_test, y_preds_clear):.2f}")The test accuracy of the clear model is 0.94
In [10]:
# Reduce the input-set's length to make the compilation time faster
# The input-set should be large enough to be representative of the input data
inputset = x_train.head(1000)
simulated_fhe_circuit = model.compile(inputset, device=device)
# Print the circuit's maximum bit-width reached during compilation
print(f"Circuit of {simulated_fhe_circuit.graph.maximum_integer_bit_width()}-bits (FHE simulation)")Circuit of 12-bits (FHE simulation)
In [11]:
# Evaluate the model using simulation
y_preds_simulated = model.predict(x_test, fhe="simulate")
print(
"The test accuracy (with FHE simulation) of the FHE model is "
f"{accuracy_score(y_test, y_preds_simulated):.2f}"
)The test accuracy (with FHE simulation) of the FHE model is 0.94
In [12]:
# Print the circuit's maximum bit-width reached during compilation
print(f"FHE circuit of {model.fhe_circuit.graph.maximum_integer_bit_width()}-bits")
time_begin = time.time()
model.fhe_circuit.client.keygen(force=True)
print(f"Key generation time: {time.time() - time_begin:.2f} seconds")FHE circuit of 12-bits
Key generation time: 1.85 seconds
In [13]:
# Reduce the test set
n_samples = 3
x_test_sample = x_test.head(n_samples)
y_test_sample = y_test.head(n_samples)
# Execute the predictions using FHE simulation on a few samples
simulated_fhe_predictions = model.predict(x_test_sample, fhe="simulate")
time_begin = time.time()
fhe_predictions = model.predict(x_test_sample, fhe="execute")
seconds_per_sample = (time.time() - time_begin) / len(x_test_sample)
print(f"Execution time in FHE: {seconds_per_sample:.2f} seconds per sample\n")
print("Expected values:", y_test_sample.tolist())
print("Simulated prediction values:", simulated_fhe_predictions)
print("FHE prediction values:", fhe_predictions)Execution time in FHE: 3.51 seconds per sample Expected values: [0, 4, 1] Simulated prediction values: [0 4 1] FHE prediction values: [0 4 1]