diff --git a/exercises/0-intro/src/.ipynb_checkpoints/lenet-checkpoint.png b/exercises/0-intro/src/.ipynb_checkpoints/lenet-checkpoint.png new file mode 100644 index 0000000000000000000000000000000000000000..dc50e56a7fe293b5f12c8bae466493f54017c5ee Binary files /dev/null and b/exercises/0-intro/src/.ipynb_checkpoints/lenet-checkpoint.png differ diff --git a/exercises/1-federated_learning/.ipynb_checkpoints/clientlib-checkpoint.py b/exercises/1-federated_learning/.ipynb_checkpoints/clientlib-checkpoint.py new file mode 100644 index 0000000000000000000000000000000000000000..4f5cf709770b82233b7b45ef93c4878787497d78 --- /dev/null +++ b/exercises/1-federated_learning/.ipynb_checkpoints/clientlib-checkpoint.py @@ -0,0 +1,51 @@ +import io +import pickle +import requests +import time +import torch + + +def _parse_model(ser): + data = pickle.loads(ser) + model_bytes = data['model_bytes'] + model_metadata = data['model_metadata'] + model_bytes_io = io.BytesIO(model_bytes) + model = torch.load(model_bytes_io) + return model, model_metadata + + +def _get_model_metadata(server): + url = f'http://{server}/api/get_model_metadata' + r = requests.get(url) + assert r.ok, r.text + return pickle.loads(r.content)['model_metadata'] + + +def wait_for_next_round(server, last_trained_round=None, join_late_by_max=10): + while True: + metadata = _get_model_metadata(server) + if metadata['round_age'] < join_late_by_max: + if last_trained_round != metadata['round']: + return + time.sleep(1) + + +def get_model_and_notify_client_started(server, client_id): + url = f'http://{server}/api/get_model_and_notify_client_started' + r = requests.post(url, data={'client_id': client_id}) + assert r.ok, r.text + return _parse_model(r.content) + + +def upload_updated_model(server, client_id, model, model_metadata): + model_bytes_io = io.BytesIO() + torch.save(model, model_bytes_io) + model_bytes_io.seek(0) + model_bytes = model_bytes_io.read() + data = {'model_bytes': model_bytes, 'model_metadata': model_metadata, 'client_id': client_id} + ser = pickle.dumps(data) + + url = f'http://{server}/api/upload_updated_model' + r = requests.post(url, data=ser) + if not r.ok: + print('ERROR', r.text) diff --git a/exercises/1-federated_learning/.ipynb_checkpoints/exercise_10-checkpoint.ipynb b/exercises/1-federated_learning/.ipynb_checkpoints/exercise_10-checkpoint.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..490f0d328c3123935740ba929bf0b01690370c29 --- /dev/null +++ b/exercises/1-federated_learning/.ipynb_checkpoints/exercise_10-checkpoint.ipynb @@ -0,0 +1,220 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "5fa2a19a-a0ec-46dc-aeef-efacd662be23", + "metadata": {}, + "source": [ + "# Embedded ML Lab - Excercise 1- Federated Learning\n", + "\n", + "In this exercise, we will explore federated learning (FL).\n", + "\n", + "To recap, the core idea of FL is that many *devices* collaboratively train a single model, where each device has its own local private training data. Each device performs local training with its own data, and exchanges the weights of the NN model with all other devices via the *server*.\n", + "\n", + "You are one participant in an FL system that comprises all participating students in this lab.\n", + "\n", + "This excercise comprises two parts.\n", + "* First, we will implement decentralized single-device training, i.e., no collaboration between devices. This will serve as a baseline to compare FL to.\n", + "* Second, we will implement actual FL, where all participants collaboratively train a model." + ] + }, + { + "cell_type": "markdown", + "id": "c7241e36-23e2-4ce4-9d97-8ce24e923c43", + "metadata": {}, + "source": [ + "## Part 1: Decentralized single-device training\n", + "\n", + "We start with the data. Therefore, we randomly distribute the CIFAR-10 dataset among all participants. This is already implemented in the helper functions in device_data. It divides the dataset into `total_clients` parts and returns the part with the number `client_id`.\n", + "\n", + "We also make use of test data. This is usually not available in FL. However, we still use it to test the model quality. Of course, the test data must not be used for training -- only testing." + ] + }, + { + "cell_type": "markdown", + "id": "6147e564-3e31-469d-af14-3d7c95a078cf", + "metadata": {}, + "source": [ + "Adjust the following constants to the participants in the lab. Each participant is one client. Make sure that you use a different *CLIENT_ID*, each." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "a3535eb2-c3e5-4e88-87c6-3f2bd44ff281", + "metadata": {}, + "outputs": [], + "source": [ + "TOTAL_CLIENTS = 11 # number of participants in the lab\n", + "CLIENT_ID = 4 # between 0 and TOTAL_CLIENTS-1" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "76aa6d0f-8b95-4763-b001-2babbba0bcc0", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Files already downloaded and verified\n", + "Files already downloaded and verified\n", + "4546\n" + ] + } + ], + "source": [ + "import torch\n", + "import device_data\n", + "\n", + "training_dataset = device_data.get_client_training_data(CLIENT_ID, TOTAL_CLIENTS)\n", + "train_loader = torch.utils.data.DataLoader(training_dataset, batch_size=16)\n", + "test_dataset = device_data.get_test_data()\n", + "test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=16)\n", + "\n", + "print(len(training_dataset))" + ] + }, + { + "cell_type": "markdown", + "id": "485fdea9-e0f7-412a-9528-2f17b334d02e", + "metadata": {}, + "source": [ + "You are already familiar with training an NN in PyTorch. We want to train a CifarNet with your part of the training data.\n", + "\n", + "**Your Task:**\n", + "- Create a instance of CifarNet, define the optimizer and the criteron. For the optimizer use `torch.optim.SGD` (https://pytorch.org/docs/stable/generated/torch.optim.SGD.html) , for the loss use criterion use `torch.nn.CrossEntropyLoss`. Use a learning rate of `0.001` and a momentum of `0.9`\n", + "- implement the function train that trains the model CifarNet. The function `train` takes the model (an instance), the optimizer, an optimization criterion, a trainloader, and a device (either `cpu` or `cuda` as input)\n", + " - Firstly, set the model in training mode, load the model on the device. Secondly, push the `inputs` and `targets` to the device.\n", + " - Inside the batch loader loop, set the grads of the optimizer to zero (`.zero_grad()`) and push the inputs into the model. After that, calculate the loss and call backward on the loss. Lastly, apply the optimizer step.\n", + "- Implement the function test that tests the model CifarNet, The function `test` takes the model (an instance), a testloader, and the device as input. The function returns the accuracy.\n", + " - Set the model into evaluation mode, for each batch calculate the number of correct detected and all detections.\n", + " - Return the accuracy (fraction of correct detected and all)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "ebfe3586-4082-4a70-b387-a9546c673f43", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 1/10: accuracy (0.39) \n", + "Epoch 2/10: accuracy (0.44) \n", + "Epoch 3/10: accuracy (0.47) \n", + "Epoch 4/10: accuracy (0.48) \n", + "Epoch 5/10: accuracy (0.49) \n", + "Epoch 6/10: accuracy (0.49) \n", + "Epoch 7/10: accuracy (0.49) \n", + "Epoch 8/10: accuracy (0.51) \n", + "Epoch 9/10: accuracy (0.51) \n", + "Epoch 10/10: accuracy (0.49) \n" + ] + } + ], + "source": [ + "# this reaches <70% with 4 clients\n", + "\n", + "from models.cifarnet import CifarNet\n", + "from tqdm import tqdm\n", + "import sys\n", + "\n", + "device = 'cuda'\n", + "epochs = 10\n", + "\n", + "#create a model instance and define loss and optimizer criterion\n", + "#-to-be-done-by-student-------------\n", + "model = CifarNet().to(device)\n", + "optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\n", + "criterion = torch.nn.CrossEntropyLoss()\n", + "#-----------------------------------\n", + "\n", + "def train(model, optimizer, criterion, trainloader, device='cpu'):\n", + " \n", + " #-to-be-done-by-student---------\n", + " model.train()\n", + " #-------------------------------\n", + " \n", + " for _, (inputs, targets) in enumerate(tqdm(trainloader, ncols=80,\n", + " file=sys.stdout, desc=\"Training\", leave=False)):\n", + " \n", + " #-to-be-done-by-student----\n", + " inputs = inputs.to(device)\n", + " targets = targets.to(device)\n", + " \n", + " optimizer.zero_grad()\n", + " \n", + " outputs = model(inputs)\n", + " loss = criterion(outputs, targets)\n", + " \n", + " loss.backward()\n", + " optimizer.step()\n", + " #--------------------------\n", + "\n", + "def test(model, testloader, device='cpu'):\n", + " num_correct = 0\n", + " num_samples = 0\n", + " \n", + " #-to-be-done-by-student---------\n", + " model.eval()\n", + " #-------------------------------\n", + " \n", + " for _, (inputs, targets) in enumerate(tqdm(testloader, ncols=80,\n", + " file=sys.stdout, desc=\"Testing\", leave=False)):\n", + " #-to-be-done-by-student----\n", + " inputs = inputs.to(device)\n", + " targets = targets.to(device)\n", + " \n", + " outputs = model(inputs)\n", + " indexes = outputs.argmax(dim=1)\n", + " \n", + " num_correct += (indexes == targets).float().sum()\n", + " num_samples += inputs.shape[0]\n", + " #--------------------------\n", + " \n", + " return num_correct / num_samples\n", + "\n", + "for epoch in range(epochs):\n", + " train(model, optimizer, criterion, train_loader, device=device)\n", + " accuracy = test(model, test_loader, device=device)\n", + " print(f'Epoch {epoch+1:2d}/{epochs:2d}: accuracy ({accuracy:.2f})')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "amended-bachelor", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/exercises/1-federated_learning/.ipynb_checkpoints/exercise_11-checkpoint.ipynb b/exercises/1-federated_learning/.ipynb_checkpoints/exercise_11-checkpoint.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..ec4dbef7801061df8ccca6558b33b542d5746e8a --- /dev/null +++ b/exercises/1-federated_learning/.ipynb_checkpoints/exercise_11-checkpoint.ipynb @@ -0,0 +1,268 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "88d20a0a-e183-43bc-8918-24d2f22ef634", + "metadata": {}, + "source": [ + "## Part 2: Federated Learning\n", + "\n", + "You already have trained the model locally on your device with your (limited) data. We want now to extend this to FL.\n", + "\n", + "Some helper functions are already implemented in *clientlib.py*:\n", + "- **wait_for_next_round**(server, last_trained_round=None, join_late_by_max=10):\n", + "Wait until a new round has started. A round is considered new if it is younger than *join_late_by_max* seconds. The parameter *last_trained_round* may be used to indicate the last round that the client has last participated (i.e., wait for a round != last_trained_round).\n", + "\n", + "- **get_model_and_notify_client_started**(server, client_id):\n", + "Registers the client at the server and downloads the current model and metadata. *metadata['round']* contains the current round number.\n", + "\n", + "- **upload_updated_model**(server, client_id, model, model_metadata):\n", + "Upload an updated model from the server. *model_metadata* must be the same as returned by *get_model_and_notify_client_started*." + ] + }, + { + "cell_type": "markdown", + "id": "d31527d0-b1a5-4369-aea0-e092609f5a95", + "metadata": {}, + "source": [ + "FL specifications:\n", + "- train for **one epoch** with your local dataset in each round. Testing is not required (but may be interesting?)\n", + "- use the same hyperparameters as in part 1\n", + "- a round ends after 60s latest. If you upload your model too late, it is rejected by the server. **Do not cheat by changing model_metadata before uploading.**\n", + "\n", + "**Your Task:**\n", + "- Implement the Federated Learning training on the client, for that in a loop do the following things\n", + "- 1) Wait for the next round to start using the helper function `clientlib.wait_for_next_round()`.\n", + "- 2) Download the newly averaged model from the server using the helper functions.\n", + "- 3) Train your model with your data, similar to on-device training.\n", + "- 4) Upload the model using the helper function\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "5e98b6e3-c7bd-44bb-ad84-55f41f064c10", + "metadata": {}, + "outputs": [], + "source": [ + "TOTAL_CLIENTS = 11 # number of participants in the lab\n", + "CLIENT_ID = 4 # between 0 and TOTAL_CLIENTS-1" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "0d64fc72-8577-4c5f-996e-54f3c9ad9d81", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Files already downloaded and verified\n", + "Files already downloaded and verified\n" + ] + } + ], + "source": [ + "import torch\n", + "import device_data\n", + "\n", + "training_dataset = device_data.get_client_training_data(CLIENT_ID, TOTAL_CLIENTS)\n", + "train_loader = torch.utils.data.DataLoader(training_dataset, batch_size=16)\n", + "test_dataset = device_data.get_test_data()\n", + "test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=16)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "35692a25-7929-4937-8469-11ab40fae52d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Starting round\n", + "downloaded model -> train (round 79)\n", + "training took 10.1s \n", + "upload updated model\n", + "Starting round\n", + "downloaded model -> train (round 80)\n", + "training took 10.1s \n", + "upload updated model\n", + "Starting round\n" + ] + }, + { + "ename": "ConnectionError", + "evalue": "HTTPConnectionPool(host='federated-learning.in8.itec.kit.edu', port=80): Max retries exceeded with url: /api/get_model_metadata (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f35bf7a20>: Failed to establish a new connection: [Errno 111] Connection refused',))", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mConnectionRefusedError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/urllib3/connection.py\u001b[0m in \u001b[0;36m_new_conn\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 174\u001b[0m conn = connection.create_connection(\n\u001b[0;32m--> 175\u001b[0;31m \u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_dns_host\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mport\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mextra_kw\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 176\u001b[0m )\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/urllib3/util/connection.py\u001b[0m in \u001b[0;36mcreate_connection\u001b[0;34m(address, timeout, source_address, socket_options)\u001b[0m\n\u001b[1;32m 94\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0merr\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 95\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0merr\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 96\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/urllib3/util/connection.py\u001b[0m in \u001b[0;36mcreate_connection\u001b[0;34m(address, timeout, source_address, socket_options)\u001b[0m\n\u001b[1;32m 84\u001b[0m \u001b[0msock\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbind\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msource_address\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 85\u001b[0;31m \u001b[0msock\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mconnect\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msa\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 86\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0msock\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mConnectionRefusedError\u001b[0m: [Errno 111] Connection refused", + "\nDuring handling of the above exception, another exception occurred:\n", + "\u001b[0;31mNewConnectionError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/urllib3/connectionpool.py\u001b[0m in \u001b[0;36murlopen\u001b[0;34m(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw)\u001b[0m\n\u001b[1;32m 709\u001b[0m \u001b[0mheaders\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mheaders\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 710\u001b[0;31m \u001b[0mchunked\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mchunked\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 711\u001b[0m )\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/urllib3/connectionpool.py\u001b[0m in \u001b[0;36m_make_request\u001b[0;34m(self, conn, method, url, timeout, chunked, **httplib_request_kw)\u001b[0m\n\u001b[1;32m 397\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 398\u001b[0;31m \u001b[0mconn\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrequest\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmethod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0murl\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mhttplib_request_kw\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 399\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/urllib3/connection.py\u001b[0m in \u001b[0;36mrequest\u001b[0;34m(self, method, url, body, headers)\u001b[0m\n\u001b[1;32m 238\u001b[0m \u001b[0mheaders\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"User-Agent\"\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_get_default_user_agent\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 239\u001b[0;31m \u001b[0msuper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mHTTPConnection\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrequest\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmethod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0murl\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbody\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mbody\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mheaders\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mheaders\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 240\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/lib/python3.6/http/client.py\u001b[0m in \u001b[0;36mrequest\u001b[0;34m(self, method, url, body, headers, encode_chunked)\u001b[0m\n\u001b[1;32m 1280\u001b[0m \u001b[0;34m\"\"\"Send a complete request to the server.\"\"\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1281\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_send_request\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmethod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0murl\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbody\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mheaders\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mencode_chunked\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1282\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/lib/python3.6/http/client.py\u001b[0m in \u001b[0;36m_send_request\u001b[0;34m(self, method, url, body, headers, encode_chunked)\u001b[0m\n\u001b[1;32m 1326\u001b[0m \u001b[0mbody\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_encode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbody\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'body'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1327\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mendheaders\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbody\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mencode_chunked\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mencode_chunked\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1328\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/lib/python3.6/http/client.py\u001b[0m in \u001b[0;36mendheaders\u001b[0;34m(self, message_body, encode_chunked)\u001b[0m\n\u001b[1;32m 1275\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mCannotSendHeader\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1276\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_send_output\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmessage_body\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mencode_chunked\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mencode_chunked\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1277\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/lib/python3.6/http/client.py\u001b[0m in \u001b[0;36m_send_output\u001b[0;34m(self, message_body, encode_chunked)\u001b[0m\n\u001b[1;32m 1041\u001b[0m \u001b[0;32mdel\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_buffer\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1042\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1043\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/lib/python3.6/http/client.py\u001b[0m in \u001b[0;36msend\u001b[0;34m(self, data)\u001b[0m\n\u001b[1;32m 979\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mauto_open\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 980\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mconnect\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 981\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/urllib3/connection.py\u001b[0m in \u001b[0;36mconnect\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 204\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mconnect\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 205\u001b[0;31m \u001b[0mconn\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_new_conn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 206\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_prepare_conn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mconn\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/urllib3/connection.py\u001b[0m in \u001b[0;36m_new_conn\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 186\u001b[0m raise NewConnectionError(\n\u001b[0;32m--> 187\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"Failed to establish a new connection: %s\"\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0me\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 188\u001b[0m )\n", + "\u001b[0;31mNewConnectionError\u001b[0m: <urllib3.connection.HTTPConnection object at 0x7f35bf7a20>: Failed to establish a new connection: [Errno 111] Connection refused", + "\nDuring handling of the above exception, another exception occurred:\n", + "\u001b[0;31mMaxRetryError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/requests/adapters.py\u001b[0m in \u001b[0;36msend\u001b[0;34m(self, request, stream, timeout, verify, cert, proxies)\u001b[0m\n\u001b[1;32m 449\u001b[0m \u001b[0mretries\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmax_retries\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 450\u001b[0;31m \u001b[0mtimeout\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 451\u001b[0m )\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/urllib3/connectionpool.py\u001b[0m in \u001b[0;36murlopen\u001b[0;34m(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw)\u001b[0m\n\u001b[1;32m 785\u001b[0m retries = retries.increment(\n\u001b[0;32m--> 786\u001b[0;31m \u001b[0mmethod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0murl\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0merror\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0me\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_pool\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_stacktrace\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0msys\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexc_info\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 787\u001b[0m )\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/urllib3/util/retry.py\u001b[0m in \u001b[0;36mincrement\u001b[0;34m(self, method, url, response, error, _pool, _stacktrace)\u001b[0m\n\u001b[1;32m 591\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mnew_retry\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mis_exhausted\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 592\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mMaxRetryError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0m_pool\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0murl\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0merror\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0mResponseError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcause\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 593\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mMaxRetryError\u001b[0m: HTTPConnectionPool(host='federated-learning.in8.itec.kit.edu', port=80): Max retries exceeded with url: /api/get_model_metadata (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f35bf7a20>: Failed to establish a new connection: [Errno 111] Connection refused',))", + "\nDuring handling of the above exception, another exception occurred:\n", + "\u001b[0;31mConnectionError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m<ipython-input-7-f7910e17da6c>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 59\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 60\u001b[0m \u001b[0;31m#-to-be-done-by-student-----\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 61\u001b[0;31m \u001b[0mclientlib\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwait_for_next_round\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mSERVER\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 62\u001b[0m \u001b[0mmodel\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmodel_metadata\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mclientlib\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_model_and_notify_client_started\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mSERVER\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mCLIENT_ID\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 63\u001b[0m \u001b[0mmodel\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mto\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdevice\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/embedded-ml-lab-students-ss24/exercises/1-federated_learning/clientlib.py\u001b[0m in \u001b[0;36mwait_for_next_round\u001b[0;34m(server, last_trained_round, join_late_by_max)\u001b[0m\n\u001b[1;32m 24\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mwait_for_next_round\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mserver\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlast_trained_round\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mjoin_late_by_max\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m10\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 25\u001b[0m \u001b[0;32mwhile\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 26\u001b[0;31m \u001b[0mmetadata\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_get_model_metadata\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mserver\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 27\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mmetadata\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'round_age'\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m<\u001b[0m \u001b[0mjoin_late_by_max\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 28\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mlast_trained_round\u001b[0m \u001b[0;34m!=\u001b[0m \u001b[0mmetadata\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'round'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/embedded-ml-lab-students-ss24/exercises/1-federated_learning/clientlib.py\u001b[0m in \u001b[0;36m_get_model_metadata\u001b[0;34m(server)\u001b[0m\n\u001b[1;32m 17\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_get_model_metadata\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mserver\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0murl\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34mf'http://{server}/api/get_model_metadata'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 19\u001b[0;31m \u001b[0mr\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mrequests\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0murl\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 20\u001b[0m \u001b[0;32massert\u001b[0m \u001b[0mr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mok\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtext\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 21\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mpickle\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mloads\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcontent\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'model_metadata'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/requests/api.py\u001b[0m in \u001b[0;36mget\u001b[0;34m(url, params, **kwargs)\u001b[0m\n\u001b[1;32m 73\u001b[0m \"\"\"\n\u001b[1;32m 74\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 75\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mrequest\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'get'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0murl\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mparams\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mparams\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 76\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 77\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/requests/api.py\u001b[0m in \u001b[0;36mrequest\u001b[0;34m(method, url, **kwargs)\u001b[0m\n\u001b[1;32m 59\u001b[0m \u001b[0;31m# cases, and look like a memory leak in others.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 60\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0msessions\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mSession\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0msession\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 61\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0msession\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrequest\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmethod\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mmethod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0murl\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0murl\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 62\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 63\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/requests/sessions.py\u001b[0m in \u001b[0;36mrequest\u001b[0;34m(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)\u001b[0m\n\u001b[1;32m 527\u001b[0m }\n\u001b[1;32m 528\u001b[0m \u001b[0msend_kwargs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mupdate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msettings\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 529\u001b[0;31m \u001b[0mresp\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mprep\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0msend_kwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 530\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 531\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mresp\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/requests/sessions.py\u001b[0m in \u001b[0;36msend\u001b[0;34m(self, request, **kwargs)\u001b[0m\n\u001b[1;32m 643\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 644\u001b[0m \u001b[0;31m# Send the request\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 645\u001b[0;31m \u001b[0mr\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0madapter\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrequest\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 646\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 647\u001b[0m \u001b[0;31m# Total elapsed time of the request (approximately)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/requests/adapters.py\u001b[0m in \u001b[0;36msend\u001b[0;34m(self, request, stream, timeout, verify, cert, proxies)\u001b[0m\n\u001b[1;32m 517\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mSSLError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0me\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrequest\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mrequest\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 518\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 519\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mConnectionError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0me\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrequest\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mrequest\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 520\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 521\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mClosedPoolError\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mConnectionError\u001b[0m: HTTPConnectionPool(host='federated-learning.in8.itec.kit.edu', port=80): Max retries exceeded with url: /api/get_model_metadata (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f35bf7a20>: Failed to establish a new connection: [Errno 111] Connection refused',))" + ] + } + ], + "source": [ + "import clientlib\n", + "SERVER = 'federated-learning.in8.itec.kit.edu:80'\n", + "\n", + "# this reaches 76% within 10 rounds with 4 clients\n", + "\n", + "torch.set_num_threads(1)\n", + "\n", + "import time\n", + "from tqdm import tqdm\n", + "import sys\n", + "\n", + "device = 'cuda'\n", + "\n", + "def train(model, optimizer, criterion, trainloader, device='cpu'):\n", + " \n", + " #-to-be-done-by-student-----\n", + " model.train()\n", + " \n", + " for _, (inputs, targets) in enumerate(tqdm(trainloader, ncols=80,\n", + " file=sys.stdout, desc=\"Training\", leave=False)):\n", + " inputs = inputs.to(device)\n", + " targets = targets.to(device)\n", + " \n", + " optimizer.zero_grad()\n", + " \n", + " outputs = model(inputs)\n", + " loss = criterion(outputs, targets)\n", + " \n", + " loss.backward()\n", + " optimizer.step()\n", + " #---------------------------\n", + " \n", + "def test(model, testloader, device='cpu'):\n", + " num_correct = 0\n", + " num_samples = 0\n", + " \n", + " #-to-be-done-by-student-----\n", + " model.eval()\n", + " \n", + " for _, (inputs, targets) in enumerate(tqdm(testloader, ncols=80,\n", + " file=sys.stdout, desc=\"Testing\", leave=False)):\n", + " inputs = inputs.to(device)\n", + " targets = targets.to(device)\n", + " \n", + " outputs = model(inputs)\n", + " indexes = outputs.argmax(dim=1)\n", + " \n", + " num_correct += (indexes == targets).float().sum()\n", + " num_samples += inputs.shape[0]\n", + " #---------------------------\n", + " \n", + " return num_correct/num_samples\n", + "\n", + "last_trained_round = None\n", + "starting_round = None\n", + "\n", + "while True:\n", + " print(\"Starting round\")\n", + " \n", + " #-to-be-done-by-student-----\n", + " clientlib.wait_for_next_round(SERVER)\n", + " model, model_metadata = clientlib.get_model_and_notify_client_started(SERVER, CLIENT_ID)\n", + " model = model.to(device)\n", + " if starting_round is None:\n", + " starting_round = model_metadata[\"round\"]\n", + " #---------------------------\n", + "\n", + " print(f'downloaded model -> train (round {model_metadata[\"round\"]})')\n", + "\n", + " start = time.time()\n", + " \n", + " #-to-be-done-by-student-----\n", + " optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\n", + " criterion = torch.nn.CrossEntropyLoss()\n", + " train(model, optimizer, criterion, train_loader, device)\n", + " #---------------------------\n", + " \n", + " end = time.time()\n", + " print(f'training took {end-start:.1f}s')\n", + "\n", + " print('upload updated model')\n", + " \n", + " #-to-be-done-by-student-----\n", + " clientlib.upload_updated_model(SERVER, CLIENT_ID, model, model_metadata) \n", + " #---------------------------\n", + "\n", + " last_trained_round = model_metadata['round']\n", + " \n", + " #we measure the accuracy after 10 rounds\n", + " if model_metadata['round'] - starting_round == 10:\n", + " accuracy = test(model, test_loader, device=device)\n", + " print(f'Accuracy: ({accuracy:.2f})')\n", + " break" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "addb1a3f-0dca-4fd4-bfed-4ce8c91f9d99", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/exercises/1-federated_learning/__pycache__/clientlib.cpython-36.pyc b/exercises/1-federated_learning/__pycache__/clientlib.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..94fb1657bc5795e546b95b6779d060b33c0aa338 Binary files /dev/null and b/exercises/1-federated_learning/__pycache__/clientlib.cpython-36.pyc differ diff --git a/exercises/1-federated_learning/__pycache__/device_data.cpython-36.pyc b/exercises/1-federated_learning/__pycache__/device_data.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..53440f2d034116c5f75cf61cd3ae7e86fe90ee38 Binary files /dev/null and b/exercises/1-federated_learning/__pycache__/device_data.cpython-36.pyc differ diff --git a/exercises/1-federated_learning/exercise_10.ipynb b/exercises/1-federated_learning/exercise_10.ipynb index af790cae72bf976063f61d01f36b5c8c3ee10edb..490f0d328c3123935740ba929bf0b01690370c29 100644 --- a/exercises/1-federated_learning/exercise_10.ipynb +++ b/exercises/1-federated_learning/exercise_10.ipynb @@ -40,21 +40,31 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "id": "a3535eb2-c3e5-4e88-87c6-3f2bd44ff281", "metadata": {}, "outputs": [], "source": [ - "TOTAL_CLIENTS = 4 # number of participants in the lab\n", - "CLIENT_ID = 0 # between 0 and TOTAL_CLIENTS-1" + "TOTAL_CLIENTS = 11 # number of participants in the lab\n", + "CLIENT_ID = 4 # between 0 and TOTAL_CLIENTS-1" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "id": "76aa6d0f-8b95-4763-b001-2babbba0bcc0", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Files already downloaded and verified\n", + "Files already downloaded and verified\n", + "4546\n" + ] + } + ], "source": [ "import torch\n", "import device_data\n", @@ -62,7 +72,9 @@ "training_dataset = device_data.get_client_training_data(CLIENT_ID, TOTAL_CLIENTS)\n", "train_loader = torch.utils.data.DataLoader(training_dataset, batch_size=16)\n", "test_dataset = device_data.get_test_data()\n", - "test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=16)" + "test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=16)\n", + "\n", + "print(len(training_dataset))" ] }, { @@ -84,12 +96,29 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "id": "ebfe3586-4082-4a70-b387-a9546c673f43", "metadata": { "scrolled": true }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 1/10: accuracy (0.39) \n", + "Epoch 2/10: accuracy (0.44) \n", + "Epoch 3/10: accuracy (0.47) \n", + "Epoch 4/10: accuracy (0.48) \n", + "Epoch 5/10: accuracy (0.49) \n", + "Epoch 6/10: accuracy (0.49) \n", + "Epoch 7/10: accuracy (0.49) \n", + "Epoch 8/10: accuracy (0.51) \n", + "Epoch 9/10: accuracy (0.51) \n", + "Epoch 10/10: accuracy (0.49) \n" + ] + } + ], "source": [ "# this reaches <70% with 4 clients\n", "\n", @@ -102,21 +131,31 @@ "\n", "#create a model instance and define loss and optimizer criterion\n", "#-to-be-done-by-student-------------\n", - "\n", - "\n", + "model = CifarNet().to(device)\n", + "optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\n", + "criterion = torch.nn.CrossEntropyLoss()\n", "#-----------------------------------\n", "\n", "def train(model, optimizer, criterion, trainloader, device='cpu'):\n", + " \n", " #-to-be-done-by-student---------\n", - " \n", + " model.train()\n", " #-------------------------------\n", + " \n", " for _, (inputs, targets) in enumerate(tqdm(trainloader, ncols=80,\n", " file=sys.stdout, desc=\"Training\", leave=False)):\n", " \n", " #-to-be-done-by-student----\n", - " \n", - " \n", - " \n", + " inputs = inputs.to(device)\n", + " targets = targets.to(device)\n", + " \n", + " optimizer.zero_grad()\n", + " \n", + " outputs = model(inputs)\n", + " loss = criterion(outputs, targets)\n", + " \n", + " loss.backward()\n", + " optimizer.step()\n", " #--------------------------\n", "\n", "def test(model, testloader, device='cpu'):\n", @@ -124,15 +163,20 @@ " num_samples = 0\n", " \n", " #-to-be-done-by-student---------\n", - " \n", - "\n", + " model.eval()\n", " #-------------------------------\n", + " \n", " for _, (inputs, targets) in enumerate(tqdm(testloader, ncols=80,\n", " file=sys.stdout, desc=\"Testing\", leave=False)):\n", " #-to-be-done-by-student----\n", - " \n", - " \n", - " \n", + " inputs = inputs.to(device)\n", + " targets = targets.to(device)\n", + " \n", + " outputs = model(inputs)\n", + " indexes = outputs.argmax(dim=1)\n", + " \n", + " num_correct += (indexes == targets).float().sum()\n", + " num_samples += inputs.shape[0]\n", " #--------------------------\n", " \n", " return num_correct / num_samples\n", @@ -168,7 +212,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.10" + "version": "3.6.9" } }, "nbformat": 4, diff --git a/exercises/1-federated_learning/exercise_11.ipynb b/exercises/1-federated_learning/exercise_11.ipynb index e3859e3c013c74acbfbdd4e6d1986f68529b5433..ec4dbef7801061df8ccca6558b33b542d5746e8a 100644 --- a/exercises/1-federated_learning/exercise_11.ipynb +++ b/exercises/1-federated_learning/exercise_11.ipynb @@ -40,21 +40,30 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "id": "5e98b6e3-c7bd-44bb-ad84-55f41f064c10", "metadata": {}, "outputs": [], "source": [ - "TOTAL_CLIENTS = 4 # number of participants in the lab\n", - "CLIENT_ID = 0 # between 0 and TOTAL_CLIENTS-1" + "TOTAL_CLIENTS = 11 # number of participants in the lab\n", + "CLIENT_ID = 4 # between 0 and TOTAL_CLIENTS-1" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "id": "0d64fc72-8577-4c5f-996e-54f3c9ad9d81", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Files already downloaded and verified\n", + "Files already downloaded and verified\n" + ] + } + ], "source": [ "import torch\n", "import device_data\n", @@ -67,10 +76,69 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "id": "35692a25-7929-4937-8469-11ab40fae52d", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Starting round\n", + "downloaded model -> train (round 79)\n", + "training took 10.1s \n", + "upload updated model\n", + "Starting round\n", + "downloaded model -> train (round 80)\n", + "training took 10.1s \n", + "upload updated model\n", + "Starting round\n" + ] + }, + { + "ename": "ConnectionError", + "evalue": "HTTPConnectionPool(host='federated-learning.in8.itec.kit.edu', port=80): Max retries exceeded with url: /api/get_model_metadata (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f35bf7a20>: Failed to establish a new connection: [Errno 111] Connection refused',))", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mConnectionRefusedError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/urllib3/connection.py\u001b[0m in \u001b[0;36m_new_conn\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 174\u001b[0m conn = connection.create_connection(\n\u001b[0;32m--> 175\u001b[0;31m \u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_dns_host\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mport\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mextra_kw\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 176\u001b[0m )\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/urllib3/util/connection.py\u001b[0m in \u001b[0;36mcreate_connection\u001b[0;34m(address, timeout, source_address, socket_options)\u001b[0m\n\u001b[1;32m 94\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0merr\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 95\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0merr\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 96\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/urllib3/util/connection.py\u001b[0m in \u001b[0;36mcreate_connection\u001b[0;34m(address, timeout, source_address, socket_options)\u001b[0m\n\u001b[1;32m 84\u001b[0m \u001b[0msock\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbind\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msource_address\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 85\u001b[0;31m \u001b[0msock\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mconnect\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msa\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 86\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0msock\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mConnectionRefusedError\u001b[0m: [Errno 111] Connection refused", + "\nDuring handling of the above exception, another exception occurred:\n", + "\u001b[0;31mNewConnectionError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/urllib3/connectionpool.py\u001b[0m in \u001b[0;36murlopen\u001b[0;34m(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw)\u001b[0m\n\u001b[1;32m 709\u001b[0m \u001b[0mheaders\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mheaders\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 710\u001b[0;31m \u001b[0mchunked\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mchunked\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 711\u001b[0m )\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/urllib3/connectionpool.py\u001b[0m in \u001b[0;36m_make_request\u001b[0;34m(self, conn, method, url, timeout, chunked, **httplib_request_kw)\u001b[0m\n\u001b[1;32m 397\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 398\u001b[0;31m \u001b[0mconn\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrequest\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmethod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0murl\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mhttplib_request_kw\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 399\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/urllib3/connection.py\u001b[0m in \u001b[0;36mrequest\u001b[0;34m(self, method, url, body, headers)\u001b[0m\n\u001b[1;32m 238\u001b[0m \u001b[0mheaders\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"User-Agent\"\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_get_default_user_agent\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 239\u001b[0;31m \u001b[0msuper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mHTTPConnection\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrequest\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmethod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0murl\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbody\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mbody\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mheaders\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mheaders\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 240\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/lib/python3.6/http/client.py\u001b[0m in \u001b[0;36mrequest\u001b[0;34m(self, method, url, body, headers, encode_chunked)\u001b[0m\n\u001b[1;32m 1280\u001b[0m \u001b[0;34m\"\"\"Send a complete request to the server.\"\"\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1281\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_send_request\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmethod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0murl\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbody\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mheaders\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mencode_chunked\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1282\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/lib/python3.6/http/client.py\u001b[0m in \u001b[0;36m_send_request\u001b[0;34m(self, method, url, body, headers, encode_chunked)\u001b[0m\n\u001b[1;32m 1326\u001b[0m \u001b[0mbody\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_encode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbody\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'body'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1327\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mendheaders\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbody\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mencode_chunked\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mencode_chunked\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1328\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/lib/python3.6/http/client.py\u001b[0m in \u001b[0;36mendheaders\u001b[0;34m(self, message_body, encode_chunked)\u001b[0m\n\u001b[1;32m 1275\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mCannotSendHeader\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1276\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_send_output\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmessage_body\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mencode_chunked\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mencode_chunked\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1277\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/lib/python3.6/http/client.py\u001b[0m in \u001b[0;36m_send_output\u001b[0;34m(self, message_body, encode_chunked)\u001b[0m\n\u001b[1;32m 1041\u001b[0m \u001b[0;32mdel\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_buffer\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1042\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1043\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/lib/python3.6/http/client.py\u001b[0m in \u001b[0;36msend\u001b[0;34m(self, data)\u001b[0m\n\u001b[1;32m 979\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mauto_open\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 980\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mconnect\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 981\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/urllib3/connection.py\u001b[0m in \u001b[0;36mconnect\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 204\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mconnect\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 205\u001b[0;31m \u001b[0mconn\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_new_conn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 206\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_prepare_conn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mconn\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/urllib3/connection.py\u001b[0m in \u001b[0;36m_new_conn\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 186\u001b[0m raise NewConnectionError(\n\u001b[0;32m--> 187\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"Failed to establish a new connection: %s\"\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0me\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 188\u001b[0m )\n", + "\u001b[0;31mNewConnectionError\u001b[0m: <urllib3.connection.HTTPConnection object at 0x7f35bf7a20>: Failed to establish a new connection: [Errno 111] Connection refused", + "\nDuring handling of the above exception, another exception occurred:\n", + "\u001b[0;31mMaxRetryError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/requests/adapters.py\u001b[0m in \u001b[0;36msend\u001b[0;34m(self, request, stream, timeout, verify, cert, proxies)\u001b[0m\n\u001b[1;32m 449\u001b[0m \u001b[0mretries\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmax_retries\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 450\u001b[0;31m \u001b[0mtimeout\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 451\u001b[0m )\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/urllib3/connectionpool.py\u001b[0m in \u001b[0;36murlopen\u001b[0;34m(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw)\u001b[0m\n\u001b[1;32m 785\u001b[0m retries = retries.increment(\n\u001b[0;32m--> 786\u001b[0;31m \u001b[0mmethod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0murl\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0merror\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0me\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_pool\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_stacktrace\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0msys\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexc_info\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 787\u001b[0m )\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/urllib3/util/retry.py\u001b[0m in \u001b[0;36mincrement\u001b[0;34m(self, method, url, response, error, _pool, _stacktrace)\u001b[0m\n\u001b[1;32m 591\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mnew_retry\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mis_exhausted\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 592\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mMaxRetryError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0m_pool\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0murl\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0merror\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0mResponseError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcause\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 593\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mMaxRetryError\u001b[0m: HTTPConnectionPool(host='federated-learning.in8.itec.kit.edu', port=80): Max retries exceeded with url: /api/get_model_metadata (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f35bf7a20>: Failed to establish a new connection: [Errno 111] Connection refused',))", + "\nDuring handling of the above exception, another exception occurred:\n", + "\u001b[0;31mConnectionError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m<ipython-input-7-f7910e17da6c>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 59\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 60\u001b[0m \u001b[0;31m#-to-be-done-by-student-----\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 61\u001b[0;31m \u001b[0mclientlib\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwait_for_next_round\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mSERVER\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 62\u001b[0m \u001b[0mmodel\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmodel_metadata\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mclientlib\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_model_and_notify_client_started\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mSERVER\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mCLIENT_ID\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 63\u001b[0m \u001b[0mmodel\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmodel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mto\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdevice\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/embedded-ml-lab-students-ss24/exercises/1-federated_learning/clientlib.py\u001b[0m in \u001b[0;36mwait_for_next_round\u001b[0;34m(server, last_trained_round, join_late_by_max)\u001b[0m\n\u001b[1;32m 24\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mwait_for_next_round\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mserver\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlast_trained_round\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mjoin_late_by_max\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m10\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 25\u001b[0m \u001b[0;32mwhile\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 26\u001b[0;31m \u001b[0mmetadata\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_get_model_metadata\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mserver\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 27\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mmetadata\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'round_age'\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m<\u001b[0m \u001b[0mjoin_late_by_max\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 28\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mlast_trained_round\u001b[0m \u001b[0;34m!=\u001b[0m \u001b[0mmetadata\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'round'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/embedded-ml-lab-students-ss24/exercises/1-federated_learning/clientlib.py\u001b[0m in \u001b[0;36m_get_model_metadata\u001b[0;34m(server)\u001b[0m\n\u001b[1;32m 17\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_get_model_metadata\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mserver\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0murl\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34mf'http://{server}/api/get_model_metadata'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 19\u001b[0;31m \u001b[0mr\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mrequests\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0murl\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 20\u001b[0m \u001b[0;32massert\u001b[0m \u001b[0mr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mok\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtext\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 21\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mpickle\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mloads\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcontent\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'model_metadata'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/requests/api.py\u001b[0m in \u001b[0;36mget\u001b[0;34m(url, params, **kwargs)\u001b[0m\n\u001b[1;32m 73\u001b[0m \"\"\"\n\u001b[1;32m 74\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 75\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mrequest\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'get'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0murl\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mparams\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mparams\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 76\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 77\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/requests/api.py\u001b[0m in \u001b[0;36mrequest\u001b[0;34m(method, url, **kwargs)\u001b[0m\n\u001b[1;32m 59\u001b[0m \u001b[0;31m# cases, and look like a memory leak in others.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 60\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0msessions\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mSession\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0msession\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 61\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0msession\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrequest\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmethod\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mmethod\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0murl\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0murl\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 62\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 63\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/requests/sessions.py\u001b[0m in \u001b[0;36mrequest\u001b[0;34m(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)\u001b[0m\n\u001b[1;32m 527\u001b[0m }\n\u001b[1;32m 528\u001b[0m \u001b[0msend_kwargs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mupdate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msettings\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 529\u001b[0;31m \u001b[0mresp\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mprep\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0msend_kwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 530\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 531\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mresp\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/requests/sessions.py\u001b[0m in \u001b[0;36msend\u001b[0;34m(self, request, **kwargs)\u001b[0m\n\u001b[1;32m 643\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 644\u001b[0m \u001b[0;31m# Send the request\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 645\u001b[0;31m \u001b[0mr\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0madapter\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrequest\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 646\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 647\u001b[0m \u001b[0;31m# Total elapsed time of the request (approximately)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/requests/adapters.py\u001b[0m in \u001b[0;36msend\u001b[0;34m(self, request, stream, timeout, verify, cert, proxies)\u001b[0m\n\u001b[1;32m 517\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mSSLError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0me\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrequest\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mrequest\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 518\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 519\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mConnectionError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0me\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrequest\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mrequest\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 520\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 521\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mClosedPoolError\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mConnectionError\u001b[0m: HTTPConnectionPool(host='federated-learning.in8.itec.kit.edu', port=80): Max retries exceeded with url: /api/get_model_metadata (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f35bf7a20>: Failed to establish a new connection: [Errno 111] Connection refused',))" + ] + } + ], "source": [ "import clientlib\n", "SERVER = 'federated-learning.in8.itec.kit.edu:80'\n", @@ -86,8 +154,22 @@ "device = 'cuda'\n", "\n", "def train(model, optimizer, criterion, trainloader, device='cpu'):\n", + " \n", " #-to-be-done-by-student-----\n", - " \n", + " model.train()\n", + " \n", + " for _, (inputs, targets) in enumerate(tqdm(trainloader, ncols=80,\n", + " file=sys.stdout, desc=\"Training\", leave=False)):\n", + " inputs = inputs.to(device)\n", + " targets = targets.to(device)\n", + " \n", + " optimizer.zero_grad()\n", + " \n", + " outputs = model(inputs)\n", + " loss = criterion(outputs, targets)\n", + " \n", + " loss.backward()\n", + " optimizer.step()\n", " #---------------------------\n", " \n", "def test(model, testloader, device='cpu'):\n", @@ -95,41 +177,71 @@ " num_samples = 0\n", " \n", " #-to-be-done-by-student-----\n", - " \n", + " model.eval()\n", + " \n", + " for _, (inputs, targets) in enumerate(tqdm(testloader, ncols=80,\n", + " file=sys.stdout, desc=\"Testing\", leave=False)):\n", + " inputs = inputs.to(device)\n", + " targets = targets.to(device)\n", + " \n", + " outputs = model(inputs)\n", + " indexes = outputs.argmax(dim=1)\n", + " \n", + " num_correct += (indexes == targets).float().sum()\n", + " num_samples += inputs.shape[0]\n", " #---------------------------\n", + " \n", " return num_correct/num_samples\n", "\n", "last_trained_round = None\n", + "starting_round = None\n", "\n", "while True:\n", " print(\"Starting round\")\n", " \n", " #-to-be-done-by-student-----\n", - "\n", + " clientlib.wait_for_next_round(SERVER)\n", + " model, model_metadata = clientlib.get_model_and_notify_client_started(SERVER, CLIENT_ID)\n", + " model = model.to(device)\n", + " if starting_round is None:\n", + " starting_round = model_metadata[\"round\"]\n", " #---------------------------\n", "\n", " print(f'downloaded model -> train (round {model_metadata[\"round\"]})')\n", "\n", " start = time.time()\n", + " \n", " #-to-be-done-by-student-----\n", - "\n", + " optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\n", + " criterion = torch.nn.CrossEntropyLoss()\n", + " train(model, optimizer, criterion, train_loader, device)\n", " #---------------------------\n", + " \n", " end = time.time()\n", " print(f'training took {end-start:.1f}s')\n", "\n", " print('upload updated model')\n", + " \n", " #-to-be-done-by-student-----\n", - "\n", + " clientlib.upload_updated_model(SERVER, CLIENT_ID, model, model_metadata) \n", " #---------------------------\n", "\n", " last_trained_round = model_metadata['round']\n", " \n", " #we measure the accuracy after 10 rounds\n", - " if model_metadata['round'] == 10:\n", + " if model_metadata['round'] - starting_round == 10:\n", " accuracy = test(model, test_loader, device=device)\n", " print(f'Accuracy: ({accuracy:.2f})')\n", " break" ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "addb1a3f-0dca-4fd4-bfed-4ce8c91f9d99", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -148,7 +260,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.10" + "version": "3.6.9" } }, "nbformat": 4, diff --git a/exercises/1-federated_learning/models/__pycache__/__init__.cpython-36.pyc b/exercises/1-federated_learning/models/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..46da6f3ec7321fb41e867449070d82e5b9a10280 Binary files /dev/null and b/exercises/1-federated_learning/models/__pycache__/__init__.cpython-36.pyc differ diff --git a/exercises/1-federated_learning/models/__pycache__/cifarnet.cpython-36.pyc b/exercises/1-federated_learning/models/__pycache__/cifarnet.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b5c8d0f38d8b04d9d6fce686572a635e6cb6ad50 Binary files /dev/null and b/exercises/1-federated_learning/models/__pycache__/cifarnet.cpython-36.pyc differ