<jupyter_start><jupyter_text>[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/bitfount/tutorials/main?labpath=03_training_a_model.ipynb) Federated Learning - Part 3: Querying and Training a modelIn this tutorial we will first learn how to execute queries on a pod, then understand how to train a model on a federated dataset.You will use the pod you set up in Part 1, so make sure you have run that first. 3.1 Requesting accessNormally, if you are training on a pod you do not own, you will have to request access.To do this, you would go to https://hub.bitfount.com/{username}/pods/{pod-identifier}.For the purpose of this tutorial, you will be using the pod you set up in Part 1, so you won't need to request any access.> ℹ️ In this tutorial, we will be training a model. This can also be done by using a YAML configuration file, which we will explain in Tutorial 4.Let's import the relevant pieces...<jupyter_code>import logging
from pathlib import Path

import nest_asyncio

from bitfount import (
    DataStructure,
    FederatedAveraging,
    FederatedModelTraining,
    Optimizer,
    PyTorchTabularClassifier,
    get_pod_schema,
)
from bitfount.federated.algorithms.model_algorithms.federated_training import (
    FederatedModelTraining,
)
from bitfount.federated.algorithms.sql_query import SqlQuery
from bitfount.federated.protocols.fed_avg import FederatedAveraging
from bitfount.runners.utils import setup_loggers

nest_asyncio.apply()  # Needed because Jupyter also has an asyncio loop<jupyter_output><empty_output><jupyter_text>Let's set up the loggers.<jupyter_code>loggers = setup_loggers([logging.getLogger("bitfount")])<jupyter_output><empty_output><jupyter_text>3.2 Querying a podWe can run a SQL query on a pod by specifying our query as a parameter to the `SQLQuery` algorithm. We then pass the `pod_identifier(s)` we would like to execute the query on.<jupyter_code>pod_identifier = "adult-demo"
query = SqlQuery(
    query="""
SELECT `occupation`, AVG(`age`)
FROM df
GROUP BY `occupation`
"""
)
query.execute(pod_identifiers=[pod_identifier])<jupyter_output><empty_output><jupyter_text>3.3 Training a modelNormally, there are a few parameters to specify in the configuration for this training run.- `pod identifier`: The list of pods that hold the data you want to train on- `data structure`: The structure of the data on which we will train the model. It contains the target column, columns to select/ignore for training.- `schema`: For training a model on a pod, we need to download the pod schema.- `protocol`: The federated learning protocol to use. Note that you must have approval from the pod!- `algorithm`: The federated learning algorithm to use.- `aggregator`: This may be required depending on your chosen protocol- `model`: The model you want to train- `model hyperparameters`: The settings used by the modelHowever, for this tutorial, we will use the default protocol (Federated Averaging) and Algorithm (Federated Model Training).In tutorial 9, we will show how to change these default protocol and algorithm.Let's define the model that we will use and the relevant data structures.<jupyter_code>pod_identifier = "adult-demo"
schema = get_pod_schema(pod_identifier)

model = PyTorchTabularClassifier(
    datastructure=DataStructure(target="TARGET", table="adult-demo"),
    schema=schema,
    epochs=1,
    batch_size=64,
    optimizer=Optimizer(name="SGD", params={"lr": 0.001}),
)<jupyter_output><empty_output><jupyter_text>That's all the setup, let's run the training!<jupyter_code>model.fit(pod_identifiers=[pod_identifier])<jupyter_output><empty_output><jupyter_text>Let's also serialize and save the model, as we will need it in one of the later tutorials.<jupyter_code>model_out = Path("part_3_model.pt")
model.serialize(model_out)<jupyter_output><empty_output><jupyter_text>Above you ran `model.fit()` to train your model. In this way the `bitfount` package set up the `FerderatedAveraging` protocol for you. Alternatively we can achieve the equivalent by explicitly specifying the protocol we want and calling `.run()`. We demonstrate this below with the `FederatedAveraging` protocol to replicate the results but this can be switched out for any protocol.<jupyter_code>protocol = FederatedAveraging(algorithm=FederatedModelTraining(model=model))
protocol.run(pod_identifiers=[pod_identifier])<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08047283473516709, 'fraction_numerical': 0.005001136621959537, 'mean_word_length': 5.779661016949152, 'pattern_counts': {'":': 1, '<': 29, '<?xml version=': 0, '>': 30, 'https://': 3, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '625619', 'license': 'Apache-2.0', 'n_tokens_mistral': 1320, 'n_tokens_neox': 1264, 'n_words': 489, 'path': '03_querying_and_training_a_model.ipynb', 'repo_name': 'bitfount/tutorials', 'size': '4399'}