pryvx 2.4.1__tar.gz → 2.4.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pryvx
3
- Version: 2.4.1
3
+ Version: 2.4.3
4
4
  Summary: A comprehensive package for privacy-enhancing technologies
5
5
  Home-page: UNKNOWN
6
6
  Author: PryvX (Jayesh Kenaudekar)
@@ -1,4 +1,5 @@
1
1
  from .psi import OPRF
2
2
  from .phe import PHE
3
3
  from .smpc import SMPC
4
- from .gdp import GDP
4
+ from .gdp import GDP
5
+ from .ldp import LDP
@@ -0,0 +1,36 @@
1
+ import grpc
2
+ from pryvx import pryvx_pb2
3
+ from pryvx import pryvx_pb2_grpc
4
+ from sklearn.linear_model import LogisticRegression
5
+ from sklearn.ensemble import RandomForestClassifier
6
+ import pickle
7
+
8
+
9
+ def train_logistic_classifier(features, labels):
10
+ model = LogisticRegression()
11
+ model.fit(features, labels)
12
+ serialized_model = pickle.dumps(model)
13
+ return serialized_model, model
14
+
15
+
16
+ def train_random_forest_classifier(features, labels):
17
+ model = RandomForestClassifier(n_estimators=100, random_state=42)
18
+ model.fit(features, labels)
19
+ serialized_model = pickle.dumps(model)
20
+ return serialized_model, model
21
+
22
+
23
+ def send_params(serialized_model, connection_url, client_id):
24
+
25
+ with grpc.insecure_channel(connection_url) as channel:
26
+ stub = pryvx_pb2_grpc.ModelServiceStub(channel)
27
+
28
+ # Attach metadata (client ID) in the request
29
+ metadata = (("client_id", client_id),)
30
+
31
+ model_params = pryvx_pb2.ModelParams(params=serialized_model)
32
+
33
+ response = stub.SendModelParams(model_params, metadata=metadata)
34
+
35
+ return f"✅ Model Params sent to server from {client_id}"
36
+
@@ -0,0 +1,20 @@
1
+ import numpy as np
2
+
3
+ def federated_ensemble(estimators, X_test):
4
+ """
5
+ Perform soft voting ensemble on a list of trained estimators.
6
+
7
+ :param estimators: List of trained models that support `predict_proba`
8
+ :param X_test: Test dataset (features only)
9
+ :return: Final predictions after soft voting
10
+ """
11
+ if not estimators:
12
+ raise ValueError("No models provided for ensemble.")
13
+
14
+ # Sum all probability predictions
15
+ avg_probs = sum(model.predict_proba(X_test) for model in estimators) / len(estimators)
16
+
17
+ # Convert probabilities to final predictions (highest probability wins)
18
+ y_pred_ensemble = np.argmax(avg_probs, axis=1)
19
+
20
+ return y_pred_ensemble
@@ -0,0 +1,51 @@
1
+ import grpc
2
+ from pryvx import pryvx_pb2
3
+ from pryvx import pryvx_pb2_grpc
4
+ import pickle
5
+ from concurrent import futures
6
+ import os
7
+ import datetime
8
+
9
+ # Directory to store received models
10
+ MODEL_SAVE_PATH = "received_models/"
11
+ os.makedirs(MODEL_SAVE_PATH, exist_ok=True)
12
+
13
+ class ModelServicer(pryvx_pb2_grpc.ModelServiceServicer):
14
+ def __init__(self):
15
+ self.client_models = {} # Store models from clients
16
+
17
+ def SendModelParams(self, request, context):
18
+ try:
19
+ # Extract metadata (client ID)
20
+ client_id = dict(context.invocation_metadata()).get("client_id", "unknown_client")
21
+
22
+ # Deserialize model received from client
23
+ model = pickle.loads(request.params)
24
+
25
+ # Assign a unique client ID
26
+ client_id = f"client_{len(self.client_models) + 1}"
27
+ self.client_models[client_id] = model
28
+
29
+ # Save model to disk
30
+ model_filename = os.path.join(MODEL_SAVE_PATH, f"{client_id}_model.pkl")
31
+ with open(model_filename, "wb") as f:
32
+
33
+ pickle.dump(model, f)
34
+
35
+ print(f"✅ Received and saved model from {client_id}")
36
+
37
+ return pryvx_pb2.ModelResponse(message=f"Model from {client_id} received and saved.")
38
+ except Exception as e:
39
+ print(f"❌ Error processing model: {e}")
40
+ return pryvx_pb2.ModelResponse(message="Failed to process model")
41
+
42
+
43
+ def start_server():
44
+ server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
45
+ pryvx_pb2_grpc.add_ModelServiceServicer_to_server(ModelServicer(), server)
46
+ server.add_insecure_port('[::]:50051')
47
+ server.start()
48
+ print("Server started. Listening on localhost:50051")
49
+
50
+ server.wait_for_termination()
51
+
@@ -0,0 +1,27 @@
1
+ import numpy as np
2
+
3
+ # Laplace Mechanism for continuous data.
4
+ # Gaussian Mechanism for continuous data (commonly used in GDP).
5
+
6
+ def laplace_mechanism(query_result, sensitivity, epsilon):
7
+ """Applies the Laplace mechanism for GDP."""
8
+ scale = sensitivity / epsilon
9
+ noise = np.random.laplace(0, scale, 1)
10
+ return query_result + noise[0]
11
+
12
+ def gaussian_mechanism(query_result, epsilon=0.5, delta=1e-5, sensitivity=1.0):
13
+ """Adds Gaussian noise to a global query result."""
14
+ sigma = np.sqrt(2 * np.log(1.25 / delta)) * sensitivity / epsilon
15
+ noise = np.random.normal(0, sigma)
16
+ return query_result + noise
17
+
18
+ class GDP:
19
+ @staticmethod
20
+ def add_noise(query_result, sensitivity, epsilon):
21
+ return laplace_mechanism(query_result, sensitivity, epsilon)
22
+
23
+ @staticmethod
24
+ def add_gaussian_noise(query_result):
25
+ return gaussian_mechanism(query_result)
26
+
27
+
@@ -0,0 +1,26 @@
1
+ import numpy as np
2
+ import random
3
+
4
+ # Laplace Mechanism (common for numeric data)
5
+ # Randomized Response (common for categorical/binary data)
6
+
7
+ def laplace_mechanism(value, epsilon, sensitivity=1.0):
8
+ """Adds Laplace noise to a numeric value for LDP."""
9
+ scale = sensitivity / epsilon
10
+ noise = np.random.laplace(0, scale)
11
+ return value + noise
12
+
13
+ def randomized_response(value, epsilon):
14
+ """Implements randomized response for binary data."""
15
+ p = np.exp(epsilon) / (1 + np.exp(epsilon))
16
+ return value if random.random() < p else 1 - value
17
+
18
+ class LDP:
19
+ @staticmethod
20
+ def add_numerical_noise(value, epsilon):
21
+ return laplace_mechanism(value, epsilon)
22
+
23
+ def add_categorical_noise(value, epsilon):
24
+ return randomized_response(value, epsilon)
25
+
26
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pryvx
3
- Version: 2.4.1
3
+ Version: 2.4.3
4
4
  Summary: A comprehensive package for privacy-enhancing technologies
