Quickstart iOS¶
Warning
The experimental Flower iOS SDK is not compatible with the latest version of Flower. iOS support is currently being reworked and will be released in 2025.
This quickstart tutorial is kept for historical purposes and will be updated once the new iOS SDK is released.
In this tutorial we will learn how to train a Neural Network on MNIST using Flower and CoreML on iOS devices.
First of all, for running the Flower Python server, it is recommended to create a virtual environment and run everything within a virtualenv. For the Flower client implementation in iOS, it is recommended to use Xcode as our IDE.
Our example consists of one Python server and two iPhone clients that all have the same model.
Clients are responsible for generating individual weight updates for the model based on their local datasets. These updates are then sent to the server which will aggregate them to produce a better model. Finally, the server sends this improved version of the model back to each client. A complete cycle of weight updates is called a round.
Now that we have a rough idea of what is going on, let’s get started to setup our Flower server environment. We first need to install Flower. You can do this by using pip:
$ pip install flwr
Or Poetry:
$ poetry add flwr
Flower Client¶
Now that we have all our dependencies installed, let’s run a simple distributed training using CoreML as our local training pipeline and MNIST as our dataset. For simplicity reasons we will use the complete Flower client with CoreML, that has been implemented and stored inside the Swift SDK. The client implementation can be seen below:
/// Parses the parameters from the local model and returns them as GetParametersRes struct
///
/// - Returns: Parameters from the local model
public func getParameters() -> GetParametersRes {
let parameters = parameters.weightsToParameters()
let status = Status(code: .ok, message: String())
return GetParametersRes(parameters: parameters, status: status)
}
/// Calls the routine to fit the local model
///
/// - Returns: The result from the local training, e.g., updated parameters
public func fit(ins: FitIns) -> FitRes {
let status = Status(code: .ok, message: String())
let result = runMLTask(configuration: parameters.parametersToWeights(parameters: ins.parameters), task: .train)
let parameters = parameters.weightsToParameters()
return FitRes(parameters: parameters, numExamples: result.numSamples, status: status)
}
/// Calls the routine to evaluate the local model
///
/// - Returns: The result from the evaluation, e.g., loss
public func evaluate(ins: EvaluateIns) -> EvaluateRes {
let status = Status(code: .ok, message: String())
let result = runMLTask(configuration: parameters.parametersToWeights(parameters: ins.parameters), task: .test)
return EvaluateRes(loss: Float(result.loss), numExamples: result.numSamples, status: status)
}
Let’s create a new application project in Xcode and add flwr
as a dependency in your
project. For our application, we will store the logic of our app in FLiOSModel.swift
and the UI elements in ContentView.swift
. We will focus more on FLiOSModel.swift
in this quickstart. Please refer to the full code example to learn more about the app.
Import Flower and CoreML related packages in FLiOSModel.swift
:
import Foundation
import CoreML
import flwr
Then add the mlmodel to the project simply by drag-and-drop, the mlmodel will be bundled
inside the application during deployment to your iOS device. We need to pass the url to
access mlmodel and run CoreML machine learning processes, it can be retrieved by calling
the function Bundle.main.url
. For the MNIST dataset, we need to preprocess it into
MLBatchProvider
object. The preprocessing is done inside DataLoader.swift
.
// prepare train dataset
let trainBatchProvider = DataLoader.trainBatchProvider() { _ in }
// prepare test dataset
let testBatchProvider = DataLoader.testBatchProvider() { _ in }
// load them together
let dataLoader = MLDataLoader(trainBatchProvider: trainBatchProvider,
testBatchProvider: testBatchProvider)
Since CoreML does not allow the model parameters to be seen before training, and
accessing the model parameters during or after the training can only be done by
specifying the layer name, we need to know this information beforehand, through looking
at the model specification, which are written as proto files. The implementation can be
seen in MLModelInspect
.
After we have all of the necessary information, let’s create our Flower client.
let compiledModelUrl = try MLModel.compileModel(at: url)
// inspect the model to be able to access the model parameters
// to access the model we need to know the layer name
// since the model parameters are stored as key value pairs
let modelInspect = try MLModelInspect(serializedData: Data(contentsOf: url))
let layerWrappers = modelInspect.getLayerWrappers()
self.mlFlwrClient = MLFlwrClient(layerWrappers: layerWrappers,
dataLoader: dataLoader,
compiledModelUrl: compiledModelUrl)
Then start the Flower gRPC client and start communicating to the server by passing our
Flower client to the function startFlwrGRPC
.
self.flwrGRPC = FlwrGRPC(serverHost: hostname, serverPort: port)
self.flwrGRPC.startFlwrGRPC(client: self.mlFlwrClient)
That’s it for the client. We only have to implement Client
or call the provided
MLFlwrClient
and call startFlwrGRPC()
. The attribute hostname
and port
tells the client which server to connect to. This can be done by entering the hostname
and port in the application before clicking the start button to start the federated
learning process.
Flower Server¶
For simple workloads we can start a Flower server and leave all the configuration
possibilities at their default values. In a file named server.py
, import Flower and
start the server:
import flwr as fl
fl.server.start_server(config=fl.server.ServerConfig(num_rounds=3))
Train the model, federated!¶
With both client and server ready, we can now run everything and see federated learning in action. FL systems usually have a server and multiple clients. We therefore have to start the server first:
$ python server.py
Once the server is running we can start the clients in different terminals. Build and run the client through your Xcode, one through Xcode Simulator and the other by deploying it to your iPhone. To see more about how to deploy your app to iPhone or Simulator visit here.
Congratulations! You’ve successfully built and run your first federated learning system
in your ios device. The full source code for this example can be found
in examples/ios
.