0.14.0
What's new?
-
Generalized
Client.fit
andClient.evaluate
return values (#610, #572, #633)Clients can now return an additional dictionary mapping
str
keys to values of the following types:bool
,bytes
,float
,int
,str
. This means one can return almost arbitrary values fromfit
/evaluate
and make use of them on the server side!This improvement also allowed for more consistent return types between
fit
andevaluate
:evaluate
should now return a tuple(float, int, dict)
representing the loss, number of examples, and a dictionary holding arbitrary problem-specific values like accuracy.In case you wondered: this feature is compatible with existing projects, the additional dictionary return value is optional. New code should however migrate to the new return types to be compatible with upcoming Flower releases (
fit
:List[np.ndarray], int, Dict[str, Scalar]
,evaluate
:float, int, Dict[str, Scalar]
). See the example below for details.Code example: note the additional dictionary return values in both
FlwrClient.fit
andFlwrClient.evaluate
:class FlwrClient(fl.client.NumPyClient): def fit(self, parameters, config): net.set_parameters(parameters) train_loss = train(net, trainloader) return net.get_weights(), len(trainloader), {"train_loss": train_loss} def evaluate(self, parameters, config): net.set_parameters(parameters) loss, accuracy, custom_metric = test(net, testloader) return loss, len(testloader), {"accuracy": accuracy, "custom_metric": custom_metric}
-
Generalized
config
argument inClient.fit
andClient.evaluate
(#595)The
config
argument used to be of typeDict[str, str]
, which means that dictionary values were expected to be strings. The new release generalizes this to enable values of the following types:bool
,bytes
,float
,int
,str
.This means one can now pass almost arbitrary values to
fit
/evaluate
using theconfig
dictionary. Yay, no morestr(epochs)
on the server-side andint(config["epochs"])
on the client side!Code example: note that the
config
dictionary now contains non-str
values in bothClient.fit
andClient.evaluate
:class FlwrClient(fl.client.NumPyClient): def fit(self, parameters, config): net.set_parameters(parameters) epochs: int = config["epochs"] train_loss = train(net, trainloader, epochs) return net.get_weights(), len(trainloader), {"train_loss": train_loss} def evaluate(self, parameters, config): net.set_parameters(parameters) batch_size: int = config["batch_size"] loss, accuracy = test(net, testloader, batch_size) return loss, len(testloader), {"accuracy": accuracy}