flwr-nightly 1.6.0.dev20231026__py3-none-any.whl → 1.6.0.dev20231101__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.
- flwr/client/app.py +57 -34
- flwr/common/retry_invoker.py +288 -0
- {flwr_nightly-1.6.0.dev20231026.dist-info → flwr_nightly-1.6.0.dev20231101.dist-info}/METADATA +50 -51
- {flwr_nightly-1.6.0.dev20231026.dist-info → flwr_nightly-1.6.0.dev20231101.dist-info}/RECORD +7 -6
- {flwr_nightly-1.6.0.dev20231026.dist-info → flwr_nightly-1.6.0.dev20231101.dist-info}/LICENSE +0 -0
- {flwr_nightly-1.6.0.dev20231026.dist-info → flwr_nightly-1.6.0.dev20231101.dist-info}/WHEEL +0 -0
- {flwr_nightly-1.6.0.dev20231026.dist-info → flwr_nightly-1.6.0.dev20231101.dist-info}/entry_points.txt +0 -0
flwr/client/app.py
CHANGED
@@ -19,7 +19,7 @@ import sys
|
|
19
19
|
import time
|
20
20
|
import warnings
|
21
21
|
from logging import INFO
|
22
|
-
from typing import Optional, Union
|
22
|
+
from typing import Callable, ContextManager, Optional, Tuple, Union
|
23
23
|
|
24
24
|
from flwr.client.client import Client
|
25
25
|
from flwr.client.typing import ClientFn
|
@@ -33,6 +33,7 @@ from flwr.common.constant import (
|
|
33
33
|
TRANSPORT_TYPES,
|
34
34
|
)
|
35
35
|
from flwr.common.logger import log
|
36
|
+
from flwr.proto.task_pb2 import TaskIns, TaskRes
|
36
37
|
|
37
38
|
from .grpc_client.connection import grpc_connection
|
38
39
|
from .grpc_rere_client.connection import grpc_request_response
|
@@ -134,44 +135,15 @@ def start_client(
|
|
134
135
|
|
135
136
|
client_fn = single_client_factory
|
136
137
|
|
137
|
-
#
|
138
|
-
|
139
|
-
if not parsed_address:
|
140
|
-
sys.exit(f"Server address ({server_address}) cannot be parsed.")
|
141
|
-
host, port, is_v6 = parsed_address
|
142
|
-
address = f"[{host}]:{port}" if is_v6 else f"{host}:{port}"
|
143
|
-
|
144
|
-
# Set the default transport layer
|
145
|
-
if transport is None:
|
146
|
-
transport = TRANSPORT_TYPE_GRPC_BIDI
|
147
|
-
|
148
|
-
# Use either gRPC bidirectional streaming or REST request/response
|
149
|
-
if transport == TRANSPORT_TYPE_REST:
|
150
|
-
try:
|
151
|
-
from .rest_client.connection import http_request_response
|
152
|
-
except ModuleNotFoundError:
|
153
|
-
sys.exit(MISSING_EXTRA_REST)
|
154
|
-
if server_address[:4] != "http":
|
155
|
-
sys.exit(
|
156
|
-
"When using the REST API, please provide `https://` or "
|
157
|
-
"`http://` before the server address (e.g. `http://127.0.0.1:8080`)"
|
158
|
-
)
|
159
|
-
connection = http_request_response
|
160
|
-
elif transport == TRANSPORT_TYPE_GRPC_RERE:
|
161
|
-
connection = grpc_request_response
|
162
|
-
elif transport == TRANSPORT_TYPE_GRPC_BIDI:
|
163
|
-
connection = grpc_connection
|
164
|
-
else:
|
165
|
-
raise ValueError(
|
166
|
-
f"Unknown transport type: {transport} (possible: {TRANSPORT_TYPES})"
|
167
|
-
)
|
138
|
+
# Initialize connection context manager
|
139
|
+
connection, address = _init_connection(transport, server_address)
|
168
140
|
|
169
141
|
while True:
|
170
142
|
sleep_duration: int = 0
|
171
143
|
with connection(
|
172
144
|
address,
|
173
|
-
|
174
|
-
root_certificates
|
145
|
+
grpc_max_message_length,
|
146
|
+
root_certificates,
|
175
147
|
) as conn:
|
176
148
|
receive, send, create_node, delete_node = conn
|
177
149
|
|
@@ -285,3 +257,54 @@ def start_numpy_client(
|
|
285
257
|
root_certificates=root_certificates,
|
286
258
|
transport=transport,
|
287
259
|
)
|
260
|
+
|
261
|
+
|
262
|
+
def _init_connection(
|
263
|
+
transport: Optional[str], server_address: str
|
264
|
+
) -> Tuple[
|
265
|
+
Callable[
|
266
|
+
[str, int, Union[bytes, str, None]],
|
267
|
+
ContextManager[
|
268
|
+
Tuple[
|
269
|
+
Callable[[], Optional[TaskIns]],
|
270
|
+
Callable[[TaskRes], None],
|
271
|
+
Optional[Callable[[], None]],
|
272
|
+
Optional[Callable[[], None]],
|
273
|
+
]
|
274
|
+
],
|
275
|
+
],
|
276
|
+
str,
|
277
|
+
]:
|
278
|
+
# Parse IP address
|
279
|
+
parsed_address = parse_address(server_address)
|
280
|
+
if not parsed_address:
|
281
|
+
sys.exit(f"Server address ({server_address}) cannot be parsed.")
|
282
|
+
host, port, is_v6 = parsed_address
|
283
|
+
address = f"[{host}]:{port}" if is_v6 else f"{host}:{port}"
|
284
|
+
|
285
|
+
# Set the default transport layer
|
286
|
+
if transport is None:
|
287
|
+
transport = TRANSPORT_TYPE_GRPC_BIDI
|
288
|
+
|
289
|
+
# Use either gRPC bidirectional streaming or REST request/response
|
290
|
+
if transport == TRANSPORT_TYPE_REST:
|
291
|
+
try:
|
292
|
+
from .rest_client.connection import http_request_response
|
293
|
+
except ModuleNotFoundError:
|
294
|
+
sys.exit(MISSING_EXTRA_REST)
|
295
|
+
if server_address[:4] != "http":
|
296
|
+
sys.exit(
|
297
|
+
"When using the REST API, please provide `https://` or "
|
298
|
+
"`http://` before the server address (e.g. `http://127.0.0.1:8080`)"
|
299
|
+
)
|
300
|
+
connection = http_request_response
|
301
|
+
elif transport == TRANSPORT_TYPE_GRPC_RERE:
|
302
|
+
connection = grpc_request_response
|
303
|
+
elif transport == TRANSPORT_TYPE_GRPC_BIDI:
|
304
|
+
connection = grpc_connection
|
305
|
+
else:
|
306
|
+
raise ValueError(
|
307
|
+
f"Unknown transport type: {transport} (possible: {TRANSPORT_TYPES})"
|
308
|
+
)
|
309
|
+
|
310
|
+
return connection, address
|
@@ -0,0 +1,288 @@
|
|
1
|
+
# Copyright 2023 Flower Labs GmbH. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
# ==============================================================================
|
15
|
+
"""`RetryInvoker` to augment other callables with error handling and retries."""
|
16
|
+
|
17
|
+
|
18
|
+
import itertools
|
19
|
+
import random
|
20
|
+
import time
|
21
|
+
from dataclasses import dataclass
|
22
|
+
from typing import (
|
23
|
+
Any,
|
24
|
+
Callable,
|
25
|
+
Dict,
|
26
|
+
Generator,
|
27
|
+
Iterable,
|
28
|
+
List,
|
29
|
+
Optional,
|
30
|
+
Tuple,
|
31
|
+
Type,
|
32
|
+
Union,
|
33
|
+
cast,
|
34
|
+
)
|
35
|
+
|
36
|
+
|
37
|
+
def exponential(
|
38
|
+
base_delay: float = 1,
|
39
|
+
multiplier: float = 2,
|
40
|
+
max_delay: Optional[int] = None,
|
41
|
+
) -> Generator[float, None, None]:
|
42
|
+
"""Wait time generator for exponential backoff strategy.
|
43
|
+
|
44
|
+
Parameters
|
45
|
+
----------
|
46
|
+
base_delay: float (default: 1)
|
47
|
+
Initial delay duration before the first retry.
|
48
|
+
multiplier: float (default: 2)
|
49
|
+
Factor by which the delay is multiplied after each retry.
|
50
|
+
max_delay: Optional[float] (default: None)
|
51
|
+
The maximum delay duration between two consecutive retries.
|
52
|
+
"""
|
53
|
+
delay = base_delay if max_delay is None else min(base_delay, max_delay)
|
54
|
+
while True:
|
55
|
+
yield delay
|
56
|
+
delay *= multiplier
|
57
|
+
if max_delay is not None:
|
58
|
+
delay = min(delay, max_delay)
|
59
|
+
|
60
|
+
|
61
|
+
def constant(
|
62
|
+
interval: Union[float, Iterable[float]] = 1,
|
63
|
+
) -> Generator[float, None, None]:
|
64
|
+
"""Wait time generator for specified intervals.
|
65
|
+
|
66
|
+
Parameters
|
67
|
+
----------
|
68
|
+
interval: Union[float, Iterable[float]] (default: 1)
|
69
|
+
A constant value to yield or an iterable of such values.
|
70
|
+
"""
|
71
|
+
if not isinstance(interval, Iterable):
|
72
|
+
interval = itertools.repeat(interval)
|
73
|
+
yield from interval
|
74
|
+
|
75
|
+
|
76
|
+
def full_jitter(max_value: float) -> float:
|
77
|
+
"""Randomize a float between 0 and the given maximum value.
|
78
|
+
|
79
|
+
This function implements the "Full Jitter" algorithm as described in the
|
80
|
+
AWS article discussing the efficacy of different jitter algorithms.
|
81
|
+
Reference: https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
|
82
|
+
|
83
|
+
Parameters
|
84
|
+
----------
|
85
|
+
max_value : float
|
86
|
+
The upper limit for the randomized value.
|
87
|
+
"""
|
88
|
+
return random.uniform(0, max_value)
|
89
|
+
|
90
|
+
|
91
|
+
@dataclass
|
92
|
+
class RetryState:
|
93
|
+
"""State for callbacks in RetryInvoker."""
|
94
|
+
|
95
|
+
target: Callable[..., Any]
|
96
|
+
args: Tuple[Any, ...]
|
97
|
+
kwargs: Dict[str, Any]
|
98
|
+
tries: int
|
99
|
+
elapsed_time: float
|
100
|
+
exception: Optional[Exception] = None
|
101
|
+
actual_wait: Optional[float] = None
|
102
|
+
|
103
|
+
|
104
|
+
# pylint: disable-next=too-many-instance-attributes
|
105
|
+
class RetryInvoker:
|
106
|
+
"""Wrapper class for retry (with backoff) triggered by exceptions.
|
107
|
+
|
108
|
+
Parameters
|
109
|
+
----------
|
110
|
+
wait_factory: Callable[[], Generator[float, None, None]]
|
111
|
+
A generator yielding successive wait times in seconds. If the generator
|
112
|
+
is finite, the giveup event will be triggered when the generator raises
|
113
|
+
`StopIteration`.
|
114
|
+
recoverable_exceptions: Union[Type[Exception], Tuple[Type[Exception]]]
|
115
|
+
An exception type (or tuple of types) that triggers backoff.
|
116
|
+
max_tries: Optional[int]
|
117
|
+
The maximum number of attempts to make before giving up. Once exhausted,
|
118
|
+
the exception will be allowed to escape. If set to None, there is no limit
|
119
|
+
to the number of tries.
|
120
|
+
max_time: Optional[float]
|
121
|
+
The maximum total amount of time to try before giving up. Once this time
|
122
|
+
has expired, this method won't be interrupted immediately, but the exception
|
123
|
+
will be allowed to escape. If set to None, there is no limit to the total time.
|
124
|
+
on_success: Optional[Callable[[RetryState], None]] (default: None)
|
125
|
+
A callable to be executed in the event of success. The parameter is a
|
126
|
+
data class object detailing the invocation.
|
127
|
+
on_backoff: Optional[Callable[[RetryState], None]] (default: None)
|
128
|
+
A callable to be executed in the event of a backoff. The parameter is a
|
129
|
+
data class object detailing the invocation.
|
130
|
+
on_giveup: Optional[Callable[[RetryState], None]] (default: None)
|
131
|
+
A callable to be executed in the event that `max_tries` or `max_time` is
|
132
|
+
exceeded, `should_giveup` returns True, or `wait_factory()` generator raises
|
133
|
+
`StopInteration`. The parameter is a data class object detailing the
|
134
|
+
invocation.
|
135
|
+
jitter: Optional[Callable[[float], float]] (default: full_jitter)
|
136
|
+
A function of the value yielded by `wait_factory()` returning the actual time
|
137
|
+
to wait. This function helps distribute wait times stochastically to avoid
|
138
|
+
timing collisions across concurrent clients. Wait times are jittered by
|
139
|
+
default using the `full_jitter` function. To disable jittering, pass
|
140
|
+
`jitter=None`.
|
141
|
+
should_giveup: Optional[Callable[[Exception], bool]] (default: None)
|
142
|
+
A function accepting an exception instance, returning whether or not
|
143
|
+
to give up prematurely before other give-up conditions are evaluated.
|
144
|
+
If set to None, the strategy is to never give up prematurely.
|
145
|
+
|
146
|
+
Examples
|
147
|
+
--------
|
148
|
+
Initialize a `RetryInvoker` with exponential backoff and invoke a function:
|
149
|
+
|
150
|
+
>>> invoker = RetryInvoker(
|
151
|
+
... exponential, # Or use `lambda: exponential(3, 2)` to pass arguments
|
152
|
+
... grpc.RpcError,
|
153
|
+
... max_tries=3,
|
154
|
+
... max_time=None,
|
155
|
+
... )
|
156
|
+
>>> invoker.invoke(my_func, arg1, arg2, kw1=kwarg1)
|
157
|
+
"""
|
158
|
+
|
159
|
+
def __init__(
|
160
|
+
self,
|
161
|
+
wait_factory: Callable[[], Generator[float, None, None]],
|
162
|
+
recoverable_exceptions: Union[Type[Exception], Tuple[Type[Exception], ...]],
|
163
|
+
max_tries: Optional[int],
|
164
|
+
max_time: Optional[float],
|
165
|
+
*,
|
166
|
+
on_success: Optional[Callable[[RetryState], None]] = None,
|
167
|
+
on_backoff: Optional[Callable[[RetryState], None]] = None,
|
168
|
+
on_giveup: Optional[Callable[[RetryState], None]] = None,
|
169
|
+
jitter: Optional[Callable[[float], float]] = full_jitter,
|
170
|
+
should_giveup: Optional[Callable[[Exception], bool]] = None,
|
171
|
+
) -> None:
|
172
|
+
self.wait_factory = wait_factory
|
173
|
+
self.recoverable_exceptions = recoverable_exceptions
|
174
|
+
self.max_tries = max_tries
|
175
|
+
self.max_time = max_time
|
176
|
+
self.on_success = on_success
|
177
|
+
self.on_backoff = on_backoff
|
178
|
+
self.on_giveup = on_giveup
|
179
|
+
self.jitter = jitter
|
180
|
+
self.should_giveup = should_giveup
|
181
|
+
|
182
|
+
# pylint: disable-next=too-many-locals
|
183
|
+
def invoke(
|
184
|
+
self,
|
185
|
+
target: Callable[..., Any],
|
186
|
+
*args: Any,
|
187
|
+
**kwargs: Any,
|
188
|
+
) -> Any:
|
189
|
+
"""Safely invoke the provided callable with retry mechanisms.
|
190
|
+
|
191
|
+
This method attempts to invoke the given callable, and in the event of
|
192
|
+
a recoverable exception, employs a retry mechanism that considers
|
193
|
+
wait times, jitter, maximum attempts, and maximum time. During the
|
194
|
+
retry process, various callbacks (`on_backoff`, `on_success`, and
|
195
|
+
`on_giveup`) can be triggered based on the outcome.
|
196
|
+
|
197
|
+
Parameters
|
198
|
+
----------
|
199
|
+
target: Callable[..., Any]
|
200
|
+
The callable to be invoked.
|
201
|
+
*args: Tuple[Any, ...]
|
202
|
+
Positional arguments to pass to `target`.
|
203
|
+
**kwargs: Dict[str, Any]
|
204
|
+
Keyword arguments to pass to `target`.
|
205
|
+
|
206
|
+
Returns
|
207
|
+
-------
|
208
|
+
Any
|
209
|
+
The result of the given callable invocation.
|
210
|
+
|
211
|
+
Raises
|
212
|
+
------
|
213
|
+
Exception
|
214
|
+
If the number of tries exceeds `max_tries`, if the total time
|
215
|
+
exceeds `max_time`, if `wait_factory()` generator raises `StopInteration`,
|
216
|
+
or if the `should_giveup` returns True for a raised exception.
|
217
|
+
|
218
|
+
Notes
|
219
|
+
-----
|
220
|
+
The time between retries is determined by the provided `wait_factory()`
|
221
|
+
generator and can optionally be jittered using the `jitter` function.
|
222
|
+
The recoverable exceptions that trigger a retry, as well as conditions to
|
223
|
+
stop retries, are also determined by the class's initialization parameters.
|
224
|
+
"""
|
225
|
+
|
226
|
+
def try_call_event_handler(
|
227
|
+
handler: Optional[Callable[[RetryState], None]]
|
228
|
+
) -> None:
|
229
|
+
if handler is not None:
|
230
|
+
handler(cast(RetryState, ref_state[0]))
|
231
|
+
|
232
|
+
try_cnt = 0
|
233
|
+
wait_generator = self.wait_factory()
|
234
|
+
start = time.time()
|
235
|
+
ref_state: List[Optional[RetryState]] = [None]
|
236
|
+
|
237
|
+
while True:
|
238
|
+
try_cnt += 1
|
239
|
+
elapsed_time = time.time() - start
|
240
|
+
state = RetryState(
|
241
|
+
target=target,
|
242
|
+
args=args,
|
243
|
+
kwargs=kwargs,
|
244
|
+
tries=try_cnt,
|
245
|
+
elapsed_time=elapsed_time,
|
246
|
+
)
|
247
|
+
ref_state[0] = state
|
248
|
+
|
249
|
+
try:
|
250
|
+
ret = target(*args, **kwargs)
|
251
|
+
except self.recoverable_exceptions as err:
|
252
|
+
# Check if giveup event should be triggered
|
253
|
+
max_tries_exceeded = try_cnt == self.max_tries
|
254
|
+
max_time_exceeded = (
|
255
|
+
self.max_time is not None and elapsed_time >= self.max_time
|
256
|
+
)
|
257
|
+
|
258
|
+
def giveup_check(_exception: Exception) -> bool:
|
259
|
+
if self.should_giveup is None:
|
260
|
+
return False
|
261
|
+
return self.should_giveup(_exception)
|
262
|
+
|
263
|
+
if giveup_check(err) or max_tries_exceeded or max_time_exceeded:
|
264
|
+
# Trigger giveup event
|
265
|
+
try_call_event_handler(self.on_giveup)
|
266
|
+
raise
|
267
|
+
|
268
|
+
try:
|
269
|
+
wait_time = next(wait_generator)
|
270
|
+
if self.jitter is not None:
|
271
|
+
wait_time = self.jitter(wait_time)
|
272
|
+
if self.max_time is not None:
|
273
|
+
wait_time = min(wait_time, self.max_time - elapsed_time)
|
274
|
+
state.actual_wait = wait_time
|
275
|
+
except StopIteration:
|
276
|
+
# Trigger giveup event
|
277
|
+
try_call_event_handler(self.on_giveup)
|
278
|
+
raise err from None
|
279
|
+
|
280
|
+
# Trigger backoff event
|
281
|
+
try_call_event_handler(self.on_backoff)
|
282
|
+
|
283
|
+
# Sleep
|
284
|
+
time.sleep(wait_time)
|
285
|
+
else:
|
286
|
+
# Trigger success event
|
287
|
+
try_call_event_handler(self.on_success)
|
288
|
+
return ret
|
{flwr_nightly-1.6.0.dev20231026.dist-info → flwr_nightly-1.6.0.dev20231101.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: flwr-nightly
|
3
|
-
Version: 1.6.0.
|
3
|
+
Version: 1.6.0.dev20231101
|
4
4
|
Summary: Flower: A Friendly Federated Learning Framework
|
5
5
|
Home-page: https://flower.dev
|
6
6
|
License: Apache-2.0
|
@@ -71,22 +71,21 @@ Description-Content-Type: text/markdown
|
|
71
71
|
Flower (`flwr`) is a framework for building federated learning systems. The
|
72
72
|
design of Flower is based on a few guiding principles:
|
73
73
|
|
74
|
-
|
74
|
+
- **Customizable**: Federated learning systems vary wildly from one use case to
|
75
75
|
another. Flower allows for a wide range of different configurations depending
|
76
76
|
on the needs of each individual use case.
|
77
77
|
|
78
|
-
|
78
|
+
- **Extendable**: Flower originated from a research project at the University of
|
79
79
|
Oxford, so it was built with AI research in mind. Many components can be
|
80
80
|
extended and overridden to build new state-of-the-art systems.
|
81
81
|
|
82
|
-
|
82
|
+
- **Framework-agnostic**: Different machine learning frameworks have different
|
83
83
|
strengths. Flower can be used with any machine learning framework, for
|
84
84
|
example, [PyTorch](https://pytorch.org),
|
85
|
-
[TensorFlow](https://tensorflow.org), [Hugging Face Transformers](https://huggingface.co/), [PyTorch Lightning](https://pytorchlightning.ai/), [MXNet](https://mxnet.apache.org/), [scikit-learn](https://scikit-learn.org/), [JAX](https://jax.readthedocs.io/), [TFLite](https://tensorflow.org/lite/), [fastai](https://www.fast.ai/), [Pandas](https://pandas.pydata.org/
|
86
|
-
) for federated analytics, or even raw [NumPy](https://numpy.org/)
|
85
|
+
[TensorFlow](https://tensorflow.org), [Hugging Face Transformers](https://huggingface.co/), [PyTorch Lightning](https://pytorchlightning.ai/), [MXNet](https://mxnet.apache.org/), [scikit-learn](https://scikit-learn.org/), [JAX](https://jax.readthedocs.io/), [TFLite](https://tensorflow.org/lite/), [fastai](https://www.fast.ai/), [Pandas](https://pandas.pydata.org/) for federated analytics, or even raw [NumPy](https://numpy.org/)
|
87
86
|
for users who enjoy computing gradients by hand.
|
88
87
|
|
89
|
-
|
88
|
+
- **Understandable**: Flower is written with maintainability in mind. The
|
90
89
|
community is encouraged to both read and contribute to the codebase.
|
91
90
|
|
92
91
|
Meet the Flower community on [flower.dev](https://flower.dev)!
|
@@ -106,11 +105,11 @@ Flower's goal is to make federated learning accessible to everyone. This series
|
|
106
105
|
2. **Using Strategies in Federated Learning**
|
107
106
|
|
108
107
|
[](https://colab.research.google.com/github/adap/flower/blob/main/doc/source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb) (or open the [Jupyter Notebook](https://github.com/adap/flower/blob/main/doc/source/tutorial-use-a-federated-learning-strategy-pytorch.ipynb))
|
109
|
-
|
108
|
+
|
110
109
|
3. **Building Strategies for Federated Learning**
|
111
110
|
|
112
111
|
[](https://colab.research.google.com/github/adap/flower/blob/main/doc/source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb) (or open the [Jupyter Notebook](https://github.com/adap/flower/blob/main/doc/source/tutorial-series-use-a-federated-learning-strategy-pytorch.ipynb))
|
113
|
-
|
112
|
+
|
114
113
|
4. **Custom Clients for Federated Learning**
|
115
114
|
|
116
115
|
[](https://colab.research.google.com/github/adap/flower/blob/main/doc/source/tutorial-series-customize-the-client-pytorch.ipynb) (or open the [Jupyter Notebook](https://github.com/adap/flower/blob/main/doc/source/tutorial-series-customize-the-client-pytorch.ipynb))
|
@@ -121,39 +120,39 @@ Stay tuned, more tutorials are coming soon. Topics include **Privacy and Securit
|
|
121
120
|
|
122
121
|
[](https://colab.research.google.com/github/adap/flower/blob/main/examples/flower-in-30-minutes/tutorial.ipynb) (or open the [Jupyter Notebook](https://github.com/adap/flower/blob/main/examples/flower-in-30-minutes/tutorial.ipynb))
|
123
122
|
|
124
|
-
|
125
123
|
## Documentation
|
126
124
|
|
127
125
|
[Flower Docs](https://flower.dev/docs):
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
126
|
+
|
127
|
+
- [Installation](https://flower.dev/docs/framework/how-to-install-flower.html)
|
128
|
+
- [Quickstart (TensorFlow)](https://flower.dev/docs/framework/tutorial-quickstart-tensorflow.html)
|
129
|
+
- [Quickstart (PyTorch)](https://flower.dev/docs/framework/tutorial-quickstart-pytorch.html)
|
130
|
+
- [Quickstart (Hugging Face)](https://flower.dev/docs/framework/tutorial-quickstart-huggingface.html)
|
131
|
+
- [Quickstart (PyTorch Lightning [code example])](https://flower.dev/docs/framework/tutorial-quickstart-pytorch-lightning.html)
|
132
|
+
- [Quickstart (MXNet)](https://flower.dev/docs/framework/example-mxnet-walk-through.html)
|
133
|
+
- [Quickstart (Pandas)](https://flower.dev/docs/framework/tutorial-quickstart-pandas.html)
|
134
|
+
- [Quickstart (fastai)](https://flower.dev/docs/framework/tutorial-quickstart-fastai.html)
|
135
|
+
- [Quickstart (JAX)](https://flower.dev/docs/framework/tutorial-quickstart-jax.html)
|
136
|
+
- [Quickstart (scikit-learn)](https://flower.dev/docs/framework/tutorial-quickstart-scikitlearn.html)
|
137
|
+
- [Quickstart (Android [TFLite])](https://flower.dev/docs/framework/tutorial-quickstart-android.html)
|
138
|
+
- [Quickstart (iOS [CoreML])](https://flower.dev/docs/framework/tutorial-quickstart-ios.html)
|
140
139
|
|
141
140
|
## Flower Baselines
|
142
141
|
|
143
142
|
Flower Baselines is a collection of community-contributed experiments that reproduce the experiments performed in popular federated learning publications. Researchers can build on Flower Baselines to quickly evaluate new ideas:
|
144
143
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
144
|
+
- [FedAvg](https://arxiv.org/abs/1602.05629):
|
145
|
+
- [MNIST](https://github.com/adap/flower/tree/main/baselines/flwr_baselines/flwr_baselines/publications/fedavg_mnist)
|
146
|
+
- [FedProx](https://arxiv.org/abs/1812.06127):
|
147
|
+
- [MNIST](https://github.com/adap/flower/tree/main/baselines/fedprox/)
|
148
|
+
- [FedBN: Federated Learning on non-IID Features via Local Batch Normalization](https://arxiv.org/abs/2102.07623):
|
149
|
+
- [Convergence Rate](https://github.com/adap/flower/tree/main/baselines/flwr_baselines/flwr_baselines/publications/fedbn/convergence_rate)
|
150
|
+
- [Adaptive Federated Optimization](https://arxiv.org/abs/2003.00295):
|
151
|
+
- [CIFAR-10/100](https://github.com/adap/flower/tree/main/baselines/flwr_baselines/flwr_baselines/publications/adaptive_federated_optimization)
|
153
152
|
|
154
|
-
Check the Flower documentation to learn more: [Using Baselines](https://flower.dev/docs/baselines/
|
153
|
+
Check the Flower documentation to learn more: [Using Baselines](https://flower.dev/docs/baselines/how-to-use-baselines.html)
|
155
154
|
|
156
|
-
The Flower community loves contributions! Make your work more visible and enable others to build on it by contributing it as a baseline: [Contributing Baselines](https://flower.dev/docs/baselines/
|
155
|
+
The Flower community loves contributions! Make your work more visible and enable others to build on it by contributing it as a baseline: [Contributing Baselines](https://flower.dev/docs/baselines/how-to-contribute-baselines.html)
|
157
156
|
|
158
157
|
## Flower Usage Examples
|
159
158
|
|
@@ -161,26 +160,26 @@ Several code examples show different usage scenarios of Flower (in combination w
|
|
161
160
|
|
162
161
|
Quickstart examples:
|
163
162
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
163
|
+
- [Quickstart (TensorFlow)](https://github.com/adap/flower/tree/main/examples/quickstart-tensorflow)
|
164
|
+
- [Quickstart (PyTorch)](https://github.com/adap/flower/tree/main/examples/quickstart-pytorch)
|
165
|
+
- [Quickstart (Hugging Face)](https://github.com/adap/flower/tree/main/examples/quickstart-huggingface)
|
166
|
+
- [Quickstart (PyTorch Lightning)](https://github.com/adap/flower/tree/main/examples/quickstart-pytorch-lightning)
|
167
|
+
- [Quickstart (fastai)](https://github.com/adap/flower/tree/main/examples/quickstart-fastai)
|
168
|
+
- [Quickstart (Pandas)](https://github.com/adap/flower/tree/main/examples/quickstart-pandas)
|
169
|
+
- [Quickstart (MXNet)](https://github.com/adap/flower/tree/main/examples/quickstart-mxnet)
|
170
|
+
- [Quickstart (JAX)](https://github.com/adap/flower/tree/main/examples/quickstart-jax)
|
171
|
+
- [Quickstart (scikit-learn)](https://github.com/adap/flower/tree/main/examples/sklearn-logreg-mnist)
|
172
|
+
- [Quickstart (Android [TFLite])](https://github.com/adap/flower/tree/main/examples/android)
|
173
|
+
- [Quickstart (iOS [CoreML])](https://github.com/adap/flower/tree/main/examples/ios)
|
175
174
|
|
176
175
|
Other [examples](https://github.com/adap/flower/tree/main/examples):
|
177
176
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
177
|
+
- [Raspberry Pi & Nvidia Jetson Tutorial](https://github.com/adap/flower/tree/main/examples/embedded-devices)
|
178
|
+
- [PyTorch: From Centralized to Federated](https://github.com/adap/flower/tree/main/examples/pytorch-from-centralized-to-federated)
|
179
|
+
- [MXNet: From Centralized to Federated](https://github.com/adap/flower/tree/main/examples/mxnet-from-centralized-to-federated)
|
180
|
+
- [Advanced Flower with TensorFlow/Keras](https://github.com/adap/flower/tree/main/examples/advanced-tensorflow)
|
181
|
+
- [Advanced Flower with PyTorch](https://github.com/adap/flower/tree/main/examples/advanced-pytorch)
|
182
|
+
- Single-Machine Simulation of Federated Learning Systems ([PyTorch](https://github.com/adap/flower/tree/main/examples/simulation_pytorch)) ([Tensorflow](https://github.com/adap/flower/tree/main/examples/simulation_tensorflow))
|
184
183
|
|
185
184
|
## Community
|
186
185
|
|
@@ -192,12 +191,12 @@ Flower is built by a wonderful community of researchers and engineers. [Join Sla
|
|
192
191
|
|
193
192
|
## Citation
|
194
193
|
|
195
|
-
If you publish work that uses Flower, please cite Flower as follows:
|
194
|
+
If you publish work that uses Flower, please cite Flower as follows:
|
196
195
|
|
197
196
|
```bibtex
|
198
197
|
@article{beutel2020flower,
|
199
198
|
title={Flower: A Friendly Federated Learning Research Framework},
|
200
|
-
author={Beutel, Daniel J and Topal, Taner and Mathur, Akhil and Qiu, Xinchi and Fernandez-Marques, Javier and Gao, Yan and Sani, Lorenzo and Kwing, Hei Li and Parcollet, Titouan and Gusmão, Pedro PB de and Lane, Nicholas D},
|
199
|
+
author={Beutel, Daniel J and Topal, Taner and Mathur, Akhil and Qiu, Xinchi and Fernandez-Marques, Javier and Gao, Yan and Sani, Lorenzo and Kwing, Hei Li and Parcollet, Titouan and Gusmão, Pedro PB de and Lane, Nicholas D},
|
201
200
|
journal={arXiv preprint arXiv:2007.14390},
|
202
201
|
year={2020}
|
203
202
|
}
|
{flwr_nightly-1.6.0.dev20231026.dist-info → flwr_nightly-1.6.0.dev20231101.dist-info}/RECORD
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
flwr/__init__.py,sha256=_lnE8lIgk0i4hpag6GWVGPPr1w4IrA5z4y_kFwIpZYM,959
|
2
2
|
flwr/client/__init__.py,sha256=7GyT3nZpvzL0grFGMcKhXrVS_IpctJpUmMk9whAzFNE,1111
|
3
|
-
flwr/client/app.py,sha256
|
3
|
+
flwr/client/app.py,sha256=-ohwtOxk9O2ESlnA_OeWNkishUoNt4hbO3tmNiChdBc,11111
|
4
4
|
flwr/client/client.py,sha256=WPDQzzPQ3VePYZDEjMEMxKWUPDWB21sL_iP12NUPt5o,7894
|
5
5
|
flwr/client/dpfedavg_numpy_client.py,sha256=LxUcPBO0mU3VScAx9vx2PlsghXjQZVEBOn3rolgrgio,7216
|
6
6
|
flwr/client/grpc_client/__init__.py,sha256=LsnbqXiJhgQcB0XzAlUQgPx011Uf7Y7yabIC1HxivJ8,735
|
@@ -26,6 +26,7 @@ flwr/common/dp.py,sha256=hF45cPElXxcQsh4AoquAyaTrNi0xCrIcKx7xOcV_1XU,1782
|
|
26
26
|
flwr/common/grpc.py,sha256=JmFrGeEqFjMKkf6Mn6NlMJdjk27pYHzsn7CquAfR4R0,1896
|
27
27
|
flwr/common/logger.py,sha256=Plgdf5NULsv9leDeNOXTeCqK-7LkZh8R34RPT4EkOs8,3466
|
28
28
|
flwr/common/parameter.py,sha256=-bFAUayToYDF50FZGrBC1hQYJCQDtB2bbr3ZuVLMtdE,2095
|
29
|
+
flwr/common/retry_invoker.py,sha256=RBTiDnYyePWvhBH9GqcWZl0tQaUOVUqOVBwfGprXWEg,10810
|
29
30
|
flwr/common/secure_aggregation/__init__.py,sha256=29nHIUO2L8-KhNHQ2KmIgRo_4CPkq4LgLCUN0on5FgI,731
|
30
31
|
flwr/common/secure_aggregation/crypto/__init__.py,sha256=dz7pVx2aPrHxr_AwgO5mIiTzu4PcvUxRq9NLBbFcsf8,738
|
31
32
|
flwr/common/secure_aggregation/crypto/shamir.py,sha256=yY35ZgHlB4YyGW_buG-1X-0M-ejXuQzISgYLgC_Z9TY,2792
|
@@ -121,8 +122,8 @@ flwr/simulation/ray_transport/__init__.py,sha256=FsaAnzC4cw4DqoouBCix6496k29jACk
|
|
121
122
|
flwr/simulation/ray_transport/ray_actor.py,sha256=EiyXPRnur8pOzGu_h5ZU4t8C5M_amnVPAQWyPSbAnEU,16564
|
122
123
|
flwr/simulation/ray_transport/ray_client_proxy.py,sha256=cPo3Ny1k5arqTLHD0bB5DSEuS66aE2SwEumtr8TzOGc,8778
|
123
124
|
flwr/simulation/ray_transport/utils.py,sha256=MVOH4l1ZPt64WidgBBay--1M3lS82CQ3ebmwU9Cvlo0,3369
|
124
|
-
flwr_nightly-1.6.0.
|
125
|
-
flwr_nightly-1.6.0.
|
126
|
-
flwr_nightly-1.6.0.
|
127
|
-
flwr_nightly-1.6.0.
|
128
|
-
flwr_nightly-1.6.0.
|
125
|
+
flwr_nightly-1.6.0.dev20231101.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
126
|
+
flwr_nightly-1.6.0.dev20231101.dist-info/METADATA,sha256=R2keD6GeJ359rUi7o0nVXaiIXrzkPfaZs71po_Ul96g,13241
|
127
|
+
flwr_nightly-1.6.0.dev20231101.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
|
128
|
+
flwr_nightly-1.6.0.dev20231101.dist-info/entry_points.txt,sha256=1uLlD5tIunkzALMfMWnqjdE_D5hRUX_I1iMmOMv6tZI,181
|
129
|
+
flwr_nightly-1.6.0.dev20231101.dist-info/RECORD,,
|
{flwr_nightly-1.6.0.dev20231026.dist-info → flwr_nightly-1.6.0.dev20231101.dist-info}/LICENSE
RENAMED
File without changes
|
File without changes
|
File without changes
|