mirror of
https://github.com/luxfhe/docs.git
synced 2026-10-30 18:13:39 +00:00
33 KiB
33 KiB
In [1]:
import shutil
import time
from pathlib import Path
from tempfile import TemporaryDirectory
import numpy
import pandas
from concrete.ml.pandas import ClientEngine, load_encrypted_dataframe
from concrete.ml.pytest.utils import pandas_dataframe_are_equal
numpy.random.seed(0)
DATA_PATH = Path("data/encrypted_pandas")
# pylint: disable=pointless-statement, consider-using-withIn [2]:
CLIENT_1_DIR = DATA_PATH / "client_1"
df_left = pandas.read_csv(CLIENT_1_DIR / "df_left.csv")
df_leftOut [2]:
| index | total_bill | tip | sex | smoker | |
|---|---|---|---|---|---|
| 0 | client_1 | 12.54 | 2.50 | Male | No |
| 1 | client_2 | 11.17 | 1.50 | Female | No |
| 2 | client_3 | 20.29 | 2.75 | Female | No |
| 3 | client_4 | 14.07 | 2.50 | Male | No |
| 4 | client_5 | 15.69 | 3.00 | Male | Yes |
| 5 | client_6 | 18.29 | 3.00 | Male | No |
| 6 | client_7 | 16.93 | 3.07 | Female | No |
| 7 | client_8 | 24.27 | 2.03 | Male | Yes |
| 8 | client_9 | 8.77 | 2.00 | Male | No |
In [3]:
schema = {"index": {index_value: i + 1 for i, index_value in enumerate(df_left["index"].values)}}In [4]:
client_1_temp_dir = TemporaryDirectory(dir=str(CLIENT_1_DIR))
client_1_temp_path = Path(client_1_temp_dir.name)
# Define the directory where to store the serialized keys
client_1_keys_path = client_1_temp_path / "keys"
client_1 = ClientEngine(keys_path=client_1_keys_path)In [5]:
df_left_enc = client_1.encrypt_from_pandas(df_left, schema=schema)In [6]:
df_left_enc.get_schema()Out [6]:
| index | total_bill | tip | sex | smoker | |
|---|---|---|---|---|---|
| dtype | object | float64 | float64 | object | object |
| str_to_int | {'client_1': 1, 'client_2': 2, 'client_3': 3, ... | NaN | NaN | {'Male': 1, 'Female': 2} | {'No': 1, 'Yes': 2} |
| scale | NaN | 0.903226 | 8.917197 | NaN | NaN |
| zero_point | NaN | 6.92129 | 12.375796 | NaN | NaN |
In [7]:
df_left_enc_path = client_1_temp_path / "df_left_enc"
df_left_enc.save(df_left_enc_path)In [8]:
CLIENT_2_DIR = DATA_PATH / "client_2"
df_right = pandas.read_csv(CLIENT_2_DIR / "df_right.csv")
df_rightOut [8]:
| index | day | time | size | |
|---|---|---|---|---|
| 0 | client_2 | Thur | Lunch | 2 |
| 1 | client_5 | Sat | Dinner | 3 |
| 2 | client_9 | Sun | Dinner | 2 |
In [9]:
client_2_temp_dir = TemporaryDirectory(dir=str(CLIENT_2_DIR))
client_2_temp_path = Path(client_2_temp_dir.name)
# Define the directory where to store the serialized keys
client_2_keys_path = client_2_temp_path / "keys"
# Copy the first user's keys
shutil.copy2(client_1_keys_path, client_2_keys_path)
client_2 = ClientEngine(keys_path=client_2_keys_path)In [10]:
df_right_enc = client_2.encrypt_from_pandas(df_right, schema=schema)
df_right_encOut [10]:
| index | day | time | size |
|---|---|---|---|
| ..3a5cea3d89.. | ..5e1c826a69.. | ..a79208da47.. | ..4a46bbeabe.. |
| ..c959c81aa2.. | ..a992e555a0.. | ..ad73b4157e.. | ..947b705b07.. |
| ..ac944db8d7.. | ..76d5b0360e.. | ..c0544afe88.. | ..fa7f74cea1.. |
In [11]:
df_right_enc_path = client_2_temp_path / "df_right_enc"
df_right_enc.save(df_right_enc_path)In [12]:
df_left_enc = load_encrypted_dataframe(df_left_enc_path)
df_right_enc = load_encrypted_dataframe(df_right_enc_path)In [13]:
start = time.time()
df_joined_enc_server = df_left_enc.merge(df_right_enc, how="left", on="index")
end = time.time() - start
print(f"Total execution time: {end:.2f}s")Total execution time: 6.84s
In [14]:
df_joined_enc_server_path = client_1_temp_path / "df_joined_enc"
df_joined_enc_server.save(df_joined_enc_server_path)In [15]:
df_joined_enc = load_encrypted_dataframe(df_joined_enc_server_path)In [16]:
df_joined_cml = client_1.decrypt_to_pandas(df_joined_enc)
df_joined_cmlOut [16]:
| index | total_bill | tip | sex | smoker | day | time | size | |
|---|---|---|---|---|---|---|---|---|
| 0 | client_1 | 12.091429 | 2.509286 | Male | No | NaN | NaN | NaN |
| 1 | client_2 | 10.984286 | 1.500000 | Female | No | Thur | Lunch | 2.0 |
| 2 | client_3 | 19.841429 | 2.733571 | Female | No | NaN | NaN | NaN |
| 3 | client_4 | 14.305714 | 2.509286 | Male | No | NaN | NaN | NaN |
| 4 | client_5 | 15.412857 | 2.957857 | Male | Yes | Sat | Dinner | 3.0 |
| 5 | client_6 | 18.734286 | 2.957857 | Male | No | NaN | NaN | NaN |
| 6 | client_7 | 16.520000 | 3.070000 | Female | No | NaN | NaN | NaN |
| 7 | client_8 | 24.270000 | 2.060714 | Male | Yes | NaN | NaN | NaN |
| 8 | client_9 | 8.770000 | 1.948571 | Male | No | Sun | Dinner | 2.0 |
In [17]:
df_joined_pandas = pandas.merge(df_left, df_right, how="left", on="index")
df_joined_pandasOut [17]:
| index | total_bill | tip | sex | smoker | day | time | size | |
|---|---|---|---|---|---|---|---|---|
| 0 | client_1 | 12.54 | 2.50 | Male | No | NaN | NaN | NaN |
| 1 | client_2 | 11.17 | 1.50 | Female | No | Thur | Lunch | 2.0 |
| 2 | client_3 | 20.29 | 2.75 | Female | No | NaN | NaN | NaN |
| 3 | client_4 | 14.07 | 2.50 | Male | No | NaN | NaN | NaN |
| 4 | client_5 | 15.69 | 3.00 | Male | Yes | Sat | Dinner | 3.0 |
| 5 | client_6 | 18.29 | 3.00 | Male | No | NaN | NaN | NaN |
| 6 | client_7 | 16.93 | 3.07 | Female | No | NaN | NaN | NaN |
| 7 | client_8 | 24.27 | 2.03 | Male | Yes | NaN | NaN | NaN |
| 8 | client_9 | 8.77 | 2.00 | Male | No | Sun | Dinner | 2.0 |
In [18]:
df_are_equal = pandas_dataframe_are_equal(
df_joined_pandas, df_joined_cml, float_rtol=0.1, equal_nan=True
)
print("Concrete ML data-frame is equal to Pandas data-frame:", df_are_equal, "\n")Concrete ML data-frame is equal to Pandas data-frame: True
In [19]:
# Clean the temporary directories and their content
client_1_temp_dir.cleanup()
client_2_temp_dir.cleanup()