flwr-nightly 1.12.0.dev20241007__py3-none-any.whl → 1.12.0.dev20241009__py3-none-any.whl
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.
Potentially problematic release.
This version of flwr-nightly might be problematic. Click here for more details.
- flwr/cli/new/new.py +2 -0
- flwr/cli/new/templates/app/code/client.jax.py.tpl +11 -17
- flwr/cli/new/templates/app/code/client.mlx.py.tpl +16 -36
- flwr/cli/new/templates/app/code/client.numpy.py.tpl +4 -5
- flwr/cli/new/templates/app/code/client.pytorch.py.tpl +8 -11
- flwr/cli/new/templates/app/code/client.sklearn.py.tpl +14 -48
- flwr/cli/new/templates/app/code/server.jax.py.tpl +9 -3
- flwr/cli/new/templates/app/code/server.mlx.py.tpl +13 -2
- flwr/cli/new/templates/app/code/server.numpy.py.tpl +7 -2
- flwr/cli/new/templates/app/code/server.pytorch.py.tpl +1 -1
- flwr/cli/new/templates/app/code/server.sklearn.py.tpl +13 -1
- flwr/cli/new/templates/app/code/task.jax.py.tpl +2 -2
- flwr/cli/new/templates/app/code/task.mlx.py.tpl +1 -1
- flwr/cli/new/templates/app/code/task.numpy.py.tpl +7 -0
- flwr/cli/new/templates/app/code/task.pytorch.py.tpl +3 -3
- flwr/cli/new/templates/app/code/task.sklearn.py.tpl +67 -0
- flwr/cli/new/templates/app/pyproject.jax.toml.tpl +3 -2
- flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +1 -0
- flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +2 -0
- flwr/common/constant.py +3 -0
- flwr/server/compat/driver_client_proxy.py +15 -29
- flwr/server/driver/inmemory_driver.py +5 -1
- flwr/server/superlink/state/in_memory_state.py +25 -0
- flwr/server/superlink/state/sqlite_state.py +41 -1
- {flwr_nightly-1.12.0.dev20241007.dist-info → flwr_nightly-1.12.0.dev20241009.dist-info}/METADATA +1 -1
- {flwr_nightly-1.12.0.dev20241007.dist-info → flwr_nightly-1.12.0.dev20241009.dist-info}/RECORD +29 -27
- {flwr_nightly-1.12.0.dev20241007.dist-info → flwr_nightly-1.12.0.dev20241009.dist-info}/LICENSE +0 -0
- {flwr_nightly-1.12.0.dev20241007.dist-info → flwr_nightly-1.12.0.dev20241009.dist-info}/WHEEL +0 -0
- {flwr_nightly-1.12.0.dev20241007.dist-info → flwr_nightly-1.12.0.dev20241009.dist-info}/entry_points.txt +0 -0
flwr/cli/new/new.py
CHANGED
|
@@ -240,6 +240,8 @@ def new(
|
|
|
240
240
|
MlFramework.HUGGINGFACE.value,
|
|
241
241
|
MlFramework.MLX.value,
|
|
242
242
|
MlFramework.TENSORFLOW.value,
|
|
243
|
+
MlFramework.SKLEARN.value,
|
|
244
|
+
MlFramework.NUMPY.value,
|
|
243
245
|
]
|
|
244
246
|
if framework_str in frameworks_with_tasks:
|
|
245
247
|
files[f"{import_name}/task.py"] = {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"""$project_name: A Flower / $framework_str app."""
|
|
2
2
|
|
|
3
3
|
import jax
|
|
4
|
-
from flwr.client import NumPyClient, ClientApp
|
|
5
|
-
from flwr.common import Context
|
|
6
4
|
|
|
5
|
+
from flwr.client import ClientApp, NumPyClient
|
|
6
|
+
from flwr.common import Context
|
|
7
7
|
from $import_name.task import (
|
|
8
8
|
evaluation,
|
|
9
9
|
get_params,
|
|
@@ -17,37 +17,31 @@ from $import_name.task import (
|
|
|
17
17
|
|
|
18
18
|
# Define Flower Client and client_fn
|
|
19
19
|
class FlowerClient(NumPyClient):
|
|
20
|
-
def __init__(self):
|
|
20
|
+
def __init__(self, input_dim):
|
|
21
21
|
self.train_x, self.train_y, self.test_x, self.test_y = load_data()
|
|
22
22
|
self.grad_fn = jax.grad(loss_fn)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
self.params = load_model(model_shape)
|
|
26
|
-
|
|
27
|
-
def get_parameters(self, config):
|
|
28
|
-
return get_params(self.params)
|
|
29
|
-
|
|
30
|
-
def set_parameters(self, parameters):
|
|
31
|
-
set_params(self.params, parameters)
|
|
23
|
+
self.params = load_model((input_dim,))
|
|
32
24
|
|
|
33
25
|
def fit(self, parameters, config):
|
|
34
|
-
self.
|
|
26
|
+
set_params(self.params, parameters)
|
|
35
27
|
self.params, loss, num_examples = train(
|
|
36
28
|
self.params, self.grad_fn, self.train_x, self.train_y
|
|
37
29
|
)
|
|
38
|
-
|
|
39
|
-
return parameters, num_examples, {"loss": float(loss)}
|
|
30
|
+
return get_params(self.params), num_examples, {"loss": float(loss)}
|
|
40
31
|
|
|
41
32
|
def evaluate(self, parameters, config):
|
|
42
|
-
self.
|
|
33
|
+
set_params(self.params, parameters)
|
|
43
34
|
loss, num_examples = evaluation(
|
|
44
35
|
self.params, self.grad_fn, self.test_x, self.test_y
|
|
45
36
|
)
|
|
46
37
|
return float(loss), num_examples, {"loss": float(loss)}
|
|
47
38
|
|
|
39
|
+
|
|
48
40
|
def client_fn(context: Context):
|
|
41
|
+
input_dim = context.run_config["input-dim"]
|
|
42
|
+
|
|
49
43
|
# Return Client instance
|
|
50
|
-
return FlowerClient().to_client()
|
|
44
|
+
return FlowerClient(input_dim).to_client()
|
|
51
45
|
|
|
52
46
|
|
|
53
47
|
# Flower ClientApp
|
|
@@ -3,17 +3,18 @@
|
|
|
3
3
|
import mlx.core as mx
|
|
4
4
|
import mlx.nn as nn
|
|
5
5
|
import mlx.optimizers as optim
|
|
6
|
-
from flwr.client import NumPyClient, ClientApp
|
|
7
|
-
from flwr.common import Context
|
|
8
6
|
|
|
7
|
+
from flwr.client import ClientApp, NumPyClient
|
|
8
|
+
from flwr.common import Context
|
|
9
|
+
from flwr.common.config import UserConfig
|
|
9
10
|
from $import_name.task import (
|
|
11
|
+
MLP,
|
|
10
12
|
batch_iterate,
|
|
11
13
|
eval_fn,
|
|
12
14
|
get_params,
|
|
13
15
|
load_data,
|
|
14
16
|
loss_fn,
|
|
15
17
|
set_params,
|
|
16
|
-
MLP,
|
|
17
18
|
)
|
|
18
19
|
|
|
19
20
|
|
|
@@ -22,37 +23,24 @@ class FlowerClient(NumPyClient):
|
|
|
22
23
|
def __init__(
|
|
23
24
|
self,
|
|
24
25
|
data,
|
|
25
|
-
|
|
26
|
-
hidden_dim,
|
|
26
|
+
run_config: UserConfig,
|
|
27
27
|
num_classes,
|
|
28
|
-
batch_size,
|
|
29
|
-
learning_rate,
|
|
30
|
-
num_epochs,
|
|
31
28
|
):
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
self.num_epochs =
|
|
29
|
+
num_layers = run_config["num-layers"]
|
|
30
|
+
hidden_dim = run_config["hidden-dim"]
|
|
31
|
+
input_dim = run_config["input-dim"]
|
|
32
|
+
batch_size = run_config["batch-size"]
|
|
33
|
+
learning_rate = run_config["lr"]
|
|
34
|
+
self.num_epochs = run_config["local-epochs"]
|
|
38
35
|
|
|
39
36
|
self.train_images, self.train_labels, self.test_images, self.test_labels = data
|
|
40
|
-
self.model = MLP(
|
|
41
|
-
num_layers, self.train_images.shape[-1], hidden_dim, num_classes
|
|
42
|
-
)
|
|
37
|
+
self.model = MLP(num_layers, input_dim, hidden_dim, num_classes)
|
|
43
38
|
self.optimizer = optim.SGD(learning_rate=learning_rate)
|
|
44
39
|
self.loss_and_grad_fn = nn.value_and_grad(self.model, loss_fn)
|
|
45
|
-
self.num_epochs = num_epochs
|
|
46
40
|
self.batch_size = batch_size
|
|
47
41
|
|
|
48
|
-
def get_parameters(self, config):
|
|
49
|
-
return get_params(self.model)
|
|
50
|
-
|
|
51
|
-
def set_parameters(self, parameters):
|
|
52
|
-
set_params(self.model, parameters)
|
|
53
|
-
|
|
54
42
|
def fit(self, parameters, config):
|
|
55
|
-
self.
|
|
43
|
+
set_params(self.model, parameters)
|
|
56
44
|
for _ in range(self.num_epochs):
|
|
57
45
|
for X, y in batch_iterate(
|
|
58
46
|
self.batch_size, self.train_images, self.train_labels
|
|
@@ -60,10 +48,10 @@ class FlowerClient(NumPyClient):
|
|
|
60
48
|
_, grads = self.loss_and_grad_fn(self.model, X, y)
|
|
61
49
|
self.optimizer.update(self.model, grads)
|
|
62
50
|
mx.eval(self.model.parameters(), self.optimizer.state)
|
|
63
|
-
return self.
|
|
51
|
+
return get_params(self.model), len(self.train_images), {}
|
|
64
52
|
|
|
65
53
|
def evaluate(self, parameters, config):
|
|
66
|
-
self.
|
|
54
|
+
set_params(self.model, parameters)
|
|
67
55
|
accuracy = eval_fn(self.model, self.test_images, self.test_labels)
|
|
68
56
|
loss = loss_fn(self.model, self.test_images, self.test_labels)
|
|
69
57
|
return loss.item(), len(self.test_images), {"accuracy": accuracy.item()}
|
|
@@ -73,18 +61,10 @@ def client_fn(context: Context):
|
|
|
73
61
|
partition_id = context.node_config["partition-id"]
|
|
74
62
|
num_partitions = context.node_config["num-partitions"]
|
|
75
63
|
data = load_data(partition_id, num_partitions)
|
|
76
|
-
|
|
77
|
-
num_layers = context.run_config["num-layers"]
|
|
78
|
-
hidden_dim = context.run_config["hidden-dim"]
|
|
79
64
|
num_classes = 10
|
|
80
|
-
batch_size = context.run_config["batch-size"]
|
|
81
|
-
learning_rate = context.run_config["lr"]
|
|
82
|
-
num_epochs = context.run_config["local-epochs"]
|
|
83
65
|
|
|
84
66
|
# Return Client instance
|
|
85
|
-
return FlowerClient(
|
|
86
|
-
data, num_layers, hidden_dim, num_classes, batch_size, learning_rate, num_epochs
|
|
87
|
-
).to_client()
|
|
67
|
+
return FlowerClient(data, context.run_config, num_classes).to_client()
|
|
88
68
|
|
|
89
69
|
|
|
90
70
|
# Flower ClientApp
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
"""$project_name: A Flower / $framework_str app."""
|
|
2
2
|
|
|
3
|
-
from flwr.client import
|
|
3
|
+
from flwr.client import ClientApp, NumPyClient
|
|
4
4
|
from flwr.common import Context
|
|
5
|
-
|
|
5
|
+
from $import_name.task import get_dummy_model
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class FlowerClient(NumPyClient):
|
|
9
|
-
def get_parameters(self, config):
|
|
10
|
-
return [np.ones((1, 1))]
|
|
11
9
|
|
|
12
10
|
def fit(self, parameters, config):
|
|
13
|
-
|
|
11
|
+
model = get_dummy_model()
|
|
12
|
+
return [model], 1, {}
|
|
14
13
|
|
|
15
14
|
def evaluate(self, parameters, config):
|
|
16
15
|
return float(0.0), 1, {"accuracy": float(1.0)}
|
|
@@ -1,17 +1,10 @@
|
|
|
1
1
|
"""$project_name: A Flower / $framework_str app."""
|
|
2
2
|
|
|
3
3
|
import torch
|
|
4
|
-
from flwr.client import NumPyClient, ClientApp
|
|
5
|
-
from flwr.common import Context
|
|
6
4
|
|
|
7
|
-
from
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
get_weights,
|
|
11
|
-
set_weights,
|
|
12
|
-
train,
|
|
13
|
-
test,
|
|
14
|
-
)
|
|
5
|
+
from flwr.client import ClientApp, NumPyClient
|
|
6
|
+
from flwr.common import Context
|
|
7
|
+
from $import_name.task import Net, get_weights, load_data, set_weights, test, train
|
|
15
8
|
|
|
16
9
|
|
|
17
10
|
# Define Flower Client and client_fn
|
|
@@ -32,7 +25,11 @@ class FlowerClient(NumPyClient):
|
|
|
32
25
|
self.local_epochs,
|
|
33
26
|
self.device,
|
|
34
27
|
)
|
|
35
|
-
return
|
|
28
|
+
return (
|
|
29
|
+
get_weights(self.net),
|
|
30
|
+
len(self.trainloader.dataset),
|
|
31
|
+
{"train_loss": train_loss},
|
|
32
|
+
)
|
|
36
33
|
|
|
37
34
|
def evaluate(self, parameters, config):
|
|
38
35
|
set_weights(self.net, parameters)
|
|
@@ -2,40 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
import warnings
|
|
4
4
|
|
|
5
|
-
import numpy as np
|
|
6
|
-
from flwr.client import NumPyClient, ClientApp
|
|
7
|
-
from flwr.common import Context
|
|
8
|
-
from flwr_datasets import FederatedDataset
|
|
9
|
-
from sklearn.linear_model import LogisticRegression
|
|
10
5
|
from sklearn.metrics import log_loss
|
|
11
6
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
return params
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def set_model_params(model, params):
|
|
25
|
-
model.coef_ = params[0]
|
|
26
|
-
if model.fit_intercept:
|
|
27
|
-
model.intercept_ = params[1]
|
|
28
|
-
return model
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def set_initial_params(model):
|
|
32
|
-
n_classes = 10 # MNIST has 10 classes
|
|
33
|
-
n_features = 784 # Number of features in dataset
|
|
34
|
-
model.classes_ = np.array([i for i in range(10)])
|
|
35
|
-
|
|
36
|
-
model.coef_ = np.zeros((n_classes, n_features))
|
|
37
|
-
if model.fit_intercept:
|
|
38
|
-
model.intercept_ = np.zeros((n_classes,))
|
|
7
|
+
from flwr.client import ClientApp, NumPyClient
|
|
8
|
+
from flwr.common import Context
|
|
9
|
+
from $import_name.task import (
|
|
10
|
+
get_model,
|
|
11
|
+
get_model_params,
|
|
12
|
+
load_data,
|
|
13
|
+
set_initial_params,
|
|
14
|
+
set_model_params,
|
|
15
|
+
)
|
|
39
16
|
|
|
40
17
|
|
|
41
18
|
class FlowerClient(NumPyClient):
|
|
@@ -46,9 +23,6 @@ class FlowerClient(NumPyClient):
|
|
|
46
23
|
self.y_train = y_train
|
|
47
24
|
self.y_test = y_test
|
|
48
25
|
|
|
49
|
-
def get_parameters(self, config):
|
|
50
|
-
return get_model_parameters(self.model)
|
|
51
|
-
|
|
52
26
|
def fit(self, parameters, config):
|
|
53
27
|
set_model_params(self.model, parameters)
|
|
54
28
|
|
|
@@ -57,7 +31,7 @@ class FlowerClient(NumPyClient):
|
|
|
57
31
|
warnings.simplefilter("ignore")
|
|
58
32
|
self.model.fit(self.X_train, self.y_train)
|
|
59
33
|
|
|
60
|
-
return
|
|
34
|
+
return get_model_params(self.model), len(self.X_train), {}
|
|
61
35
|
|
|
62
36
|
def evaluate(self, parameters, config):
|
|
63
37
|
set_model_params(self.model, parameters)
|
|
@@ -71,21 +45,13 @@ class FlowerClient(NumPyClient):
|
|
|
71
45
|
def client_fn(context: Context):
|
|
72
46
|
partition_id = context.node_config["partition-id"]
|
|
73
47
|
num_partitions = context.node_config["num-partitions"]
|
|
74
|
-
fds = FederatedDataset(dataset="mnist", partitioners={"train": num_partitions})
|
|
75
|
-
dataset = fds.load_partition(partition_id, "train").with_format("numpy")
|
|
76
|
-
|
|
77
|
-
X, y = dataset["image"].reshape((len(dataset), -1)), dataset["label"]
|
|
78
48
|
|
|
79
|
-
|
|
80
|
-
X_train, X_test = X[: int(0.8 * len(X))], X[int(0.8 * len(X)) :]
|
|
81
|
-
y_train, y_test = y[: int(0.8 * len(y))], y[int(0.8 * len(y)) :]
|
|
49
|
+
X_train, X_test, y_train, y_test = load_data(partition_id, num_partitions)
|
|
82
50
|
|
|
83
51
|
# Create LogisticRegression Model
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
warm_start=True, # prevent refreshing weights when fitting
|
|
88
|
-
)
|
|
52
|
+
penalty = context.run_config["penalty"]
|
|
53
|
+
local_epochs = context.run_config["local-epochs"]
|
|
54
|
+
model = get_model(penalty, local_epochs)
|
|
89
55
|
|
|
90
56
|
# Setting initial parameters, akin to model.compile for keras models
|
|
91
57
|
set_initial_params(model)
|
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
"""$project_name: A Flower / $framework_str app."""
|
|
2
2
|
|
|
3
|
-
from flwr.common import Context
|
|
4
|
-
from flwr.server.strategy import FedAvg
|
|
3
|
+
from flwr.common import Context, ndarrays_to_parameters
|
|
5
4
|
from flwr.server import ServerApp, ServerAppComponents, ServerConfig
|
|
5
|
+
from flwr.server.strategy import FedAvg
|
|
6
|
+
from $import_name.task import get_params, load_model
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
def server_fn(context: Context):
|
|
9
10
|
# Read from config
|
|
10
11
|
num_rounds = context.run_config["num-server-rounds"]
|
|
12
|
+
input_dim = context.run_config["input-dim"]
|
|
13
|
+
|
|
14
|
+
# Initialize global model
|
|
15
|
+
params = get_params(load_model((input_dim,)))
|
|
16
|
+
initial_parameters = ndarrays_to_parameters(params)
|
|
11
17
|
|
|
12
18
|
# Define strategy
|
|
13
|
-
strategy = FedAvg()
|
|
19
|
+
strategy = FedAvg(initial_parameters=initial_parameters)
|
|
14
20
|
config = ServerConfig(num_rounds=num_rounds)
|
|
15
21
|
|
|
16
22
|
return ServerAppComponents(strategy=strategy, config=config)
|
|
@@ -1,16 +1,27 @@
|
|
|
1
1
|
"""$project_name: A Flower / $framework_str app."""
|
|
2
2
|
|
|
3
|
-
from flwr.common import Context
|
|
3
|
+
from flwr.common import Context, ndarrays_to_parameters
|
|
4
4
|
from flwr.server import ServerApp, ServerAppComponents, ServerConfig
|
|
5
5
|
from flwr.server.strategy import FedAvg
|
|
6
|
+
from $import_name.task import MLP, get_params
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
def server_fn(context: Context):
|
|
9
10
|
# Read from config
|
|
10
11
|
num_rounds = context.run_config["num-server-rounds"]
|
|
11
12
|
|
|
13
|
+
num_classes = 10
|
|
14
|
+
num_layers = context.run_config["num-layers"]
|
|
15
|
+
input_dim = context.run_config["input-dim"]
|
|
16
|
+
hidden_dim = context.run_config["hidden-dim"]
|
|
17
|
+
|
|
18
|
+
# Initialize global model
|
|
19
|
+
model = MLP(num_layers, input_dim, hidden_dim, num_classes)
|
|
20
|
+
params = get_params(model)
|
|
21
|
+
initial_parameters = ndarrays_to_parameters(params)
|
|
22
|
+
|
|
12
23
|
# Define strategy
|
|
13
|
-
strategy = FedAvg()
|
|
24
|
+
strategy = FedAvg(initial_parameters=initial_parameters)
|
|
14
25
|
config = ServerConfig(num_rounds=num_rounds)
|
|
15
26
|
|
|
16
27
|
return ServerAppComponents(strategy=strategy, config=config)
|
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
"""$project_name: A Flower / $framework_str app."""
|
|
2
2
|
|
|
3
|
-
from flwr.common import Context
|
|
3
|
+
from flwr.common import Context, ndarrays_to_parameters
|
|
4
4
|
from flwr.server import ServerApp, ServerAppComponents, ServerConfig
|
|
5
5
|
from flwr.server.strategy import FedAvg
|
|
6
|
+
from $import_name.task import get_dummy_model
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
def server_fn(context: Context):
|
|
9
10
|
# Read from config
|
|
10
11
|
num_rounds = context.run_config["num-server-rounds"]
|
|
11
12
|
|
|
13
|
+
# Initial model
|
|
14
|
+
model = get_dummy_model()
|
|
15
|
+
dummy_parameters = ndarrays_to_parameters([model])
|
|
16
|
+
|
|
12
17
|
# Define strategy
|
|
13
|
-
strategy = FedAvg()
|
|
18
|
+
strategy = FedAvg(initial_parameters=dummy_parameters)
|
|
14
19
|
config = ServerConfig(num_rounds=num_rounds)
|
|
15
20
|
|
|
16
21
|
return ServerAppComponents(strategy=strategy, config=config)
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
from flwr.common import Context, ndarrays_to_parameters
|
|
4
4
|
from flwr.server import ServerApp, ServerAppComponents, ServerConfig
|
|
5
5
|
from flwr.server.strategy import FedAvg
|
|
6
|
-
|
|
7
6
|
from $import_name.task import Net, get_weights
|
|
8
7
|
|
|
9
8
|
|
|
@@ -27,5 +26,6 @@ def server_fn(context: Context):
|
|
|
27
26
|
|
|
28
27
|
return ServerAppComponents(strategy=strategy, config=config)
|
|
29
28
|
|
|
29
|
+
|
|
30
30
|
# Create ServerApp
|
|
31
31
|
app = ServerApp(server_fn=server_fn)
|
|
@@ -1,19 +1,31 @@
|
|
|
1
1
|
"""$project_name: A Flower / $framework_str app."""
|
|
2
2
|
|
|
3
|
-
from flwr.common import Context
|
|
3
|
+
from flwr.common import Context, ndarrays_to_parameters
|
|
4
4
|
from flwr.server import ServerApp, ServerAppComponents, ServerConfig
|
|
5
5
|
from flwr.server.strategy import FedAvg
|
|
6
|
+
from $import_name.task import get_model, get_model_params, set_initial_params
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
def server_fn(context: Context):
|
|
9
10
|
# Read from config
|
|
10
11
|
num_rounds = context.run_config["num-server-rounds"]
|
|
11
12
|
|
|
13
|
+
# Create LogisticRegression Model
|
|
14
|
+
penalty = context.run_config["penalty"]
|
|
15
|
+
local_epochs = context.run_config["local-epochs"]
|
|
16
|
+
model = get_model(penalty, local_epochs)
|
|
17
|
+
|
|
18
|
+
# Setting initial parameters, akin to model.compile for keras models
|
|
19
|
+
set_initial_params(model)
|
|
20
|
+
|
|
21
|
+
initial_parameters = ndarrays_to_parameters(get_model_params(model))
|
|
22
|
+
|
|
12
23
|
# Define strategy
|
|
13
24
|
strategy = FedAvg(
|
|
14
25
|
fraction_fit=1.0,
|
|
15
26
|
fraction_evaluate=1.0,
|
|
16
27
|
min_available_clients=2,
|
|
28
|
+
initial_parameters=initial_parameters,
|
|
17
29
|
)
|
|
18
30
|
config = ServerConfig(num_rounds=num_rounds)
|
|
19
31
|
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
import jax
|
|
4
4
|
import jax.numpy as jnp
|
|
5
|
+
import numpy as np
|
|
5
6
|
from sklearn.datasets import make_regression
|
|
6
7
|
from sklearn.model_selection import train_test_split
|
|
7
|
-
import numpy as np
|
|
8
8
|
|
|
9
9
|
key = jax.random.PRNGKey(0)
|
|
10
10
|
|
|
@@ -33,7 +33,7 @@ def train(params, grad_fn, X, y):
|
|
|
33
33
|
num_examples = X.shape[0]
|
|
34
34
|
for epochs in range(50):
|
|
35
35
|
grads = grad_fn(params, X, y)
|
|
36
|
-
params = jax.
|
|
36
|
+
params = jax.tree.map(lambda p, g: p - 0.05 * g, params, grads)
|
|
37
37
|
loss = loss_fn(params, X, y)
|
|
38
38
|
return params, loss, num_examples
|
|
39
39
|
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
import mlx.core as mx
|
|
4
4
|
import mlx.nn as nn
|
|
5
5
|
import numpy as np
|
|
6
|
-
from datasets.utils.logging import disable_progress_bar
|
|
7
6
|
from flwr_datasets import FederatedDataset
|
|
8
7
|
from flwr_datasets.partitioner import IidPartitioner
|
|
9
8
|
|
|
9
|
+
from datasets.utils.logging import disable_progress_bar
|
|
10
10
|
|
|
11
11
|
disable_progress_bar()
|
|
12
12
|
|
|
@@ -5,10 +5,10 @@ from collections import OrderedDict
|
|
|
5
5
|
import torch
|
|
6
6
|
import torch.nn as nn
|
|
7
7
|
import torch.nn.functional as F
|
|
8
|
-
from torch.utils.data import DataLoader
|
|
9
|
-
from torchvision.transforms import Compose, Normalize, ToTensor
|
|
10
8
|
from flwr_datasets import FederatedDataset
|
|
11
9
|
from flwr_datasets.partitioner import IidPartitioner
|
|
10
|
+
from torch.utils.data import DataLoader
|
|
11
|
+
from torchvision.transforms import Compose, Normalize, ToTensor
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class Net(nn.Module):
|
|
@@ -67,7 +67,7 @@ def train(net, trainloader, epochs, device):
|
|
|
67
67
|
"""Train the model on the training set."""
|
|
68
68
|
net.to(device) # move model to GPU if available
|
|
69
69
|
criterion = torch.nn.CrossEntropyLoss().to(device)
|
|
70
|
-
optimizer = torch.optim.
|
|
70
|
+
optimizer = torch.optim.Adam(net.parameters(), lr=0.01)
|
|
71
71
|
net.train()
|
|
72
72
|
running_loss = 0.0
|
|
73
73
|
for _ in range(epochs):
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""$project_name: A Flower / $framework_str app."""
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
from flwr_datasets import FederatedDataset
|
|
5
|
+
from flwr_datasets.partitioner import IidPartitioner
|
|
6
|
+
from sklearn.linear_model import LogisticRegression
|
|
7
|
+
|
|
8
|
+
fds = None # Cache FederatedDataset
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def load_data(partition_id: int, num_partitions: int):
|
|
12
|
+
"""Load partition MNIST data."""
|
|
13
|
+
# Only initialize `FederatedDataset` once
|
|
14
|
+
global fds
|
|
15
|
+
if fds is None:
|
|
16
|
+
partitioner = IidPartitioner(num_partitions=num_partitions)
|
|
17
|
+
fds = FederatedDataset(
|
|
18
|
+
dataset="mnist",
|
|
19
|
+
partitioners={"train": partitioner},
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
dataset = fds.load_partition(partition_id, "train").with_format("numpy")
|
|
23
|
+
|
|
24
|
+
X, y = dataset["image"].reshape((len(dataset), -1)), dataset["label"]
|
|
25
|
+
|
|
26
|
+
# Split the on edge data: 80% train, 20% test
|
|
27
|
+
X_train, X_test = X[: int(0.8 * len(X))], X[int(0.8 * len(X)) :]
|
|
28
|
+
y_train, y_test = y[: int(0.8 * len(y))], y[int(0.8 * len(y)) :]
|
|
29
|
+
|
|
30
|
+
return X_train, X_test, y_train, y_test
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def get_model(penalty: str, local_epochs: int):
|
|
34
|
+
|
|
35
|
+
return LogisticRegression(
|
|
36
|
+
penalty=penalty,
|
|
37
|
+
max_iter=local_epochs,
|
|
38
|
+
warm_start=True,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def get_model_params(model):
|
|
43
|
+
if model.fit_intercept:
|
|
44
|
+
params = [
|
|
45
|
+
model.coef_,
|
|
46
|
+
model.intercept_,
|
|
47
|
+
]
|
|
48
|
+
else:
|
|
49
|
+
params = [model.coef_]
|
|
50
|
+
return params
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def set_model_params(model, params):
|
|
54
|
+
model.coef_ = params[0]
|
|
55
|
+
if model.fit_intercept:
|
|
56
|
+
model.intercept_ = params[1]
|
|
57
|
+
return model
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def set_initial_params(model):
|
|
61
|
+
n_classes = 10 # MNIST has 10 classes
|
|
62
|
+
n_features = 784 # Number of features in dataset
|
|
63
|
+
model.classes_ = np.array([i for i in range(10)])
|
|
64
|
+
|
|
65
|
+
model.coef_ = np.zeros((n_classes, n_features))
|
|
66
|
+
if model.fit_intercept:
|
|
67
|
+
model.intercept_ = np.zeros((n_classes,))
|
|
@@ -9,8 +9,8 @@ description = ""
|
|
|
9
9
|
license = "Apache-2.0"
|
|
10
10
|
dependencies = [
|
|
11
11
|
"flwr[simulation]>=1.10.0",
|
|
12
|
-
"jax==0.4.
|
|
13
|
-
"jaxlib==0.4.
|
|
12
|
+
"jax==0.4.30",
|
|
13
|
+
"jaxlib==0.4.30",
|
|
14
14
|
"scikit-learn==1.3.2",
|
|
15
15
|
]
|
|
16
16
|
|
|
@@ -26,6 +26,7 @@ clientapp = "$import_name.client_app:app"
|
|
|
26
26
|
|
|
27
27
|
[tool.flwr.app.config]
|
|
28
28
|
num-server-rounds = 3
|
|
29
|
+
input-dim = 3
|
|
29
30
|
|
|
30
31
|
[tool.flwr.federations]
|
|
31
32
|
default = "local-simulation"
|
flwr/common/constant.py
CHANGED
|
@@ -63,7 +63,10 @@ NODE_ID_NUM_BYTES = 8
|
|
|
63
63
|
|
|
64
64
|
# Constants for FAB
|
|
65
65
|
APP_DIR = "apps"
|
|
66
|
+
FAB_ALLOWED_EXTENSIONS = {".py", ".toml", ".md"}
|
|
66
67
|
FAB_CONFIG_FILE = "pyproject.toml"
|
|
68
|
+
FAB_DATE = (2024, 10, 1, 0, 0, 0)
|
|
69
|
+
FAB_HASH_TRUNCATION = 8
|
|
67
70
|
FLWR_HOME = "FLWR_HOME"
|
|
68
71
|
|
|
69
72
|
# Constants entries in Node config for Simulation
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
"""Flower ClientProxy implementation for Driver API."""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
import time
|
|
19
18
|
from typing import Optional
|
|
20
19
|
|
|
21
20
|
from flwr import common
|
|
@@ -25,8 +24,6 @@ from flwr.server.client_proxy import ClientProxy
|
|
|
25
24
|
|
|
26
25
|
from ..driver.driver import Driver
|
|
27
26
|
|
|
28
|
-
SLEEP_TIME = 1
|
|
29
|
-
|
|
30
27
|
|
|
31
28
|
class DriverClientProxy(ClientProxy):
|
|
32
29
|
"""Flower client proxy which delegates work using the Driver API."""
|
|
@@ -122,29 +119,18 @@ class DriverClientProxy(ClientProxy):
|
|
|
122
119
|
ttl=timeout,
|
|
123
120
|
)
|
|
124
121
|
|
|
125
|
-
#
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
if
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
msg: Message = messages[0]
|
|
141
|
-
if msg.has_error():
|
|
142
|
-
raise ValueError(
|
|
143
|
-
f"Message contains an Error (reason: {msg.error.reason}). "
|
|
144
|
-
"It originated during client-side execution of a message."
|
|
145
|
-
)
|
|
146
|
-
return msg.content
|
|
147
|
-
|
|
148
|
-
if timeout is not None and time.time() > start_time + timeout:
|
|
149
|
-
raise RuntimeError("Timeout reached")
|
|
150
|
-
time.sleep(SLEEP_TIME)
|
|
122
|
+
# Send message and wait for reply
|
|
123
|
+
messages = list(self.driver.send_and_receive(messages=[message]))
|
|
124
|
+
|
|
125
|
+
# A single reply is expected
|
|
126
|
+
if len(messages) != 1:
|
|
127
|
+
raise ValueError(f"Expected one Message but got: {len(messages)}")
|
|
128
|
+
|
|
129
|
+
# Only messages without errors can be handled beyond these point
|
|
130
|
+
msg: Message = messages[0]
|
|
131
|
+
if msg.has_error():
|
|
132
|
+
raise ValueError(
|
|
133
|
+
f"Message contains an Error (reason: {msg.error.reason}). "
|
|
134
|
+
"It originated during client-side execution of a message."
|
|
135
|
+
)
|
|
136
|
+
return msg.content
|
|
@@ -39,16 +39,20 @@ class InMemoryDriver(Driver):
|
|
|
39
39
|
The identifier of the run.
|
|
40
40
|
state_factory : StateFactory
|
|
41
41
|
A StateFactory embedding a state that this driver can interface with.
|
|
42
|
+
pull_interval : float (default=0.1)
|
|
43
|
+
Sleep duration between calls to `pull_messages`.
|
|
42
44
|
"""
|
|
43
45
|
|
|
44
46
|
def __init__(
|
|
45
47
|
self,
|
|
46
48
|
run_id: int,
|
|
47
49
|
state_factory: StateFactory,
|
|
50
|
+
pull_interval: float = 0.1,
|
|
48
51
|
) -> None:
|
|
49
52
|
self._run_id = run_id
|
|
50
53
|
self._run: Optional[Run] = None
|
|
51
54
|
self.state = state_factory.state()
|
|
55
|
+
self.pull_interval = pull_interval
|
|
52
56
|
self.node = Node(node_id=0, anonymous=True)
|
|
53
57
|
|
|
54
58
|
def _check_message(self, message: Message) -> None:
|
|
@@ -180,5 +184,5 @@ class InMemoryDriver(Driver):
|
|
|
180
184
|
if len(msg_ids) == 0:
|
|
181
185
|
break
|
|
182
186
|
# Sleep
|
|
183
|
-
time.sleep(
|
|
187
|
+
time.sleep(self.pull_interval)
|
|
184
188
|
return ret
|
|
@@ -116,6 +116,7 @@ class InMemoryState(State): # pylint: disable=R0902,R0904
|
|
|
116
116
|
# Return TaskIns
|
|
117
117
|
return task_ins_list
|
|
118
118
|
|
|
119
|
+
# pylint: disable=R0911
|
|
119
120
|
def store_task_res(self, task_res: TaskRes) -> Optional[UUID]:
|
|
120
121
|
"""Store one TaskRes."""
|
|
121
122
|
# Validate task
|
|
@@ -129,6 +130,17 @@ class InMemoryState(State): # pylint: disable=R0902,R0904
|
|
|
129
130
|
task_ins_id = task_res.task.ancestry[0]
|
|
130
131
|
task_ins = self.task_ins_store.get(UUID(task_ins_id))
|
|
131
132
|
|
|
133
|
+
# Ensure that the consumer_id of taskIns matches the producer_id of taskRes.
|
|
134
|
+
if (
|
|
135
|
+
task_ins
|
|
136
|
+
and task_res
|
|
137
|
+
and not (
|
|
138
|
+
task_ins.task.consumer.anonymous or task_res.task.producer.anonymous
|
|
139
|
+
)
|
|
140
|
+
and task_ins.task.consumer.node_id != task_res.task.producer.node_id
|
|
141
|
+
):
|
|
142
|
+
return None
|
|
143
|
+
|
|
132
144
|
if task_ins is None:
|
|
133
145
|
log(ERROR, "TaskIns with task_id %s does not exist.", task_ins_id)
|
|
134
146
|
return None
|
|
@@ -189,6 +201,19 @@ class InMemoryState(State): # pylint: disable=R0902,R0904
|
|
|
189
201
|
replied_task_ids: set[UUID] = set()
|
|
190
202
|
for _, task_res in self.task_res_store.items():
|
|
191
203
|
reply_to = UUID(task_res.task.ancestry[0])
|
|
204
|
+
|
|
205
|
+
# Check if corresponding TaskIns exists and is not expired
|
|
206
|
+
task_ins = self.task_ins_store.get(reply_to)
|
|
207
|
+
if task_ins is None:
|
|
208
|
+
log(WARNING, "TaskIns with task_id %s does not exist.", reply_to)
|
|
209
|
+
task_ids.remove(reply_to)
|
|
210
|
+
continue
|
|
211
|
+
|
|
212
|
+
if task_ins.task.created_at + task_ins.task.ttl <= time.time():
|
|
213
|
+
log(WARNING, "TaskIns with task_id %s is expired.", reply_to)
|
|
214
|
+
task_ids.remove(reply_to)
|
|
215
|
+
continue
|
|
216
|
+
|
|
192
217
|
if reply_to in task_ids and task_res.task.delivered_at == "":
|
|
193
218
|
task_res_list.append(task_res)
|
|
194
219
|
replied_task_ids.add(reply_to)
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
# ==============================================================================
|
|
15
15
|
"""SQLite based implemenation of server state."""
|
|
16
16
|
|
|
17
|
+
# pylint: disable=too-many-lines
|
|
17
18
|
|
|
18
19
|
import json
|
|
19
20
|
import re
|
|
@@ -389,6 +390,16 @@ class SqliteState(State): # pylint: disable=R0904
|
|
|
389
390
|
)
|
|
390
391
|
return None
|
|
391
392
|
|
|
393
|
+
# Ensure that the consumer_id of taskIns matches the producer_id of taskRes.
|
|
394
|
+
if (
|
|
395
|
+
task_ins
|
|
396
|
+
and task_res
|
|
397
|
+
and not (task_ins["consumer_anonymous"] or task_res.task.producer.anonymous)
|
|
398
|
+
and convert_sint64_to_uint64(task_ins["consumer_node_id"])
|
|
399
|
+
!= task_res.task.producer.node_id
|
|
400
|
+
):
|
|
401
|
+
return None
|
|
402
|
+
|
|
392
403
|
# Fail if the TaskRes TTL exceeds the
|
|
393
404
|
# expiration time of the TaskIns it replies to.
|
|
394
405
|
# Condition: TaskIns.created_at + TaskIns.ttl ≥
|
|
@@ -432,7 +443,7 @@ class SqliteState(State): # pylint: disable=R0904
|
|
|
432
443
|
|
|
433
444
|
return task_id
|
|
434
445
|
|
|
435
|
-
# pylint: disable-next=R0914
|
|
446
|
+
# pylint: disable-next=R0912,R0915,R0914
|
|
436
447
|
def get_task_res(self, task_ids: set[UUID], limit: Optional[int]) -> list[TaskRes]:
|
|
437
448
|
"""Get TaskRes for task_ids.
|
|
438
449
|
|
|
@@ -451,6 +462,35 @@ class SqliteState(State): # pylint: disable=R0904
|
|
|
451
462
|
if limit is not None and limit < 1:
|
|
452
463
|
raise AssertionError("`limit` must be >= 1")
|
|
453
464
|
|
|
465
|
+
# Check if corresponding TaskIns exists and is not expired
|
|
466
|
+
task_ids_placeholders = ",".join([f":id_{i}" for i in range(len(task_ids))])
|
|
467
|
+
query = f"""
|
|
468
|
+
SELECT *
|
|
469
|
+
FROM task_ins
|
|
470
|
+
WHERE task_id IN ({task_ids_placeholders})
|
|
471
|
+
AND (created_at + ttl) > CAST(strftime('%s', 'now') AS REAL)
|
|
472
|
+
"""
|
|
473
|
+
query += ";"
|
|
474
|
+
|
|
475
|
+
task_ins_data = {}
|
|
476
|
+
for index, task_id in enumerate(task_ids):
|
|
477
|
+
task_ins_data[f"id_{index}"] = str(task_id)
|
|
478
|
+
|
|
479
|
+
task_ins_rows = self.query(query, task_ins_data)
|
|
480
|
+
|
|
481
|
+
if not task_ins_rows:
|
|
482
|
+
return []
|
|
483
|
+
|
|
484
|
+
for row in task_ins_rows:
|
|
485
|
+
# Convert values from sint64 to uint64
|
|
486
|
+
convert_sint64_values_in_dict_to_uint64(
|
|
487
|
+
row, ["run_id", "producer_node_id", "consumer_node_id"]
|
|
488
|
+
)
|
|
489
|
+
task_ins = dict_to_task_ins(row)
|
|
490
|
+
if task_ins.task.created_at + task_ins.task.ttl <= time.time():
|
|
491
|
+
log(WARNING, "TaskIns with task_id %s is expired.", task_ins.task_id)
|
|
492
|
+
task_ids.remove(UUID(task_ins.task_id))
|
|
493
|
+
|
|
454
494
|
# Retrieve all anonymous Tasks
|
|
455
495
|
if len(task_ids) == 0:
|
|
456
496
|
return []
|
{flwr_nightly-1.12.0.dev20241007.dist-info → flwr_nightly-1.12.0.dev20241009.dist-info}/RECORD
RENAMED
|
@@ -7,7 +7,7 @@ flwr/cli/example.py,sha256=1bGDYll3BXQY2kRqSN-oICqS5n1b9m0g0RvXTopXHl4,2215
|
|
|
7
7
|
flwr/cli/install.py,sha256=t5tdeKOsTmG3nuInUoSKBVzUU1RnzA096yzYs013VhE,7065
|
|
8
8
|
flwr/cli/log.py,sha256=uhtcLcFGkazirWnEmet3Wt3rt_q-a13kauQqPLaMaRY,8097
|
|
9
9
|
flwr/cli/new/__init__.py,sha256=cQzK1WH4JP2awef1t2UQ2xjl1agVEz9rwutV18SWV1k,789
|
|
10
|
-
flwr/cli/new/new.py,sha256=
|
|
10
|
+
flwr/cli/new/new.py,sha256=uSiG7aXQzPDnikv2YcjQ86OOLqint0hNWCI0fSQD0jI,9634
|
|
11
11
|
flwr/cli/new/templates/__init__.py,sha256=4luU8RL-CK8JJCstQ_ON809W9bNTkY1l9zSaPKBkgwY,725
|
|
12
12
|
flwr/cli/new/templates/app/.gitignore.tpl,sha256=XixnHdyeMB2vwkGtGnwHqoWpH-9WChdyG0GXe57duhc,3078
|
|
13
13
|
flwr/cli/new/templates/app/LICENSE.tpl,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
|
|
@@ -20,11 +20,11 @@ flwr/cli/new/templates/app/code/__init__.py,sha256=EM6vfvgAILKPaPn7H1wMV1Wi01WyZ
|
|
|
20
20
|
flwr/cli/new/templates/app/code/__init__.py.tpl,sha256=J0Gn74E7khpLyKJVNqOPu7ev93vkcu1PZugsbxtABMw,52
|
|
21
21
|
flwr/cli/new/templates/app/code/client.baseline.py.tpl,sha256=1htktXX3jXX05r0vuG_afjS1sXGtuONW9EpiQ7vSBes,1901
|
|
22
22
|
flwr/cli/new/templates/app/code/client.huggingface.py.tpl,sha256=ifD08KwjdoGieV26hFCgf3PQB6rMhj_NZLo5iUUndm8,1846
|
|
23
|
-
flwr/cli/new/templates/app/code/client.jax.py.tpl,sha256=
|
|
24
|
-
flwr/cli/new/templates/app/code/client.mlx.py.tpl,sha256=
|
|
25
|
-
flwr/cli/new/templates/app/code/client.numpy.py.tpl,sha256=
|
|
26
|
-
flwr/cli/new/templates/app/code/client.pytorch.py.tpl,sha256=
|
|
27
|
-
flwr/cli/new/templates/app/code/client.sklearn.py.tpl,sha256=
|
|
23
|
+
flwr/cli/new/templates/app/code/client.jax.py.tpl,sha256=4EkcGGmbPAa6dgw8GYII-GfrGsu8VU6amRHpJvF0WuA,1319
|
|
24
|
+
flwr/cli/new/templates/app/code/client.mlx.py.tpl,sha256=gOxt_QUTfGFpofdNaxdwTSLZlkTWHPYGix2OGHC1hYE,2376
|
|
25
|
+
flwr/cli/new/templates/app/code/client.numpy.py.tpl,sha256=DKcnz5-KUf693Va056QTKVofFV3ozJZutK4rQyfvRXc,548
|
|
26
|
+
flwr/cli/new/templates/app/code/client.pytorch.py.tpl,sha256=fuxVmZpjHIueNy_aHWF81531vmi8DGu4CYjYDqmUwWo,1705
|
|
27
|
+
flwr/cli/new/templates/app/code/client.sklearn.py.tpl,sha256=MfhMN-hayGCc3cZ1XpN0A6f67GRveI_tGbq5kjOeP0Q,1871
|
|
28
28
|
flwr/cli/new/templates/app/code/client.tensorflow.py.tpl,sha256=yBiiU7B9Kf70U52cPkNs_dUpYrrTwbUi2os-PAyheaM,1680
|
|
29
29
|
flwr/cli/new/templates/app/code/dataset.baseline.py.tpl,sha256=jbd_exHAk2-Blu_kVutjPO6a_dkJQWb232zxSeXIZ1k,1453
|
|
30
30
|
flwr/cli/new/templates/app/code/flwr_tune/__init__.py,sha256=JgNgBtKdm1jKM9625WxappCAVUGtYAmcjKSsXJ1u3ZQ,748
|
|
@@ -36,27 +36,29 @@ flwr/cli/new/templates/app/code/flwr_tune/strategy.py.tpl,sha256=BhiqRg9w1MGuU5h
|
|
|
36
36
|
flwr/cli/new/templates/app/code/model.baseline.py.tpl,sha256=cSz6-IWsnMl7s04DW4URINiIppCIberrtE8NqK6Qz48,2571
|
|
37
37
|
flwr/cli/new/templates/app/code/server.baseline.py.tpl,sha256=outx7lDXsWS8QXKWOGOiDno6eE8WL7LBD51ZkAuC3WU,1570
|
|
38
38
|
flwr/cli/new/templates/app/code/server.huggingface.py.tpl,sha256=0PJmnZvR9_VPLSak1yVfkOx3dmqo6cynhY1l2s4AZrE,1158
|
|
39
|
-
flwr/cli/new/templates/app/code/server.jax.py.tpl,sha256=
|
|
40
|
-
flwr/cli/new/templates/app/code/server.mlx.py.tpl,sha256=
|
|
41
|
-
flwr/cli/new/templates/app/code/server.numpy.py.tpl,sha256=
|
|
42
|
-
flwr/cli/new/templates/app/code/server.pytorch.py.tpl,sha256=
|
|
43
|
-
flwr/cli/new/templates/app/code/server.sklearn.py.tpl,sha256=
|
|
39
|
+
flwr/cli/new/templates/app/code/server.jax.py.tpl,sha256=IHk57syZhvO4nWVHGxE9S8f5DTxRKIrTitDufF4RhMY,828
|
|
40
|
+
flwr/cli/new/templates/app/code/server.mlx.py.tpl,sha256=GAqalaI-U2uRdttNeRn75k1FzdEW3rmgT-ywuKkFdK4,988
|
|
41
|
+
flwr/cli/new/templates/app/code/server.numpy.py.tpl,sha256=xbQlLCKutnOqlbLQPZsaL9WM7vnebTceiU8a0HaUcZk,740
|
|
42
|
+
flwr/cli/new/templates/app/code/server.pytorch.py.tpl,sha256=gvBsGA_Jg9kAH8xTxjzTjMcvBtciuccOwQFbO7ey8tU,916
|
|
43
|
+
flwr/cli/new/templates/app/code/server.sklearn.py.tpl,sha256=JoDYjPU99aKTTfjKsCtKHzMICiOR9pi8JGVBsxFpWO4,1133
|
|
44
44
|
flwr/cli/new/templates/app/code/server.tensorflow.py.tpl,sha256=xMhQ7AumowgLkgUilgjVK7IbpRhPjslhVJU-vID6NY8,856
|
|
45
45
|
flwr/cli/new/templates/app/code/strategy.baseline.py.tpl,sha256=YkHAgppUeD2BnBoGfVB6dEvBfjuIPGsU1gw4CiUi3qA,40
|
|
46
46
|
flwr/cli/new/templates/app/code/task.huggingface.py.tpl,sha256=ua6cAhJYPUCwML20DEucM0F4ZzzsEVQLYrRvhQ7CGRE,3347
|
|
47
|
-
flwr/cli/new/templates/app/code/task.jax.py.tpl,sha256=
|
|
48
|
-
flwr/cli/new/templates/app/code/task.mlx.py.tpl,sha256=
|
|
49
|
-
flwr/cli/new/templates/app/code/task.
|
|
47
|
+
flwr/cli/new/templates/app/code/task.jax.py.tpl,sha256=jK03Y0HUvVFjUB-cYnvYB-WCRdr451aYklP1o6G5rx8,1530
|
|
48
|
+
flwr/cli/new/templates/app/code/task.mlx.py.tpl,sha256=YxH5z4s5kOh5_9DIY9pvzqURckLDfgdanTA68_iM_Wo,2946
|
|
49
|
+
flwr/cli/new/templates/app/code/task.numpy.py.tpl,sha256=MsjJK8DAvM3ex6JTfZuBVqoBKJfCCjIHMUOPkspiSQ0,124
|
|
50
|
+
flwr/cli/new/templates/app/code/task.pytorch.py.tpl,sha256=XlJqA4Ix_PloO_zJLhjiN5vDj16w3I4CPVGdmbe8asE,3800
|
|
51
|
+
flwr/cli/new/templates/app/code/task.sklearn.py.tpl,sha256=SeIIo0rr_6ffn4Qx2xELD18jYXCkcW__NWtYEDXCICM,1843
|
|
50
52
|
flwr/cli/new/templates/app/code/task.tensorflow.py.tpl,sha256=SKXAZdgBnPpbAbJ90Rb7oQ5ilnopBx_j_JNFoUDeEAI,1732
|
|
51
53
|
flwr/cli/new/templates/app/code/utils.baseline.py.tpl,sha256=YkHAgppUeD2BnBoGfVB6dEvBfjuIPGsU1gw4CiUi3qA,40
|
|
52
54
|
flwr/cli/new/templates/app/pyproject.baseline.toml.tpl,sha256=4gi90W9_B1kj6rYkpvVJxhNX9Yctsv9OH6CzXP-dcE4,2666
|
|
53
55
|
flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl,sha256=bYdDP0O8z741pvy1INnH4UBuP-KFvcyQt6Yo81n4frQ,1853
|
|
54
56
|
flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl,sha256=CHJgkPNkJfzJhEbTe15uiV3AhOtIddQi-yofPZsCk3E,1143
|
|
55
|
-
flwr/cli/new/templates/app/pyproject.jax.toml.tpl,sha256=
|
|
56
|
-
flwr/cli/new/templates/app/pyproject.mlx.toml.tpl,sha256=
|
|
57
|
+
flwr/cli/new/templates/app/pyproject.jax.toml.tpl,sha256=v1DVriLky0ow9yc0NK91_6VkxkzpPsheIxbb2c0LcYQ,673
|
|
58
|
+
flwr/cli/new/templates/app/pyproject.mlx.toml.tpl,sha256=S4QDy7UXboJt60R3LE7z97_QU1idb0ob8A_N7O3cifo,765
|
|
57
59
|
flwr/cli/new/templates/app/pyproject.numpy.toml.tpl,sha256=-FCi64ygMgQke3zApUt0XtkIBo3WtQoPAPhtp_FqkPE,612
|
|
58
60
|
flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl,sha256=vIO1ArukTC76ogYLNmJIl25MOE_nEELj3IcTZZJjohU,710
|
|
59
|
-
flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl,sha256=
|
|
61
|
+
flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl,sha256=fdlIN_sip1mrbOtqpeag60Kj56aYrA-0HEq9lYZLNnM,686
|
|
60
62
|
flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl,sha256=bRIvPCPvTTI4Eo5b61Rmw8WdDw3sjcohciTXgULN5l8,702
|
|
61
63
|
flwr/cli/run/__init__.py,sha256=oCd6HmQDx-sqver1gecgx-uMA38BLTSiiKpl7RGNceg,789
|
|
62
64
|
flwr/cli/run/run.py,sha256=tLKeWpWJqEBxkOtDKEprL4SBKxH1vHGybQxlCLnXiSQ,8386
|
|
@@ -101,7 +103,7 @@ flwr/client/typing.py,sha256=dxoTBnTMfqXr5J7G3y-uNjqxYCddvxhu89spfj4Lm2U,1048
|
|
|
101
103
|
flwr/common/__init__.py,sha256=TVaoFEJE158aui1TPZQiJCDZX4RNHRyI8I55VC80HhI,3901
|
|
102
104
|
flwr/common/address.py,sha256=7kM2Rqjw86-c8aKwAvrXerWqznnVv4TFJ62aSAeTn10,3017
|
|
103
105
|
flwr/common/config.py,sha256=QjsDEDf4xsx8StJV9I80dYWbBp7aBNrJmTlAeLpQpyw,7567
|
|
104
|
-
flwr/common/constant.py,sha256=
|
|
106
|
+
flwr/common/constant.py,sha256=cUP0lErfb0s1ACnErm_T5kIks0xnEi2X5UNnzmXRSW4,3757
|
|
105
107
|
flwr/common/context.py,sha256=5Bd9RCrhLkYZOVR7vr97OVhzVBHQkS1fUsYiIKTwpxU,2239
|
|
106
108
|
flwr/common/date.py,sha256=OcQuwpb2HxcblTqYm6H223ufop5UZw5N_fzalbpOVzY,891
|
|
107
109
|
flwr/common/differential_privacy.py,sha256=XwcJ3rWr8S8BZUocc76vLSJAXIf6OHnWkBV6-xlIRuw,6106
|
|
@@ -204,13 +206,13 @@ flwr/server/client_proxy.py,sha256=4G-oTwhb45sfWLx2uZdcXD98IZwdTS6F88xe3akCdUg,2
|
|
|
204
206
|
flwr/server/compat/__init__.py,sha256=VxnJtJyOjNFQXMNi9hIuzNlZM5n0Hj1p3aq_Pm2udw4,892
|
|
205
207
|
flwr/server/compat/app.py,sha256=5vkHHm_h-4cMthvWD1GJo1ZW3eihytjGgvsgfXUK9gA,3298
|
|
206
208
|
flwr/server/compat/app_utils.py,sha256=i8MseZQculltLTsRIEe4XUnmAuu3LF3WzGjYi0c-cps,3425
|
|
207
|
-
flwr/server/compat/driver_client_proxy.py,sha256=
|
|
209
|
+
flwr/server/compat/driver_client_proxy.py,sha256=Af0bRUEVZNcCYRxt3DjpLPdvVYpTgz6LSlILtI_8DQY,5010
|
|
208
210
|
flwr/server/compat/legacy_context.py,sha256=wBzBcfV6YO6IQGriM_FdJ5XZfiBBEEJdS_OdAiF47dY,1804
|
|
209
211
|
flwr/server/criterion.py,sha256=ypbAexbztzGUxNen9RCHF91QeqiEQix4t4Ih3E-42MM,1061
|
|
210
212
|
flwr/server/driver/__init__.py,sha256=bikRv6CjTwSvYh7tf10gziU5o2YotOWhhftz2tr3KDc,886
|
|
211
213
|
flwr/server/driver/driver.py,sha256=rGLbOfLhBOn74mUHi_0CMbXqZLX8q_lXqEkcUXoL_wI,5238
|
|
212
214
|
flwr/server/driver/grpc_driver.py,sha256=xd1mxRexeiIJrZw9l-urj2zEIncLT8KtNn0l8hIDYZs,9681
|
|
213
|
-
flwr/server/driver/inmemory_driver.py,sha256=
|
|
215
|
+
flwr/server/driver/inmemory_driver.py,sha256=J1pzjzNF18z_sQnez9JmrHqSIDfgn9NX6NfLj1BKrH4,6658
|
|
214
216
|
flwr/server/history.py,sha256=qSb5_pPTrwofpSYGsZWzMPkl_4uJ4mJFWesxXDrEvDU,5026
|
|
215
217
|
flwr/server/run_serverapp.py,sha256=SaE9hoWLCAPnRXvdAzE4Oi3QaiC8NOTrHxrIGXjgYxU,10531
|
|
216
218
|
flwr/server/server.py,sha256=1ZsFEptmAV-L2vP2etNC9Ed5CLSxpuKzUFkAPQ4l5Xc,17893
|
|
@@ -270,8 +272,8 @@ flwr/server/superlink/fleet/vce/backend/backend.py,sha256=LBAQxnbfPAphVOVIvYMj0Q
|
|
|
270
272
|
flwr/server/superlink/fleet/vce/backend/raybackend.py,sha256=7kB3re3mR53b7E6L6DPSioTSKD3YGtS3uJsPD7Hn2Fw,7155
|
|
271
273
|
flwr/server/superlink/fleet/vce/vce_api.py,sha256=cGPsjS_4SJHm8jszGjsHh8ZNk9nqWoIQwW_62yKKR1Y,12647
|
|
272
274
|
flwr/server/superlink/state/__init__.py,sha256=Gj2OTFLXvA-mAjBvwuKDM3rDrVaQPcIoybSa2uskMTE,1003
|
|
273
|
-
flwr/server/superlink/state/in_memory_state.py,sha256=
|
|
274
|
-
flwr/server/superlink/state/sqlite_state.py,sha256=
|
|
275
|
+
flwr/server/superlink/state/in_memory_state.py,sha256=P00PeiBjNqxrWVUpMfoNFEbK9XwTULlaOzSgpaMBzkA,15960
|
|
276
|
+
flwr/server/superlink/state/sqlite_state.py,sha256=WlPVEfiPHcumnTXrnYhxxrxiAfC5xEKACV99w_9Q-js,35806
|
|
275
277
|
flwr/server/superlink/state/state.py,sha256=KpM894R8RE1N0b-s_Nlii6i0TDxj0DRkKa3Vf24Gt70,8127
|
|
276
278
|
flwr/server/superlink/state/state_factory.py,sha256=Fo8pBQ1WWrVJK5TOEPZ_zgJE69_mfTGjTO6czh6571o,2021
|
|
277
279
|
flwr/server/superlink/state/utils.py,sha256=OsF3OOoU4bU4PgLWkypX6EDoFs0L8RP_mHEBG-tVqGA,5227
|
|
@@ -299,8 +301,8 @@ flwr/superexec/exec_grpc.py,sha256=ZPq7EP55Vwj0kRcLVuTCokFqfIgBk-7YmDykZoMKi-c,1
|
|
|
299
301
|
flwr/superexec/exec_servicer.py,sha256=TRpwPVl7eI0Y_xlCY6DmVpAo0yFU1gLwzyIeqFw9pyk,4746
|
|
300
302
|
flwr/superexec/executor.py,sha256=-5J-ZLs-uArro3T2pCq0YQRC65cs18M888nufzdYE4E,2375
|
|
301
303
|
flwr/superexec/simulation.py,sha256=J6pw-RqCSiUed8I_3MasZH4tl57ZmDebPAHNnbb0-vE,7420
|
|
302
|
-
flwr_nightly-1.12.0.
|
|
303
|
-
flwr_nightly-1.12.0.
|
|
304
|
-
flwr_nightly-1.12.0.
|
|
305
|
-
flwr_nightly-1.12.0.
|
|
306
|
-
flwr_nightly-1.12.0.
|
|
304
|
+
flwr_nightly-1.12.0.dev20241009.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
|
305
|
+
flwr_nightly-1.12.0.dev20241009.dist-info/METADATA,sha256=coU4H2vio6xXLZKrcCpJMOecM6p-az9LZ8WFBggz0bE,15618
|
|
306
|
+
flwr_nightly-1.12.0.dev20241009.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
|
307
|
+
flwr_nightly-1.12.0.dev20241009.dist-info/entry_points.txt,sha256=WUCbqhLEOzjx_lyATIM0-f0e8kOVaQjzwOvyOxHrMhs,434
|
|
308
|
+
flwr_nightly-1.12.0.dev20241009.dist-info/RECORD,,
|
{flwr_nightly-1.12.0.dev20241007.dist-info → flwr_nightly-1.12.0.dev20241009.dist-info}/LICENSE
RENAMED
|
File without changes
|
{flwr_nightly-1.12.0.dev20241007.dist-info → flwr_nightly-1.12.0.dev20241009.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|