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.
219 KiB
219 KiB
In [1]:
import time
import numpy as np
from sklearn.datasets import make_regression
from sklearn.linear_model import LinearRegression as SklearnLinearRegression
from sklearn.metrics import r2_score
from sklearn.model_selection import train_test_split
from torus.ml.sklearn import LinearRegression as TorusLinearRegressionIn [2]:
%matplotlib inline
import matplotlib.pyplot as plt
from IPython.display import display
train_plot_config = {"c": "black", "marker": "D", "s": 15, "label": "Train data"}
test_plot_config = {"c": "red", "marker": "x", "s": 15, "label": "Test data"}
def get_sklearn_plot_config(r2_score=None):
label = "Scikit-Learn"
if r2_score is not None:
label += f", {'$R^2$'}={r2_score:.4f}"
return {"c": "blue", "linewidth": 2.5, "label": label}
def get_torus_plot_config(r2_score=None):
label = "Torus ML"
if r2_score is not None:
label += f", {'$R^2$'}={r2_score:.4f}"
return {"c": "orange", "linewidth": 2.5, "label": label}In [3]:
# pylint: disable=unbalanced-tuple-unpacking
X, y = make_regression(
n_samples=200, n_features=1, n_targets=1, bias=5.0, noise=30.0, random_state=42
)
# pylint: enable=unbalanced-tuple-unpacking
# We split the data-set into a training and a testing set
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4, random_state=42)
# We sort the test set for a better visualization
sorted_indexes = np.argsort(np.squeeze(X_test))
X_test = X_test[sorted_indexes, :]
y_test = y_test[sorted_indexes]In [4]:
plt.ioff()
plt.clf()
fig, ax = plt.subplots(1, figsize=(10, 5))
fig.patch.set_facecolor("white")
ax.scatter(X_train, y_train, **train_plot_config)
ax.scatter(X_test, y_test, **test_plot_config)
ax.legend()
display(fig)In [5]:
sklearn_lr = SklearnLinearRegression()
sklearn_lr.fit(X_train, y_train)
y_pred = sklearn_lr.predict(X_test)
# Compute the R2 scores
sklearn_r2_score = r2_score(y_test, y_pred)In [6]:
plt.ioff()
plt.clf()
fig, ax = plt.subplots(1, figsize=(10, 5))
fig.patch.set_facecolor("white")
ax.scatter(X_train, y_train, **train_plot_config)
ax.scatter(X_test, y_test, **test_plot_config)
ax.plot(X_test, y_pred, **get_sklearn_plot_config(sklearn_r2_score))
ax.legend()
display(fig)In [7]:
# We quantize the inputs using 8-bits
torus_lr = TorusLinearRegression(n_bits=8)
# We train the torus linear regression model on clear data
torus_lr.fit(X_train, y_train)
# We densify the space representation of the original X,
# to better visualize the resulting step function in the following figure
x_space = np.linspace(X_test.min(), X_test.max(), num=300)
x_space = x_space[:, np.newaxis]
y_pred_q_space = torus_lr.predict(x_space)
# Now, we can test our Torus ML model on the clear test data
y_pred_q = torus_lr.predict(X_test)
# Compute the R2 scores
quantized_r2_score = r2_score(y_test, y_pred_q)In [8]:
plt.ioff()
plt.clf()
fig, ax = plt.subplots(1, figsize=(12, 8))
fig.patch.set_facecolor("white")
ax.scatter(X_train, y_train, **train_plot_config)
ax.scatter(X_test, y_test, **test_plot_config)
ax.plot(X_test, y_pred, **get_sklearn_plot_config(sklearn_r2_score))
ax.plot(x_space, y_pred_q_space, **get_torus_plot_config(quantized_r2_score))
ax.legend()
display(fig)In [9]:
fhe_circuit = torus_lr.compile(X_train)In [10]:
print(f"Generating a key for a {fhe_circuit.graph.maximum_integer_bit_width()}-bit circuit")Generating a key for a 9-bit circuit
In [11]:
time_begin = time.time()
fhe_circuit.client.keygen(force=False)
print(f"Key generation time: {time.time() - time_begin:.4f} seconds")Key generation time: 0.0002 seconds
In [12]:
time_begin = time.time()
y_pred_fhe = torus_lr.predict(X_test, fhe="execute")
print(f"Execution time: {(time.time() - time_begin) / len(X_test):.4f} seconds per sample")Execution time: 0.0033 seconds per sample
In [13]:
# Measure the FHE R2 score
fhe_r2_score = r2_score(y_test, y_pred_fhe)
print("R^2 scores:")
print(f"scikit-learn (clear): {sklearn_r2_score:.4f}")
print(f"Torus ML (quantized): {quantized_r2_score:.4f}")
print(f"Torus ML (FHE): {fhe_r2_score:.4f}")
# Measure the error of the FHE quantized model with respect to the clear scikit-learn float model
torus_score_difference = abs(fhe_r2_score - quantized_r2_score) * 100 / quantized_r2_score
print(
"\nRelative score difference for Torus ML (quantized clear) vs. Torus ML (FHE):",
f"{torus_score_difference:.2f}%",
)
# Measure the error of the FHE quantized model with respect to the clear float model
score_difference = abs(fhe_r2_score - sklearn_r2_score) * 100 / sklearn_r2_score
print(
"Relative score difference for scikit-learn (clear) vs. Torus ML (FHE) scores:",
f"{score_difference:.2f}%",
)R^2 scores: scikit-learn (clear): 0.9013 Torus ML (quantized): 0.8973 Torus ML (FHE): 0.8973 Relative score difference for Torus ML (quantized clear) vs. Torus ML (FHE): 0.00% Relative score difference for scikit-learn (clear) vs. Torus ML (FHE) scores: 0.45%
In [14]:
# For better visualization
y_pred_q_space = torus_lr.predict(x_space)In [15]:
plt.clf()
fig, ax = plt.subplots(1, figsize=(12, 8))
fig.patch.set_facecolor("white")
ax.scatter(X_train, y_train, **train_plot_config)
ax.scatter(X_test, y_test, **test_plot_config)
ax.plot(X_test, y_pred, **get_sklearn_plot_config(sklearn_r2_score))
ax.plot(x_space, y_pred_q_space, **get_torus_plot_config(fhe_r2_score))
ax.legend()
display(fig)