This document provides a comprehensive step-by-step guide to executing a Federated Fuzzy Regression Tree (FRT) experiment using fedxai-lib in a distributed Docker environment. The example demonstrates training an interpretable regression model on weather data distributed across multiple client nodes.
- Overview
- Dataset Description
- Environment Setup
- Dataset Preparation
- Docker Infrastructure Deployment
- Federation Execution
- Results and Model Interpretation
- Troubleshooting
We will train a Federated Fuzzy Regression Tree to predict mean temperature based on various meteorological features from the Weather Izimir dataset. The dataset is partitioned horizontally across multiple client nodes, simulating a realistic federated learning scenario where data cannot leave its source.
The federation consists of three types of nodes:
- Director (1 node): Orchestrates the federation and aggregates client statistics
- Clients (4 nodes): Each holds a private partition of the training/test data
- Requester (1 node): Initiates federation requests and monitors execution
Build an interpretable fuzzy regression tree that:
- Maintains data privacy (raw data never leaves client nodes)
- Provides explainable predictions through fuzzy rules
- Implements obfuscation to prevent inference attacks
The dataset contains meteorological measurements from Izimir, Turkey, with the following features:
Input Features:
Max_temperature- Maximum daily temperature (°C)Min_temperature- Minimum daily temperature (°C)Dewpoint- Dew point temperature (°C)Precipitation- Precipitation amount (mm)Sea_level_pressure- Sea level atmospheric pressure (hPa)Standard_pressure- Standard atmospheric pressure (hPa)Visibility- Visibility distance (km)Wind_speed- Average wind speed (km/h)Max_wind_speed- Maximum wind speed (km/h)
Target Variable:
Mean_temperature- Mean daily temperature (°C)
The dataset is partitioned horizontally into 4 client datasets:
datasets_splits/WeatherIzimir/
├── client_X_train_1.csv
├── client_y_train_1.csv
├── client_X_test_1.csv
├── client_y_test_1.csv
├── client_X_train_2.csv
├── client_y_train_2.csv
├── ... (clients 3, 4)
Each client receives approximately 25% of the data, ensuring IID (Independent and Identically Distributed) partitioning.
Ensure you have the following installed:
- Docker (version 20.10+)
- Docker Compose (version 1.29+)
- Git
fedxai-lib/
├── datasets_splits/WeatherIzimir/ # Client data partitions
├── models/ # Output directory for trained models
├── Dockerfile.fedxai_lib # Docker image for fedxai library
├── Dockerfile.requester # Docker image for requester
├── docker-compose-director.yml # Director configuration
├── docker-compose-clients.yml # Clients configuration
└── docker-compose-requester.yml # Requester configurationFor realistic federated scenarios, deploy the system using Docker containers distributed across multiple machines.
# Navigate to repository root
cd fedxai-lib
# Build fedxai library image (used by director and clients)
docker build --progress=plain -f Dockerfile.fedxai_lib -t fedxai .
# Build requester image
docker build --progress=plain -f Dockerfile.requester -t fedlang-requester .Expected Output:
[+] Building 45.3s (12/12) FINISHED
Successfully tagged fedxai:latest
Successfully tagged fedlang-requester:latest
The repository includes three compose files:
docker-compose-director.yml- Runs the director (server/aggregator) nodedocker-compose-clients.yml- Runs client nodes with their data partitionsdocker-compose-requester.yml- Runs the requester node to initiate federations
Key environment variables:
| Variable | Description |
|---|---|
FEDLANG_NODE_TYPE |
Node type: director, client, or requester |
FEDLANG_NODE_NAME |
Unique node identifier (format: name@IP) |
FEDLANG_COOKIE |
Erlang cookie for distributed authentication |
FEDLANG_DIRECTOR_NAME |
Director node identifier for clients to connect |
ERL_FLAGS |
Erlang runtime flags for configuring the Erlang node (e.g., -setcookie for authentication, distributed port configuration) |
If you don't already have the dataset partitions, generate them using the test script:
cd src
poetry run python tests/test_fed_frt_weather_izimir.pyThis script:
- Loads the raw
WeatherIzimir.csvdataset - Normalizes features using RobustScaler and MinMaxScaler
- Partitions data into 4 client datasets as an example (see test files for implementation details on dataset partitioning)
- Saves partitions to
datasets_splits/WeatherIzimir/
Verify data partitions exist:
ls -lh datasets_splits/WeatherIzimir/Expected Output:
client_X_train_1.csv
client_y_train_1.csv
client_X_test_1.csv
client_y_test_1.csv
... (16 files total for 4 clients)
The federation uses the following network configuration:
- Director:
172.20.0.2:9000(bridge network) - Clients: Host network mode with ports
9001-9004 - Requester:
172.20.0.254(bridge network)
Edit the docker-compose files to match your network setup:
docker-compose-director.yml:
environment:
- FEDLANG_NODE_NAME=director@172.16.2.185 # Director's external IP
- FEDLANG_COOKIE=050df51e-1c75-433e-95c3-8e3e1926d6a6docker-compose-clients.yml:
environment:
- FEDLANG_NODE_NAME=client1@172.16.6.42 # Client host IP
- FEDLANG_DIRECTOR_NAME=director@172.16.2.185 # Director's external IP
- FEDLANG_COOKIE=050df51e-1c75-433e-95c3-8e3e1926d6a6docker-compose-requester.yml:
environment:
- FEDLANG_DIRECTOR_NAME=director@172.16.2.185 # Director's external IP
- ERL_FLAGS: -setcookie 050df51e-1c75-433e-95c3-8e3e1926d6a6Important:
- Replace IP addresses with your actual machine IPs
- Keep the same
FEDLANG_COOKIEvalue across all nodes for authentication
# Create directory for model outputs (shared across containers)
sudo mkdir -p /models
sudo chmod 777 /modelsOn the director machine:
docker compose -f docker-compose-director.yml up -dVerify director is running:
docker logs directorExpected Output:
=INFO REPORT==== 18-Oct-2025::22:17:01.404054 ===
Starting node type: "director"
=INFO REPORT==== 18-Oct-2025::22:17:01.404170 ===
Fedlang director, start_link
=INFO REPORT==== 18-Oct-2025::22:17:01.404301 ===
Fedlang director, init
=PROGRESS REPORT==== 18-Oct-2025::22:17:01.404427 ===
supervisor: {local,fedlang_sup}
started: [{pid,<0.302.0>},
{id,fedlang_director},
{mfargs,{fedlang_director,start_link,[]}},
{restart_type,permanent},
{significant,false},
{shutdown,5000},
{child_type,worker}]
=PROGRESS REPORT==== 18-Oct-2025::22:17:01.404623 ===
application: fedlang
started_at: 'director@172.16.2.185'
On client machine(s):
docker compose -f docker-compose-clients.yml up -dVerify clients are running:
docker ps
docker logs client1
docker logs client2
docker logs client3
docker logs client4Expected Output (per client):
=INFO REPORT==== 18-Oct-2025::22:25:58.015750 ===
Starting node type: "client"
=INFO REPORT==== 18-Oct-2025::22:25:58.015813 ===
Fedlang client, start_link
=INFO REPORT==== 18-Oct-2025::22:25:58.015883 ===
Fedlang client, init
=PROGRESS REPORT==== 18-Oct-2025::22:25:58.015986 ===
supervisor: {local,inet_gethost_native_sup}
started: [{pid,<0.304.0>},{mfa,{inet_gethost_native,init,[[]]}}]
=PROGRESS REPORT==== 18-Oct-2025::22:25:58.030063 ===
supervisor: {local,fedlang_sup}
started: [{pid,<0.302.0>},
{id,fedlang_client},
{mfargs,{fedlang_client,start_link,[]}},
{restart_type,permanent},
{significant,false},
{shutdown,5000},
{child_type,worker}]
=PROGRESS REPORT==== 18-Oct-2025::22:25:58.030220 ===
application: fedlang
started_at: 'client1@172.16.6.42'
On the requester machine:
docker compose -f docker-compose-requester.yml up -dVerify requester is running:
docker logs requesterdocker exec -it requester /bin/bashYou are now inside the requester container shell.
Navigate to the scripts directory:
cd scripts
ls executions/View the federation configuration:
cat executions/federated_frt_weather_izimir.jsonConfiguration Details:
The "algorithm" field specifies the algorithm identifier. For a complete list of all available algorithm identifiers and their hyperparameters, see Algorithm_Hyperparameters.md.
{
"algorithm": "federated_frt",
"parameters": {
"gain_threshold": 0.0001,
"max_number_rounds": 100,
"num_fuzzy_sets": 5,
"max_depth": null,
"min_samples_split_ratio": 0.1,
"min_num_clients": 20,
"obfuscate": true,
"features_names": [
"Max_temperature", "Min_temperature", "Dewpoint",
"Precipitation", "Sea_level_pressure", "Standard_pressure",
"Visibility", "Wind_speed", "Max_wind_speed"
],
"target": "Mean_temperature",
"dataset_X_train": "/dataset/X_train.csv",
"dataset_y_train": "/dataset/y_train.csv",
"dataset_X_test": "/dataset/X_test.csv",
"dataset_y_test": "/dataset/y_test.csv",
"model_output_file": "/models/frt_weather_izimir.pickle"
}
}For detailed parameter specifications, see Algorithm_Hyperparameters.md.
Run the federation script:
./run_federation.sh ./executions/federated_frt_weather_izimir.jsonThe federation execution proceeds through multiple stages. You can monitor the execution by checking the director node logs:
docker logs -f directorExample output from the director node:
=INFO REPORT==== 18-Oct-2025::22:28:30.974575 ===
Begin: Round=1, Step=2, Entity="#available_clients", Method="compute_rule_weights_step1"
=INFO REPORT==== 18-Oct-2025::22:28:31.180870 ===
End: Round=1, Step=2, Entity="#available_clients", Method="compute_rule_weights_step1"
=INFO REPORT==== 18-Oct-2025::22:28:31.181253 ===
Begin: Round=1, Step=3, Entity="#server", Method="compute_rule_error_stats"
=INFO REPORT==== 18-Oct-2025::22:28:31.182416 ===
End: Round=1, Step=3, Entity="#server", Method="compute_rule_error_stats"
=INFO REPORT==== 18-Oct-2025::22:28:31.182627 ===
Begin: Round=1, Step=4, Entity="#available_clients", Method="compute_weight_rules_step2"
=INFO REPORT==== 18-Oct-2025::22:28:31.214616 ===
End: Round=1, Step=4, Entity="#available_clients", Method="compute_weight_rules_step2"
=INFO REPORT==== 18-Oct-2025::22:28:31.214972 ===
Begin: Round=1, Step=5, Entity="#server", Method="compute_rule_weights"
=INFO REPORT==== 18-Oct-2025::22:28:31.217633 ===
End: Round=1, Step=5, Entity="#server", Method="compute_rule_weights"
=INFO REPORT==== 18-Oct-2025::22:28:31.217993 ===
Begin: Round=1, Step=1, Entity="#server", Method="save_model"
2025-10-18 22:28:31,218 [MainThread ] [INFO ] model_output_file = /models/frt_weather_izimir.pickle
=INFO REPORT==== 18-Oct-2025::22:28:31.226569 ===
End: Round=1, Step=1, Entity="#server", Method="save_model"
=INFO REPORT==== 18-Oct-2025::22:28:31.226855 ===
Begin: Round=1, Step=2, Entity="#available_clients", Method="save_model"
=INFO REPORT==== 18-Oct-2025::22:28:31.239358 ===
End: Round=1, Step=2, Entity="#available_clients", Method="save_model"
=INFO REPORT==== 18-Oct-2025::22:28:31.239746 ===
Notifying end client: "3b59b111-9ddd-48a4-ae99-42028801757a"
=INFO REPORT==== 18-Oct-2025::22:28:31.240053 ===
Notifying end client: "43bd4712-27cb-4e2f-8af1-318d2fca0309"
=INFO REPORT==== 18-Oct-2025::22:28:31.240238 ===
Notifying end client: "66870db7-b0c2-4092-a582-f23c30b4b448"
=INFO REPORT==== 18-Oct-2025::22:28:31.240591 ===
Notifying end client: "b01ef527-627c-49f6-b7cf-8d0cb32ec25b"
=INFO REPORT==== 18-Oct-2025::22:28:31.240918 ===
handle_info, incoming message {fl_end_str_run,
"b2ad6fbc-1307-4f27-a2e3-8f15c0016f57"}
Exit the requester container:
exitThe trained model is now available on the host machine:
ls -lh /models/Expected Output:
frt_weather_izimir.pickle # Global federated model
frt_weather_izimir_client_0.pickle
frt_weather_izimir_client_1.pickle
... (client-specific models)
import pickle
# Load the trained federated model
with open('/models/frt_weather_izimir.pickle', 'rb') as f:
model = pickle.load(f)
# View model structure
print(f"Number of fuzzy rules: {len(model.get_rules())}")
print(f"Tree depth: {model.root_node.depth}")The FRT model consists of interpretable fuzzy rules in the form:
IF Max_temperature is HIGH AND Dewpoint is MEDIUM
THEN Mean_temperature = 0.85 * Max_temperature + 0.12 * Dewpoint + 0.03
(Weight: 0.92, Support: 0.15, Confidence: 0.88)
import numpy as np
# Example input: [Max_temp, Min_temp, Dewpoint, Precip, Sea_press, Std_press, Vis, Wind, Max_wind]
input_sample = np.array([[25.5, 18.2, 15.3, 0.0, 1013.2, 1012.8, 10.0, 12.5, 20.3]])
# Predict
prediction, rule_id, num_active_rules = model.predict(input_sample)[0]
print(f"Predicted Mean Temperature: {prediction:.2f}°C")
print(f"Activated Rule ID: {rule_id}")
print(f"Number of Active Rules: {num_active_rules}")Symptoms:
Error: Connection refused to director@172.16.2.185
Solutions:
- Verify director is running:
docker logs director - Check firewall rules allow ports 4369 and 9000
- Verify IP addresses in environment variables match actual machine IPs
- Ensure
FEDLANG_COOKIEis identical across all nodes
Symptoms:
FileNotFoundError: /dataset/X_train.csv not found
Solutions:
- Verify dataset partitions exist:
ls datasets_splits/WeatherIzimir/ - Check volume mounts in
docker-compose-clients.yml:volumes: - ./datasets_splits/WeatherIzimir/client_X_train_1.csv:/dataset/X_train.csv
- Ensure paths are relative to docker-compose file location
Symptoms:
- Federation stops at a specific round without error
Solutions:
- Check client logs for errors:
docker logs client1 - Verify all clients are connected: count active clients in director logs
- Increase network timeout: add
-kernel net_ticktime 120toERL_FLAGS
Symptoms:
ls /models/ # Empty directory
Solutions:
- Check volume mount exists:
docker inspect director | grep models - Verify permissions:
ls -ld /models(should be writable) - Check server logs for write errors:
docker logs director
- Main README: README.md
- GitHub Repository: https://github.com/jlcorcuera/fedxai-lib
- Research Papers: See Citations section
For questions or issues, please contact the contributors or open an issue on GitHub.