5
5
  Home-page: UNKNOWN
6
6
  Author: PryvX (Jayesh Kenaudekar)
@@ -3,8 +3,10 @@ README.md
3
3
  setup.py
4
4
  pryvx/__init__.py
5
5
  pryvx/fl_client.py
6
+ pryvx/fl_ensemble.py
6
7
  pryvx/fl_server.py
7
8
  pryvx/gdp.py
9
+ pryvx/ldp.py
8
10
  pryvx/phe.py
9
11
  pryvx/pryvx_pb2.py
10
12
  pryvx/pryvx_pb2_grpc.py
@@ -1,6 +1,6 @@
1
1
  from setuptools import setup, find_packages
2
2
 
3
- VERSION = '2.4.1'
3
+ VERSION = '2.4.3'
4
4
 
5
5
 
6
6
  # Setting up
@@ -1,27 +0,0 @@
1
- import grpc
2
- from pryvx import pryvx_pb2
3
- from pryvx import pryvx_pb2_grpc
4
- from sklearn.linear_model import LogisticRegression
5
- import pickle
6
-
7
-
8
- def train(features, labels):
9
- model = LogisticRegression()
10
- model.fit(features, labels)
11
-
12
- serialized_model = pickle.dumps(model)
13
-
14
- return serialized_model
15
-
16
-
17
- def send_params(serialized_model, connection_url):
18
-
19
- with grpc.insecure_channel(connection_url) as channel:
20
- stub = pryvx_pb2_grpc.ModelServiceStub(channel)
21
-
22
- model_params = pryvx_pb2.ModelParams(params=serialized_model)
23
-
24
- response = stub.SendModelParams(model_params)
25
-
26
- return "Model Params sent to server"
27
-
@@ -1,31 +0,0 @@
1
- import grpc
2
- from pryvx import pryvx_pb2
3
- from pryvx import pryvx_pb2_grpc
4
- import pickle
5
- from concurrent import futures
6
-
7
- # Server
8
- class ModelServicer(pryvx_pb2_grpc.ModelServiceServicer):
9
- def __init__(self):
10
- self.client_params = {}
11
-
12
- def SendModelParams(self, request, context):
13
- # Deserialize the model
14
- loaded_model = pickle.loads(request.params)
15
-
16
- # save model to gcp storage bucket
17
-
18
- print("Received model params from client")
19
-
20
- return pryvx_pb2.ModelParams(params=request.params)
21
-
22
-
23
- def start_server():
24
- server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
25
- pryvx_pb2_grpc.add_ModelServiceServicer_to_server(ModelServicer(), server)
26
- server.add_insecure_port('[::]:50051')
27
- server.start()
28
- print("Server started. Listening on localhost:50051")
29
-
30
- server.wait_for_termination()
31
-
pryvx-2.4.1/pryvx/gdp.py DELETED
@@ -1,15 +0,0 @@
1
- import numpy as np
2
-
3
- def laplace_mechanism(true_value, sensitivity, epsilon):
4
- """Applies the Laplace mechanism for GDP."""
5
- scale = sensitivity / epsilon
6
- noise = np.random.laplace(0, scale, 1)
7
- return true_value + noise[0]
8
-
9
-
10
- class GDP:
11
- @staticmethod
12
- def add_noise(query_result, sensitivity, epsilon):
13
- return laplace_mechanism(query_result, sensitivity, epsilon)
14
-
15
-
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes