From 1656eb6e24675b07906f4f8bcd7716c5e6c9a736 Mon Sep 17 00:00:00 2001 From: Shauvik RC Date: Sat, 2 Mar 2024 13:34:48 -0800 Subject: [PATCH 01/22] Fixing broken links to point to github (#54) --- benchmarks/README.md | 2 +- ...troduction to Federated Learning with CIFAR10.ipynb | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/benchmarks/README.md b/benchmarks/README.md index 02aa242..611b612 100644 --- a/benchmarks/README.md +++ b/benchmarks/README.md @@ -53,7 +53,7 @@ There are multiple official benchmarks for `pfl` to simulate various scenarios, ## Run distributed simulations Each benchmark can run in distributed mode with multiple cores, GPUs and machines. -See the [distributed simulation guide](https://pages.github.apple.com/apple/pfl-research/tutorials/simulation_distributed.html) on how it works. +See the [distributed simulation guide](https://apple.github.io/pfl-research/guides/simulation_distributed.html) on how it works. In summary, to quickly get started running distributed simulations: 1. Install [Horovod](https://horovod.readthedocs.io/en/stable/install_include.html). We have a helper script [here](https://github.com/apple/pfl-research/blob/main/build_scripts/install_horovod.sh). 2. Invoke your Python script with the `horovodrun` command. E.g. to run the same CIFAR10 training as described above in the quickstart, but train with 2 processes on the same machine, the command will look like this: diff --git a/tutorials/Introduction to Federated Learning with CIFAR10.ipynb b/tutorials/Introduction to Federated Learning with CIFAR10.ipynb index 7243f55..655d464 100644 --- a/tutorials/Introduction to Federated Learning with CIFAR10.ipynb +++ b/tutorials/Introduction to Federated Learning with CIFAR10.ipynb @@ -156,7 +156,7 @@ "source": [ "As displayed above, the images are of dimensions `32x32` with `3` color channels and the labels are one-hot vectors `[0-9]`. Also, you can see that we exclude all but 2 classes, Airplane (0) and Bird (2), to make things simple for this tutorial.\n", "\n", - "As the data is not inherently split into real users, we need to use [ArtificialFederatedDataset](https://pages.github.apple.com/apple/pfl-research/reference/data.html#pfl.data.federated_dataset.ArtificialFederatedDataset) to sample datapoints to create artificial user datasets for federated learning, which in turn requires a function for sampling the length of a user dataset and the actual datapoints of this dataset.\n", + "As the data is not inherently split into real users, we need to use [ArtificialFederatedDataset](https://apple.github.io/pfl-research/reference/data.html#pfl.data.federated_dataset.ArtificialFederatedDataset) to sample datapoints to create artificial user datasets for federated learning, which in turn requires a function for sampling the length of a user dataset and the actual datapoints of this dataset.\n", "\n", "Firstly, we define a function which samples the length of a dataset from a Poisson distribution with mean 5:" ] @@ -360,7 +360,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "To train a model using `pfl`, a [Model](https://pages.github.apple.com/apple/pfl-research/reference/model.html#models) object must be instantiated for the Deep Learning framework in which the model was defined. A `pfl` Model acts as an adapter between the model of the Deep Learning framework and `pfl`. We use Keras with TensorFlow for this example.\n", + "To train a model using `pfl`, a [Model](https://apple.github.io/pfl-research/reference/model.html#models) object must be instantiated for the Deep Learning framework in which the model was defined. A `pfl` Model acts as an adapter between the model of the Deep Learning framework and `pfl`. We use Keras with TensorFlow for this example.\n", "\n", "The central optimizer is an input parameter to the model object. This optimizer is used when applying the aggregated model update to the central model." ] @@ -401,9 +401,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "`Backend` is a component in `pfl` used to collect and average statistics from user devices. [SimulatedBackend](https://pages.github.apple.com/apple/pfl-research/reference/aggregate.html#pfl.aggregate.SimulatedBackend) provides simulation. For larger datasets or models, it also [supports distributed simulations](https://pages.github.apple.com/apple/pfl-research/tutorials/simulation_distributed.html) with multiple processes, GPUs and machines.\n", + "`Backend` is a component in `pfl` used to collect and average statistics from user devices. [SimulatedBackend](https://apple.github.io/pfl-research/reference/aggregate.html#pfl.aggregate.SimulatedBackend) provides simulation. For larger datasets or models, it also [supports distributed simulations](https://apple.github.io/pfl-research/tutorials/simulation_distributed.html) with multiple processes, GPUs and machines.\n", "\n", - "`pfl` provides various privacy mechanisms in [pfl.privacy](https://pages.github.apple.com/apple/pfl-research/reference/privacy.html#module-privacy).\n", + "`pfl` provides various privacy mechanisms in [pfl.privacy](https://apple.github.io/pfl-research/reference/privacy.html#module-privacy).\n", "These mechanisms are used to guarantee local and/or central differential privacy and are parameterized by `SimulatedBackend` in simulations.\n", "\n", "Below, we initialize `SimulatedBackend` with Gaussian Moments Accountant as the central differential privacy mechanism, which provides the minimum privacy guarantee required by most use-cases." @@ -445,7 +445,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The main component of a `pfl` modeling setup is the algorithm. In this tutorial, we will be using the [Federated Averaging](https://arxiv.org/pdf/1602.05629.pdf) algorithm. `pfl` implements Federated Averaging using the class [FederatedAveraging](https://pages.github.apple.com/apple/pfl-research/reference/algorithm.html#pfl.algorithm.federated_averaging.FederatedAveraging).\n", + "The main component of a `pfl` modeling setup is the algorithm. In this tutorial, we will be using the [Federated Averaging](https://arxiv.org/pdf/1602.05629.pdf) algorithm. `pfl` implements Federated Averaging using the class [FederatedAveraging](https://apple.github.io/pfl-research/reference/algorithm.html#pfl.algorithm.federated_averaging.FederatedAveraging).\n", "\n", "Everything is tied together in the `run` method of an algorithm. This method requires the model, backend, optional callbacks, as well as hyperparameters, which depends on the model and algorithm combination. In this case, training a neural network with federated averaging requires a `NNTrainHyperParams` and `NNAlgorithmParams`.\n", "\n", From b876fdac755d39f136e9dfabac21ccc86c8e5df3 Mon Sep 17 00:00:00 2001 From: ac554 <47990575+ac554@users.noreply.github.com> Date: Mon, 4 Mar 2024 16:30:32 -0800 Subject: [PATCH 02/22] remove broken link (#57) --- pfl/privacy/privacy_accountant.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pfl/privacy/privacy_accountant.py b/pfl/privacy/privacy_accountant.py index 368c440..54de581 100644 --- a/pfl/privacy/privacy_accountant.py +++ b/pfl/privacy/privacy_accountant.py @@ -105,7 +105,7 @@ class PLDPrivacyAccountant(PrivacyAccountant): """ Privacy Loss Distribution (PLD) privacy accountant, from dp-accounting package. - Code: https://github.com/google/differential-privacy/blob/main/python/dp_accounting/pld/pld_privacy_accountant.py # pylint: disable=line-too-long + The PLD algorithm is based on: “Tight on budget?: Tight bounds for r-fold approximate differential privacy.”, Meiser and Mohammadi, in CCS, pages 247-264, 2018, https://eprint.iacr.org/2017/1034.pdf From efc22f7989d863c5a827e808c125dc1468609b3f Mon Sep 17 00:00:00 2001 From: Rogier van Dalen Date: Tue, 5 Mar 2024 00:34:48 +0000 Subject: [PATCH 03/22] Rename EMMGMMHyperParams to EMGMMHyperParams (#55) --- pfl/algorithm/expectation_maximization_gmm.py | 6 +++--- tests/algorithm/test_expectation_maximization_gmm.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pfl/algorithm/expectation_maximization_gmm.py b/pfl/algorithm/expectation_maximization_gmm.py index f451229..d097156 100644 --- a/pfl/algorithm/expectation_maximization_gmm.py +++ b/pfl/algorithm/expectation_maximization_gmm.py @@ -18,7 +18,7 @@ @dataclass(frozen=True) -class EMMGMMHyperParams(AlgorithmHyperParams): +class EMGMMHyperParams(AlgorithmHyperParams): """ Parameters for EM GMM algorithms. @@ -113,7 +113,7 @@ def compute_new_num_components(iteration, num_iterations_since_last_mix_up, return compute_new_num_components -class ExpectationMaximizationGMM(FederatedAlgorithm[EMMGMMHyperParams, +class ExpectationMaximizationGMM(FederatedAlgorithm[EMGMMHyperParams, GMMHyperParams, GaussianMixtureModel, MappedVectorStatistics, @@ -132,7 +132,7 @@ def get_next_central_contexts( self, model: GaussianMixtureModel, iteration: int, - algorithm_params: EMMGMMHyperParams, + algorithm_params: EMGMMHyperParams, model_train_params: GMMHyperParams, model_eval_params: Optional[GMMHyperParams] = None, ) -> Tuple[Optional[Tuple[CentralContext, ...]], GaussianMixtureModel, diff --git a/tests/algorithm/test_expectation_maximization_gmm.py b/tests/algorithm/test_expectation_maximization_gmm.py index b4e546b..ed09964 100644 --- a/tests/algorithm/test_expectation_maximization_gmm.py +++ b/tests/algorithm/test_expectation_maximization_gmm.py @@ -6,7 +6,7 @@ from pfl.aggregate.base import Backend, get_total_weight_name from pfl.algorithm.expectation_maximization_gmm import ( - EMMGMMHyperParams, + EMGMMHyperParams, ExpectationMaximizationGMM, make_compute_new_num_components, ) @@ -144,7 +144,7 @@ def test_run(self, tmpdir, numpy_ops, mock_gmm_backend, max_num_components=64, step_components=2) - algorithm_params = EMMGMMHyperParams( + algorithm_params = EMGMMHyperParams( central_num_iterations=central_num_iterations, evaluation_frequency=1, val_cohort_size=fixed_val_cohort_size, From 22a2a6b68a3c71f52d01d7fb90e78e1a8c119121 Mon Sep 17 00:00:00 2001 From: fgranqvist Date: Tue, 12 Mar 2024 00:14:44 +0100 Subject: [PATCH 04/22] Link from readme to docs, docs to readme (#58) --- README.md | 4 ++++ docs/source/index.rst | 2 ++ 2 files changed, 6 insertions(+) diff --git a/README.md b/README.md index 6d47ff5..ee97d37 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # `pfl`: Python framework for Private Federated Learning simulations +**Documentation website:** https://apple.github.io/pfl-research + `pfl` is a Python framework developed at Apple to empower researchers to run efficient simulations with privacy-preserving federated learning (FL) and disseminate the results of their research in FL. We are a team comprising engineering and research expertise, and we encourage researchers to publish their papers, with this code, with confidence. The framework is `not` intended to be used for third-party FL deployments but the results of the simulations can be tremendously useful in actual FL deployments. @@ -32,6 +34,8 @@ pip install 'pfl[tf,pytorch,trees]' To try out `pfl` immediately without installation, we provide several colab notebooks for learning the different components in `pfl` hands-on. `` +Also available as Jupyter notebooks [here](https://github.com/apple/pfl-research/tree/develop/tutorials). + ## Getting started - benchmarks `pfl` aims to streamline the benchmarking process of testing hypotheses in the Federated Learning paradigm. The official benchmarks are available in the [benchmarks](./benchmarks) directory, using a variety of realistic dataset-model combinations with and without differential privacy (yes, we do also have CIFAR10). diff --git a/docs/source/index.rst b/docs/source/index.rst index 931099b..18e1a71 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -6,6 +6,8 @@ pfl: Python framework for Private Federated Learning simulations ================================================================ +**Github repo available at** https://github.com/apple/pfl-research. + ``pfl`` is a Python framework developed at Apple to enable researchers to `run efficient simulations with privacy-preserving federated learning (FL)` and `disseminate the results of their research in FL`. The framework is `not` intended to be used for third-party FL deployments but the results of the simulations can be tremendously useful in actual FL deployments. We hope that ``pfl`` will promote open research in FL and its effective dissemination. From 2c9d089ac8b0c8b82e6c98e49a5d0d7b083322e0 Mon Sep 17 00:00:00 2001 From: fgranqvist Date: Wed, 13 Mar 2024 22:48:11 +0000 Subject: [PATCH 05/22] license, CI, py version badges (#59) --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index ee97d37..21f56c7 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ # `pfl`: Python framework for Private Federated Learning simulations +[![GitHub License](https://img.shields.io/github/license/apple/pfl-research)](https://github.com/apple/pfl-research/blob/main/LICENSE) +[![CircleCI](https://dl.circleci.com/status-badge/img/gh/apple/pfl-research/tree/main.svg?style=shield)](https://dl.circleci.com/status-badge/redirect/gh/apple/pfl-research/tree/main) +[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/pfl)](https://github.com/apple/pfl-research/blob/main/pyproject.toml#L18) + **Documentation website:** https://apple.github.io/pfl-research `pfl` is a Python framework developed at Apple to empower researchers to run efficient simulations with privacy-preserving federated learning (FL) and disseminate the results of their research in FL. We are a team comprising engineering and research expertise, and we encourage researchers to publish their papers, with this code, with confidence. From 2d79b66ead81333b88b9b00f5e5e3e2db9f7baa1 Mon Sep 17 00:00:00 2001 From: fgranqvist Date: Fri, 15 Mar 2024 00:05:58 +0000 Subject: [PATCH 06/22] run ci on develop merge (#60) --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1a90f60..51034f2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -210,7 +210,7 @@ workflows: matches: # Only on branches approved by Apple CircleCI policy: # https://app.circleci.com/settings/organization/github/apple/policies/baseline_apple - pattern: "^main|gh-readonly-queue/main/pr-\\d+-[0-9a-f]{40}.*$" + pattern: "^main$|^develop$|gh-readonly-queue/main/pr-\\d+-[0-9a-f]{40}.*$" value: << pipeline.git.branch >> jobs: - code-quality From 93f938f5d55a2a3f2bccb7157f4dd8dc4f2b86b7 Mon Sep 17 00:00:00 2001 From: fgranqvist Date: Thu, 28 Mar 2024 09:01:47 +0100 Subject: [PATCH 07/22] correctly trigger develop ci (#61) --- .circleci/config.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 51034f2..5902dd0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -207,11 +207,13 @@ jobs: workflows: build_and_test: when: - matches: - # Only on branches approved by Apple CircleCI policy: - # https://app.circleci.com/settings/organization/github/apple/policies/baseline_apple - pattern: "^main$|^develop$|gh-readonly-queue/main/pr-\\d+-[0-9a-f]{40}.*$" - value: << pipeline.git.branch >> + or: + - matches: + # Only on branches approved by Apple CircleCI policy: + # https://app.circleci.com/settings/organization/github/apple/policies/baseline_apple + pattern: "^main|gh-readonly-queue/main/pr-\\d+-[0-9a-f]{40}.*$" + value: << pipeline.git.branch >> + - equal: [ develop, << pipeline.git.branch >> ] jobs: - code-quality - build-documentation-wheel From 9be095ccbd371299392c1a3d2abe4e7438736d2a Mon Sep 17 00:00:00 2001 From: fgranqvist Date: Mon, 1 Apr 2024 01:25:14 +0200 Subject: [PATCH 08/22] set seeds for tf examples (#62) --- benchmarks/image_classification/tf/train.py | 3 +++ benchmarks/lm/tf/train.py | 3 +++ 2 files changed, 6 insertions(+) diff --git a/benchmarks/image_classification/tf/train.py b/benchmarks/image_classification/tf/train.py index 9d3da23..6c80ebd 100644 --- a/benchmarks/image_classification/tf/train.py +++ b/benchmarks/image_classification/tf/train.py @@ -2,6 +2,7 @@ import argparse import logging import os +import random from uuid import uuid4 import numpy as np @@ -55,6 +56,8 @@ def main(): argument_parser = add_model_arguments(argument_parser) arguments = argument_parser.parse_args() + os.environ['PYTHONHASHSEED'] = str(arguments.seed) + random.seed(arguments.seed) tf.random.set_seed(arguments.seed) np.random.seed(arguments.seed) diff --git a/benchmarks/lm/tf/train.py b/benchmarks/lm/tf/train.py index 1456ffa..bbddaff 100644 --- a/benchmarks/lm/tf/train.py +++ b/benchmarks/lm/tf/train.py @@ -2,6 +2,7 @@ import argparse import logging import os +import random from uuid import uuid4 import numpy as np @@ -58,6 +59,8 @@ def main(): parser = add_weighting_arguments(parser) arguments = parser.parse_args() + os.environ['PYTHONHASHSEED'] = str(arguments.seed) + random.seed(arguments.seed) np.random.seed(arguments.seed) tf.random.set_seed(arguments.seed) From a55c301a4dc86b822f544d2f1f2e283e00253936 Mon Sep 17 00:00:00 2001 From: congzheng-song <90863343+congzheng-song@users.noreply.github.com> Date: Wed, 3 Apr 2024 02:12:12 -0700 Subject: [PATCH 09/22] Update LLM Benchmark Configs (#63) --- benchmarks/dataset/hugging_face/__init__.py | 40 ++++++++++++++--- benchmarks/dataset/hugging_face/alpaca.py | 10 ++--- benchmarks/dataset/hugging_face/oasst.py | 10 ++--- benchmarks/llm/README.md | 4 +- benchmarks/llm/argument_parsing.py | 15 ++++++- benchmarks/llm/configs/alpaca.yaml | 50 +++++++++++++++++++++ benchmarks/llm/configs/aya.yaml | 48 ++++++++++++++++++++ benchmarks/llm/configs/baseline.yaml | 38 ---------------- benchmarks/llm/configs/oasst.yaml | 48 ++++++++++++++++++++ benchmarks/llm/train.py | 15 ++++++- pfl/data/pytorch.py | 3 +- 11 files changed, 219 insertions(+), 62 deletions(-) create mode 100644 benchmarks/llm/configs/alpaca.yaml create mode 100644 benchmarks/llm/configs/aya.yaml delete mode 100644 benchmarks/llm/configs/baseline.yaml create mode 100644 benchmarks/llm/configs/oasst.yaml diff --git a/benchmarks/dataset/hugging_face/__init__.py b/benchmarks/dataset/hugging_face/__init__.py index c7616c7..4f1a4fb 100644 --- a/benchmarks/dataset/hugging_face/__init__.py +++ b/benchmarks/dataset/hugging_face/__init__.py @@ -1,23 +1,49 @@ # Copyright © 2023-2024 Apple Inc. -import logging -from typing import Dict, List, Union +from collections import namedtuple +from typing import Any, Callable, Dict, List, Union import torch IGNORE_INDEX = -100 -logger = logging.getLogger(__name__) + +IndexedData = namedtuple('IndexedData', ['data', 'index']) class GetItemDataset(torch.utils.data.Dataset): """ Wraps a dataset that has __getitem__. """ - def __init__(self, data: Union[Dict, List]): + def __init__(self, data: Union[Dict, List], return_index: bool = False): super().__init__() - self.data = data + self._data = data + self._return_index = return_index def __len__(self): - return len(self.data) + return len(self._data) def __getitem__(self, i): - return self.data[i] + if self._return_index: + # Return both data and index. The index can be used in the below + # `UserIDCollatorWrapper` to pass the `user_id` to + # `PyTorchFederatedDataset` + return IndexedData(data=self._data[i], index=i) + return self._data[i] + + +class UserIDCollatorWrapper: + """ + Wraps an existing collator to add user ID to the resulting collated data. + This is useful for `PyTorchFederatedDataset` which does not have `user_id` + by default. + """ + + def __init__(self, collator: Callable[[List], Dict[str, Any]]): + self._collator = collator + + def __call__(self, indexed_data: IndexedData) -> Dict[str, Any]: + assert isinstance(indexed_data, IndexedData), ( + "`UserIDCollatorWrapper` only supports `torch.utils.data.Dataset` " + "that returns `IndexedData`") + data = self._collator(indexed_data.data) + data["user_id"] = indexed_data.index + return data diff --git a/benchmarks/dataset/hugging_face/alpaca.py b/benchmarks/dataset/hugging_face/alpaca.py index 27d1365..1efecdd 100644 --- a/benchmarks/dataset/hugging_face/alpaca.py +++ b/benchmarks/dataset/hugging_face/alpaca.py @@ -15,10 +15,7 @@ from pfl.data.pytorch import PyTorchDataDataset, PyTorchFederatedDataset from pfl.data.sampling import get_user_sampler -from . import ( - IGNORE_INDEX, - GetItemDataset, -) +from . import IGNORE_INDEX, GetItemDataset, UserIDCollatorWrapper logger = logging.getLogger(__name__) @@ -134,11 +131,12 @@ def make_iid_federated_dataset(user_dataset: Dict[str, List[Dict]], """ Split the dataset into IID artificial users. """ user_sampler = get_user_sampler('random', list(user_dataset.keys())) user_id_to_weight = {k: len(v) for k, v in user_dataset.items()} - return PyTorchFederatedDataset(GetItemDataset(user_dataset), + collate_fn = UserIDCollatorWrapper(AlpacaDataCollator(tokenizer)) + return PyTorchFederatedDataset(GetItemDataset(user_dataset, True), user_sampler, user_id_to_weight=user_id_to_weight, batch_size=None, - collate_fn=AlpacaDataCollator(tokenizer), + collate_fn=collate_fn, **dataloader_kwargs) diff --git a/benchmarks/dataset/hugging_face/oasst.py b/benchmarks/dataset/hugging_face/oasst.py index 8169948..c513504 100644 --- a/benchmarks/dataset/hugging_face/oasst.py +++ b/benchmarks/dataset/hugging_face/oasst.py @@ -15,10 +15,7 @@ from pfl.data.pytorch import PyTorchDataDataset, PyTorchFederatedDataset from pfl.data.sampling import get_user_sampler -from . import ( - IGNORE_INDEX, - GetItemDataset, -) +from . import IGNORE_INDEX, GetItemDataset, UserIDCollatorWrapper logger = logging.getLogger(__name__) @@ -94,11 +91,12 @@ def make_federated_dataset(user_dataset: Dict[str, List[Dict]], """ user_sampler = get_user_sampler('random', list(user_dataset.keys())) user_id_to_weight = {k: len(v) for k, v in user_dataset.items()} - return PyTorchFederatedDataset(GetItemDataset(user_dataset), + collate_fn = UserIDCollatorWrapper(default_data_collator) + return PyTorchFederatedDataset(GetItemDataset(user_dataset, True), user_sampler, user_id_to_weight=user_id_to_weight, batch_size=None, - collate_fn=default_data_collator, + collate_fn=collate_fn, **dataloader_kwargs) diff --git a/benchmarks/llm/README.md b/benchmarks/llm/README.md index e9bf19a..b9ae583 100644 --- a/benchmarks/llm/README.md +++ b/benchmarks/llm/README.md @@ -21,10 +21,10 @@ dataset=alpaca LLM benchmark no DP: ``` -python -m llm.train --args_config llm/configs/{dataset}_baseline.yaml +python -m llm.train --args_config llm/configs/{dataset}.yaml ``` LLM benchmark Central DP: ``` -python -m llm.train --args_config llm/configs/{dataset}_baseline.yaml --central_privacy_mechanism gaussian_moments_accountant +python -m llm.train --args_config llm/configs/{dataset}.yaml --central_privacy_mechanism gaussian_moments_accountant ``` diff --git a/benchmarks/llm/argument_parsing.py b/benchmarks/llm/argument_parsing.py index 2e6c0e1..269c9b4 100644 --- a/benchmarks/llm/argument_parsing.py +++ b/benchmarks/llm/argument_parsing.py @@ -16,10 +16,15 @@ def parse_peft_config(args) -> Optional[PeftConfig]: if args.peft_type is None: return None assert args.peft_type == 'lora', "Currently only supports PEFT with LoRA." + target_modules = None + if args.lora_target_modules is not None: + target_modules = args.lora_target_modules.split(',') + return LoraConfig(task_type=args.peft_task_type, r=args.lora_r, lora_alpha=args.lora_alpha, - lora_dropout=args.lora_dropout) + lora_dropout=args.lora_dropout, + target_modules=target_modules) def add_peft_arguments(argument_parser): @@ -53,6 +58,14 @@ def add_peft_arguments(argument_parser): default=0.0, help='LoRA dropout.') + argument_parser.add_argument('--lora_target_modules', + type=str, + default=None, + help='Modules in the model to apply LoRA.' + 'Use comma to add multiple modules, e.g.' + '`query,key,value` applies LoRA on all ' + '`query`, `key` and `value` modules.') + return argument_parser diff --git a/benchmarks/llm/configs/alpaca.yaml b/benchmarks/llm/configs/alpaca.yaml new file mode 100644 index 0000000..ea98a43 --- /dev/null +++ b/benchmarks/llm/configs/alpaca.yaml @@ -0,0 +1,50 @@ +dataset: alpaca +mean_datapoints_per_user: 16 +datapoints_per_user_distribution: poisson + +# Model config +hugging_face_model_name_or_path: TinyLlama/TinyLlama-1.1B-intermediate-step-1195k-token-2.5T +model_max_length: 512 +use_fast_tokenizer: True +padding_side: right +amp_dtype: bfloat16 +model_dtype_same_as_amp: False +use_torch_compile: True + +# PEFT - LoRA +peft_type: lora +lora_r: 8 + +central_optimizer: adam +adaptivity_degree: 1.0e-4 +learning_rate: 0.01 +central_lr_scheduler: cosine +central_lr_num_warmup_iterations: 50 + +central_num_iterations: 1000 +evaluation_frequency: 10 +central_eval_batch_size: 8 +cohort_size: 100 +val_cohort_size: 0 +noise_cohort_size: 5000 + +local_batch_size: 4 +local_num_epochs: 1 +local_learning_rate: 0.01 +local_max_grad_norm: 1.0 + +central_privacy_mechanism: none # gaussian_moments_accountant +central_epsilon: 2.0 +central_delta: 1e-6 +central_privacy_clipping_bound: 0.1 +central_order: 2 +population: 1e6 + +use_tensorboard: False + +add_all_arguments: True +algorithm_name: fedavg +mu: 0.01 +scaffold_population: 2934 +adafedprox_metric_name: "Central val | loss" +adafedprox_adapt_frequency: 20 diff --git a/benchmarks/llm/configs/aya.yaml b/benchmarks/llm/configs/aya.yaml new file mode 100644 index 0000000..2eb9ad0 --- /dev/null +++ b/benchmarks/llm/configs/aya.yaml @@ -0,0 +1,48 @@ +dataset: aya + +# Model config +hugging_face_model_name_or_path: TinyLlama/TinyLlama-1.1B-intermediate-step-1195k-token-2.5T +model_max_length: 512 +use_fast_tokenizer: True +padding_side: right +amp_dtype: bfloat16 +model_dtype_same_as_amp: False +use_torch_compile: True + +# PEFT - LoRA +peft_type: lora +lora_r: 8 + +central_optimizer: adam +adaptivity_degree: 1.0e-4 +learning_rate: 0.01 +central_lr_scheduler: cosine +central_lr_num_warmup_iterations: 50 + +central_num_iterations: 1000 +evaluation_frequency: 10 +central_eval_batch_size: 12 +cohort_size: 100 +val_cohort_size: 0 +noise_cohort_size: 5000 + +local_batch_size: 4 +local_num_epochs: 1 +local_learning_rate: 0.1 +local_max_grad_norm: 1.0 + +central_privacy_mechanism: none # gaussian_moments_accountant +central_epsilon: 2.0 +central_delta: 1e-6 +central_privacy_clipping_bound: 0.1 +central_order: 2 +population: 1e6 + +use_tensorboard: False + +add_all_arguments: True +algorithm_name: fedavg +mu: 0.01 +scaffold_population: 4089 +adafedprox_metric_name: "Central val | loss" +adafedprox_adapt_frequency: 20 diff --git a/benchmarks/llm/configs/baseline.yaml b/benchmarks/llm/configs/baseline.yaml deleted file mode 100644 index 016f216..0000000 --- a/benchmarks/llm/configs/baseline.yaml +++ /dev/null @@ -1,38 +0,0 @@ -# Dataset config -#dataset: alpaca -#mean_datapoints_per_user: 16 -#datapoints_per_user_distribution: poisson - -# Model config -hugging_face_model_name_or_path: facebook/opt-1.3b -model_max_length: 512 -use_fast_tokenizer: True -padding_side: right -amp_dtype: bfloat16 -model_dtype_same_as_amp: True - -central_optimizer: adam -adaptivity_degree: 0.01 - -central_privacy_mechanism: none -central_epsilon: 2.0 -central_delta: 1e-6 -central_privacy_clipping_bound: 1.0 -central_order: 2 -population: 1e6 - -evaluation_frequency: 10 -learning_rate: 0.1 -cohort_size: 100 -val_cohort_size: 0 - -central_num_iterations: 2000 -local_batch_size: 4 -central_eval_batch_size: 8 -local_num_epochs: 1 -local_learning_rate: 0.1 - -use_tensorboard: False - -# PEFT -peft_type: lora diff --git a/benchmarks/llm/configs/oasst.yaml b/benchmarks/llm/configs/oasst.yaml new file mode 100644 index 0000000..b5c8201 --- /dev/null +++ b/benchmarks/llm/configs/oasst.yaml @@ -0,0 +1,48 @@ +dataset: oasst + +# Model config +hugging_face_model_name_or_path: TinyLlama/TinyLlama-1.1B-intermediate-step-1195k-token-2.5T +model_max_length: 512 +use_fast_tokenizer: True +padding_side: right +amp_dtype: bfloat16 +model_dtype_same_as_amp: False +use_torch_compile: True + +# PEFT - LoRA +peft_type: lora +lora_r: 8 + +central_optimizer: adam +adaptivity_degree: 1.0e-4 +learning_rate: 0.01 +central_lr_scheduler: cosine +central_lr_num_warmup_iterations: 50 + +central_num_iterations: 1000 +evaluation_frequency: 10 +central_eval_batch_size: 12 +cohort_size: 100 +val_cohort_size: 0 +noise_cohort_size: 5000 + +local_batch_size: 4 +local_num_epochs: 1 +local_learning_rate: 0.1 +local_max_grad_norm: 1.0 + +central_privacy_mechanism: none # gaussian_moments_accountant +central_epsilon: 2.0 +central_delta: 1e-6 +central_privacy_clipping_bound: 0.1 +central_order: 2 +population: 1e6 + +use_tensorboard: False + +add_all_arguments: True +algorithm_name: fedavg +mu: 0.01 +scaffold_population: 12870 +adafedprox_metric_name: "Central val | loss" +adafedprox_adapt_frequency: 20 diff --git a/benchmarks/llm/train.py b/benchmarks/llm/train.py index 70d1210..1e205fe 100644 --- a/benchmarks/llm/train.py +++ b/benchmarks/llm/train.py @@ -2,6 +2,8 @@ import argparse import logging +import os +from uuid import uuid4 import numpy as np import torch @@ -21,7 +23,7 @@ from llm.argument_parsing import add_llm_arguments, parse_central_lr_scheduler, parse_peft_config from pfl.aggregate.simulate import SimulatedBackend -from pfl.callback import AggregateMetricsToDisk, CentralEvaluationCallback, StopwatchCallback +from pfl.callback import AggregateMetricsToDisk, CentralEvaluationCallback, StopwatchCallback, WandbCallback from pfl.hyperparam import NNEvalHyperParams, NNTrainHyperParams from pfl.model.pytorch import PyTorchModel @@ -138,6 +140,17 @@ def main(): algorithm, algorithm_params, algorithm_callbacks = get_algorithm(arguments) callbacks.extend(algorithm_callbacks) + if arguments.wandb_project_id: + callbacks.append( + WandbCallback( + wandb_project_id=arguments.wandb_project_id, + wandb_experiment_name=os.environ.get('WANDB_TASK_ID', + str(uuid4())), + # List of dicts to one dict. + wandb_config=dict(vars(arguments)), + tags=os.environ.get('WANDB_TAGS', 'empty-tag').split(','), + group=os.environ.get('WANDB_GROUP', None))) + logger.info("Starts federated learning.") model = algorithm.run(algorithm_params=algorithm_params, backend=backend, diff --git a/pfl/data/pytorch.py b/pfl/data/pytorch.py index fb9f470..5533535 100644 --- a/pfl/data/pytorch.py +++ b/pfl/data/pytorch.py @@ -277,7 +277,8 @@ def _tensors_to_pfl_dataset(self, tensors): if isinstance(tensors, Dict): # The tensors are from a dictionary, no need to do extra processing # on the tensors as below. - return self._dataset_cls(tensors, **self._dataset_kwargs) + user_id = tensors.pop("user_id") if "user_id" in tensors else None + return self._dataset_cls(tensors, user_id, **self._dataset_kwargs) def process_tensor(tensor): assert tensor.shape[0] == 1, ( From 1dcd9a2b479094bcbce1d3696e26b8343519704c Mon Sep 17 00:00:00 2001 From: fgranqvist Date: Fri, 19 Apr 2024 16:59:32 +0200 Subject: [PATCH 10/22] fix error in error in GBDT config (#64) --- pfl/tree/federated_gbdt.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pfl/tree/federated_gbdt.py b/pfl/tree/federated_gbdt.py index dfa8d03..d9c394b 100644 --- a/pfl/tree/federated_gbdt.py +++ b/pfl/tree/federated_gbdt.py @@ -176,8 +176,8 @@ def __post_init__(self): 'validation cohort size must be an integer >= 0') assert self.cohort_size_per_layer_modifier_fn in [ 'none', 'linear', 'power' - ], (f'{self.cohort_size_per_layer_modifier_function} is not a', - 'valid value for cohort_size_per_layer_modifier_function') + ], (f'{self.cohort_size_per_layer_modifier_fn} is not a', + 'valid value for cohort_size_per_layer_modifier_fn') assert isinstance( self.leaf_nodes_reduction_factor, int) and self.leaf_nodes_reduction_factor >= 1, ( From b1e7be618271e8f50ed698545d27f0152d3220ae Mon Sep 17 00:00:00 2001 From: Martin Pelikan <154003090+martin-pelikan-apple@users.noreply.github.com> Date: Fri, 10 May 2024 09:54:03 -0700 Subject: [PATCH 11/22] Fixes werkzeug vulnerability (#68) --- benchmarks/poetry.lock | 8 ++++---- poetry.lock | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/benchmarks/poetry.lock b/benchmarks/poetry.lock index 124d9ed..fb31b53 100644 --- a/benchmarks/poetry.lock +++ b/benchmarks/poetry.lock @@ -1696,7 +1696,7 @@ requests = ">=2.21.0,<3" setuptools = ">=41.0.0" six = ">1.9" tensorboard-data-server = ">=0.7.0,<0.8.0" -werkzeug = ">=1.0.1" +werkzeug = ">=3.0.3" [[package]] name = "tensorboard-data-server" @@ -2202,13 +2202,13 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess [[package]] name = "werkzeug" -version = "3.0.0" +version = "3.0.3" description = "The comprehensive WSGI web application library." optional = true python-versions = ">=3.8" files = [ - {file = "werkzeug-3.0.0-py3-none-any.whl", hash = "sha256:cbb2600f7eabe51dbc0502f58be0b3e1b96b893b05695ea2b35b43d4de2d9962"}, - {file = "werkzeug-3.0.0.tar.gz", hash = "sha256:3ffff4dcc32db52ef3cc94dff3000a3c2846890f3a5a51800a27b909c5e770f0"}, + {file = "werkzeug-3.0.3-py3-none-any.whl", hash = "sha256:fc9645dc43e03e4d630d23143a04a7f947a9a3b5727cd535fdfe155a17cc48c8"}, + {file = "werkzeug-3.0.3.tar.gz", hash = "sha256:097e5bfda9f0aba8da6b8545146def481d06aa7d3266e7448e2cccf67dd8bd18"}, ] [package.dependencies] diff --git a/poetry.lock b/poetry.lock index 547ea88..bbd03f3 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2079,7 +2079,7 @@ requests = ">=2.21.0,<3" setuptools = ">=41.0.0" six = ">1.9" tensorboard-data-server = ">=0.7.0,<0.8.0" -werkzeug = ">=1.0.1" +werkzeug = ">=3.0.3" [[package]] name = "tensorboard-data-server" @@ -2483,13 +2483,13 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess [[package]] name = "werkzeug" -version = "3.0.0" +version = "3.0.3" description = "The comprehensive WSGI web application library." optional = true python-versions = ">=3.8" files = [ - {file = "werkzeug-3.0.0-py3-none-any.whl", hash = "sha256:cbb2600f7eabe51dbc0502f58be0b3e1b96b893b05695ea2b35b43d4de2d9962"}, - {file = "werkzeug-3.0.0.tar.gz", hash = "sha256:3ffff4dcc32db52ef3cc94dff3000a3c2846890f3a5a51800a27b909c5e770f0"}, + {file = "werkzeug-3.0.3-py3-none-any.whl", hash = "sha256:fc9645dc43e03e4d630d23143a04a7f947a9a3b5727cd535fdfe155a17cc48c8"}, + {file = "werkzeug-3.0.3.tar.gz", hash = "sha256:097e5bfda9f0aba8da6b8545146def481d06aa7d3266e7448e2cccf67dd8bd18"}, ] [package.dependencies] From 2df910ebbbf7e37141b0a9efac12e03a8bc4b847 Mon Sep 17 00:00:00 2001 From: fgranqvist Date: Wed, 29 May 2024 11:50:21 +0200 Subject: [PATCH 12/22] move noise cohort to privacy args (#70) --- benchmarks/utils/argument_parsing.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/benchmarks/utils/argument_parsing.py b/benchmarks/utils/argument_parsing.py index bd5cc2f..00885b5 100644 --- a/benchmarks/utils/argument_parsing.py +++ b/benchmarks/utils/argument_parsing.py @@ -184,15 +184,6 @@ def add_dnn_training_arguments(argument_parser): help='The target number of users for one iteration ' 'of training.') - argument_parser.add_argument( - '--noise_cohort_size', - type=int, - default=1000, - help=('The cohort size to use in calculating noise for DP. ' - 'If you run cohort_size=100 but noise_cohort_size=1000, ' - 'then your results will only be valid if running with ' - 'cohort_size=1000 outside simulation')) - argument_parser.add_argument( '--val_cohort_size', type=int, @@ -347,6 +338,16 @@ def __call__(self, parser, namespace, values, option_string=None): 'sampled to participate again. This parameter is used in ' '`BandedMatrixFactorizationMechanism`.') + argument_parser.add_argument( + '--noise_cohort_size', + type=int, + default=1000, + help=('The cohort size to use when calculating noise for DP. ' + 'If you run cohort_size=100 but noise_cohort_size=1000, ' + 'then the noise will be scaled down by a factor of 0.1 ' + 'and your results will only be valid if running with ' + 'cohort_size=1000 outside simulation')) + return argument_parser From 5b488286b3bb053c8ba0094bc7ed8ec0ac1c21b5 Mon Sep 17 00:00:00 2001 From: fgranqvist Date: Thu, 30 May 2024 13:21:36 +0200 Subject: [PATCH 13/22] FLAIR HF (#72) --- benchmarks/dataset/flair/download_dataset.py | 94 -- .../dataset/flair/download_preprocess.py | 213 +++++ benchmarks/dataset/flair/prepare_dataset.py | 236 ----- benchmarks/flair/README.md | 3 +- benchmarks/poetry.lock | 806 +++++++++++++++++- benchmarks/pyproject.toml | 1 + 6 files changed, 1014 insertions(+), 339 deletions(-) delete mode 100644 benchmarks/dataset/flair/download_dataset.py create mode 100644 benchmarks/dataset/flair/download_preprocess.py delete mode 100644 benchmarks/dataset/flair/prepare_dataset.py diff --git a/benchmarks/dataset/flair/download_dataset.py b/benchmarks/dataset/flair/download_dataset.py deleted file mode 100644 index cb4a82a..0000000 --- a/benchmarks/dataset/flair/download_dataset.py +++ /dev/null @@ -1,94 +0,0 @@ -# Copyright © 2023-2024 Apple Inc. -import argparse -import functools -import logging -import multiprocessing -import os -import subprocess -import sys -from urllib.parse import urljoin -from urllib.request import urlretrieve - -logger = logging.getLogger(name=__name__) - -DATA_URL = "https://docs-assets.developer.apple.com/ml-research/datasets/flair/" -NUM_IMAGE_BATCHES = 43 -SMALL_IMAGE_URLS = [ - urljoin(DATA_URL, f"images/small/small_images-{str(i).zfill(2)}.tar.gz") - for i in range(NUM_IMAGE_BATCHES) -] -RAW_IMAGE_URLS = [ - urljoin(DATA_URL, f"images/raw/images-{str(i).zfill(2)}.tar.gz") - for i in range(NUM_IMAGE_BATCHES) -] -LABELS_AND_METADATA_URL = urljoin(DATA_URL, "labels/labels_and_metadata.json") -LABEL_RELATIONSHIP_URL = urljoin(DATA_URL, "labels/label_relationship.txt") - - -def extract_tar(compressed_path: str, dataset_dir: str, - keep_archive_after_decompress: bool): - subprocess.run(f"tar -zxf {compressed_path} -C {dataset_dir}".split(), - check=True) - if not keep_archive_after_decompress: - os.remove(compressed_path) - - -def decompress_images(dataset_dir: str, keep_archive_after_decompress: bool): - compressed_paths = [ - os.path.join(dataset_dir, path) for path in os.listdir(dataset_dir) - if path.endswith(".tar.gz") - ] - decompress = functools.partial( - extract_tar, - dataset_dir=dataset_dir, - keep_archive_after_decompress=keep_archive_after_decompress) - with multiprocessing.Pool(multiprocessing.cpu_count()) as pool: - pool.map(decompress, compressed_paths) - - -if __name__ == '__main__': - logging.basicConfig(stream=sys.stdout, - level=logging.INFO, - format='%(asctime)s %(levelname)s: %(message)s') - - parser = argparse.ArgumentParser( - description='Download the images and labels of FLAIR dataset.') - parser.add_argument("--dataset_dir", - required=True, - help="Path to directory of dataset to be downloaded") - parser.add_argument("--download_raw", - action="store_true", - help="Whether to download the raw images, " - "which need storage space ~1.2TB") - parser.add_argument("--keep_archive_after_decompress", - action="store_true", - help="Whether to keep the image tarball archives") - arguments = parser.parse_args() - os.makedirs(arguments.dataset_dir, exist_ok=True) - - # download labels and metadata - logger.info("Downloading labels...") - urlretrieve( - LABELS_AND_METADATA_URL, - os.path.join(arguments.dataset_dir, - os.path.basename(LABELS_AND_METADATA_URL))) - urlretrieve( - LABEL_RELATIONSHIP_URL, - os.path.join(arguments.dataset_dir, - os.path.basename(LABEL_RELATIONSHIP_URL))) - # download and decompress all images - for image_url in SMALL_IMAGE_URLS: - logger.info(f"Downloading small image: {image_url}") - urlretrieve( - image_url, - os.path.join(arguments.dataset_dir, os.path.basename(image_url))) - if arguments.download_raw: - for image_url in RAW_IMAGE_URLS: - logger.info(f"Downloading raw image: {image_url}") - urlretrieve( - image_url, - os.path.join(arguments.dataset_dir, - os.path.basename(image_url))) - logger.info("Decompressing images...") - decompress_images(arguments.dataset_dir, - arguments.keep_archive_after_decompress) diff --git a/benchmarks/dataset/flair/download_preprocess.py b/benchmarks/dataset/flair/download_preprocess.py new file mode 100644 index 0000000..f6e833e --- /dev/null +++ b/benchmarks/dataset/flair/download_preprocess.py @@ -0,0 +1,213 @@ +# Copyright © 2024 Apple Inc. +import argparse +import json +import logging +import sys +from collections import Counter, defaultdict +from typing import Counter as TCounter + +import h5py +import numpy as np +import tqdm +from datasets import load_dataset + +logger = logging.getLogger(name=__name__) + +LABEL_DELIMITER = '|' # Labels will be joined by delimiter and saved to hdf5 +LOG_INTERVAL = 100 # Log the preprocessing progress every interval steps + + +def load_image_from_huggingface(dataset, image_id): + """ + Load an image from the HuggingFace dataset by image_id. + + :param dataset: + The loaded HuggingFace dataset. + :param image_id: + The image_id of the image to be loaded. + :return: + The loaded image as a PIL Image object. + """ + # Assuming image_id is unique and using filter to get the specific image + image_data = dataset.filter(lambda x: x['image_id'] == image_id) + image_entry = next(iter(image_data)) # Get the first (and only) entry + return image_entry['image'] + + +def preprocess_federated_dataset(output_file: str): + """ + Process images and labels into a HDF5 federated dataset where data is + first split by train/test partitions and then split again by user ID. + + :param dataset: + The loaded HuggingFace dataset. + :param output_file: + Output path for HDF5 file. Use the postfix `.hdf5`. + """ + + # Load dataset from HuggingFace + # This is a Dict[str, Dataset] where key is the split. + dataset_splits = load_dataset('apple/flair', keep_in_memory=False) + logger.info( + f'Preprocessing federated dataset, sample record: {next(iter(dataset_splits["train"]))}' + ) + + label_counter: TCounter[str] = Counter() + fine_grained_label_counter: TCounter[str] = Counter() + + partition_to_user_to_ix: defaultdict = defaultdict( + lambda: defaultdict(list)) + for partition, ds in dataset_splits.items(): + for i, entry in tqdm.tqdm( + enumerate(ds), + total=len(ds), + desc=f'{partition} - Mapping users to datapoints.'): + # Make user to datapoints mapping. + partition_to_user_to_ix[partition][entry['user_id']].append(i) + label_counter.update(entry["labels"]) + fine_grained_label_counter.update(entry["fine_grained_labels"]) + + label_to_index = { + label: index + for index, label in enumerate(sorted(label_counter.keys())) + } + fine_grained_label_to_index = { + fine_grained_label: index + for index, fine_grained_label in enumerate( + sorted(fine_grained_label_counter.keys())) + } + + with h5py.File(output_file, 'w') as h5file: + for partition, user_to_ix in partition_to_user_to_ix.items(): + ds = dataset_splits[partition] + + # Iterate through users of each partition. + for i, (user_id, data_indices) in tqdm.tqdm( + enumerate(user_to_ix.items()), + total=len(user_to_ix), + desc=f'{partition} - constructing dataset'): + # Load and concatenate all images and labels of a user. + image_array, image_id_array = [], [] + labels_row, labels_col = [], [] + fine_grained_labels_row, fine_grained_labels_col = [], [] + for j, data_index in enumerate(data_indices): + metadata = ds[data_index] + image_id = metadata["image_id"] + image_array.append(np.asarray(metadata["image"])) + image_id_array.append(image_id) + # Encode labels as row indices and column indices + labels_row.extend([j] * len(metadata["labels"])) + labels_col.extend( + [label_to_index[l] for l in metadata["labels"]]) + fine_grained_labels_row.extend( + [j] * len(metadata["fine_grained_labels"])) + fine_grained_labels_col.extend([ + fine_grained_label_to_index[l] + for l in metadata["fine_grained_labels"] + ]) + # Update label counter + label_counter.update(metadata["labels"]) + fine_grained_label_counter.update( + metadata["fine_grained_labels"]) + + # Multiple variable-length labels. Needs to be stored as a string. + h5file[f'/{partition}/{user_id}/labels_row'] = np.asarray( + labels_row, dtype=np.uint16) + h5file[f'/{partition}/{user_id}/labels_col'] = np.asarray( + labels_col, dtype=np.uint8) + h5file[ + f'/{partition}/{user_id}/fine_grained_labels_row'] = np.asarray( + fine_grained_labels_row, dtype=np.uint16) + h5file[ + f'/{partition}/{user_id}/fine_grained_labels_col'] = np.asarray( + fine_grained_labels_col, dtype=np.uint16) + h5file[f'/{partition}/{user_id}/image_ids'] = np.asarray( + image_id_array, dtype='S') + # Tensor with dimensions [num_images,width,height,channels] + h5file.create_dataset(f'/{partition}/{user_id}/images', + data=np.stack(image_array)) + + if (i + 1) % LOG_INTERVAL == 0: + logger.info(f"Processed {i + 1}/{len(user_to_ix)} users") + + # Write metadata + h5file['/metadata/label_mapping'] = json.dumps(label_to_index) + h5file['/metadata/fine_grained_label_mapping'] = json.dumps( + fine_grained_label_to_index) + + logger.info('Finished preprocess federated dataset successfully!') + + +def preprocess_central_dataset(output_file: str): + """ + Process images and labels into a HDF5 (not federated) dataset where + data is split by train/val/test partitions. + + :param dataset: + The loaded HuggingFace dataset. + :param output_file: + Output path for HDF5 file. Use the postfix `.hdf5`. + """ + logger.info('Preprocessing central dataset.') + dataset_splits = load_dataset('apple/flair', keep_in_memory=False) + + label_counter: TCounter[str] = Counter() + fine_grained_label_counter: TCounter[str] = Counter() + with h5py.File(output_file, 'w') as h5file: + # Iterate through dataset. + for partition, dataset in dataset_splits.items(): + for i, entry in tqdm.tqdm(enumerate(dataset), total=len(dataset)): + image_id = entry["image_id"] + image = np.asarray( + entry["image"] + ) # Directly use the image array from the dataset + h5file.create_dataset(f'/{partition}/{image_id}/image', + data=image) + # Encode labels as a single string, separated by delimiter | + h5file[ + f'/{partition}/{image_id}/labels'] = LABEL_DELIMITER.join( + entry["labels"]) + h5file[f'/{partition}/{image_id}/fine_grained_labels'] = ( + LABEL_DELIMITER.join(entry["fine_grained_labels"])) + h5file[f'/{partition}/{image_id}/user_id'] = entry["user_id"] + # Update label counter + label_counter.update(entry["labels"]) + fine_grained_label_counter.update(entry["fine_grained_labels"]) + + if (i + 1) % LOG_INTERVAL == 0: + logger.info(f"Processed {i + 1}/{len(dataset)} entries") + + # Write metadata + h5file['/metadata/label_mapping'] = json.dumps(dict(label_counter)) + h5file['/metadata/fine_grained_label_mapping'] = json.dumps( + dict(fine_grained_label_counter)) + + logger.info('Finished preprocessing central dataset successfully!') + + +if __name__ == '__main__': + logging.basicConfig(stream=sys.stdout, + level=logging.INFO, + format='%(asctime)s %(levelname)s: %(message)s') + + argument_parser = argparse.ArgumentParser( + description= + 'Download and preprocess the images and labels of FLAIR dataset into HDF5 files.' + ) + argument_parser.add_argument( + '--output_file', + required=True, + help='Path to output HDF5 file that will be constructed by this script' + ) + argument_parser.add_argument('--not_group_data_by_user', + action='store_true', + default=False, + help='If true, do not group data by user IDs.' + 'If false, group data by user IDs to ' + 'make suitable for federated learning.') + arguments = argument_parser.parse_args() + + if arguments.not_group_data_by_user: + preprocess_central_dataset(arguments.output_file) + else: + preprocess_federated_dataset(arguments.output_file) diff --git a/benchmarks/dataset/flair/prepare_dataset.py b/benchmarks/dataset/flair/prepare_dataset.py deleted file mode 100644 index 5a9ba50..0000000 --- a/benchmarks/dataset/flair/prepare_dataset.py +++ /dev/null @@ -1,236 +0,0 @@ -# Copyright © 2023-2024 Apple Inc. -import argparse -import json -import logging -import os -import sys -from collections import Counter, defaultdict -from typing import Dict, Tuple - -import h5py -import numpy as np -import tqdm -from PIL import Image - -logger = logging.getLogger(name=__name__) - -LABEL_DELIMITER = '|' # Labels will be joined by delimiter and saved to hdf5 -LOG_INTERVAL = 100 # Log the preprocessing progress every interval steps - - -def load_user_metadata_and_label_counters( - labels_file: str) -> Tuple[Dict, Counter, Counter]: - """ - Load labels and metadata keyed by `user_id`, and label counts. - - :param labels_file: - A .json file with a list of labels and metadata dictionaries. Each - dictionary has keys: `[image_id,user_id,labels,fine_grained_labels]`. - * `image_id` is the ID of an image. - * `user_id` is the ID of the user `image_id` belongs to. - * `labels` is a list of 17 higher-order class labels. - * `fine_grained_labels` is a list of 1,628 fine-grained class labels. - :return: - Three dictionaries. First dictionary has key being `user_id` and value - being a list of labels and metadata for each image `user_id` owns. - Second and third dictionaries are counts for the labels for coarse-grained - and fine-grained taxonomies. - """ - user_metadata = defaultdict(list) - with open(labels_file) as f: - metadata_list = json.load(f) - - label_counter: Counter = Counter() - fine_grained_label_counter: Counter = Counter() - for metadata in metadata_list: - user_metadata[metadata["user_id"]].append(metadata) - label_counter.update(metadata["labels"]) - fine_grained_label_counter.update(metadata["fine_grained_labels"]) - return user_metadata, label_counter, fine_grained_label_counter - - -def preprocess_federated_dataset(image_dir: str, labels_file: str, - output_file: str): - """ - Process images and labels into a HDF5 federated dataset where data is - first split by train/test partitions and then split again by user ID. - - :param image_dir: - Path to directory of images output from the script - `download_dataset.sh`. - :param labels_file: - A .json file with a list of labels and metadata dictionaries. Each - dictionary has keys: `[image_id,user_id,labels,fine_grained_labels]`. - * `image_id` is the ID of an image. - * `user_id` is the ID of the user `image_id` belongs to. - * `labels` is a list of 17 higher-order class labels. - * `fine_grained_labels` is a list of ~1,600 fine-grained class labels. - :param output_file: - Output path for HDF5 file. Use the postfix `.hdf5`. - """ - logger.info('Preprocessing federated dataset.') - (user_metadata, label_counter, fine_grained_label_counter - ) = load_user_metadata_and_label_counters(labels_file) - - label_to_index = { - label: index - for index, label in enumerate(sorted(label_counter.keys())) - } - fine_grained_label_to_index = { - fine_grained_label: index - for index, fine_grained_label in enumerate( - sorted(fine_grained_label_counter.keys())) - } - - label_counter = Counter() - fine_grained_label_counter = Counter() - with h5py.File(output_file, 'w') as h5file: - # Iterate through users of each partition. - for i, user_id in tqdm.tqdm(enumerate(user_metadata), - total=len(user_metadata)): - # This snippet was used to generate flair_federated_small.h5 - #if i > len(user_metadata)*0.01: - # break - #if len(user_metadata[user_id]) > 20: - # # Skip large users - # continue - # This snippet was used to generate flair_federated_ci.h5 - #if i > 12: - # break - #if i > 10: - # user_metadata[user_id][0]['partition'] = 'test' - - # Load and concatenate all images of a user. - image_array, image_id_array = [], [] - labels_row, labels_col = [], [] - fine_grained_labels_row, fine_grained_labels_col = [], [] - # Load and concatenate all images and labels of a user. - for j, metadata in enumerate(user_metadata[user_id]): - image_id = metadata["image_id"] - image = Image.open(os.path.join(image_dir, f"{image_id}.jpg")) - image_array.append(np.asarray(image)) - image_id_array.append(image_id) - # Encode labels as row indices and column indices - labels_row.extend([j] * len(metadata["labels"])) - labels_col.extend( - [label_to_index[l] for l in metadata["labels"]]) - fine_grained_labels_row.extend( - [j] * len(metadata["fine_grained_labels"])) - fine_grained_labels_col.extend([ - fine_grained_label_to_index[l] - for l in metadata["fine_grained_labels"] - ]) - # Update label counter - label_counter.update(metadata["labels"]) - fine_grained_label_counter.update( - metadata["fine_grained_labels"]) - - partition = user_metadata[user_id][0]["partition"] - # Multiple variable-length labels. Needs to be stored as a string. - h5file[f'/{partition}/{user_id}/labels_row'] = np.asarray( - labels_row, dtype=np.uint16) - h5file[f'/{partition}/{user_id}/labels_col'] = np.asarray( - labels_col, dtype=np.uint8) - h5file[ - f'/{partition}/{user_id}/fine_grained_labels_row'] = np.asarray( - fine_grained_labels_row, dtype=np.uint16) - h5file[ - f'/{partition}/{user_id}/fine_grained_labels_col'] = np.asarray( - fine_grained_labels_col, dtype=np.uint16) - h5file[f'/{partition}/{user_id}/image_ids'] = np.asarray( - image_id_array, dtype='S') - # Tensor with dimensions [num_images,width,height,channels] - h5file.create_dataset(f'/{partition}/{user_id}/images', - data=np.stack(image_array)) - - if (i + 1) % LOG_INTERVAL == 0: - logger.info(f"Processed {i + 1}/{len(user_metadata)} users") - - # Write metadata - h5file['/metadata/label_mapping'] = json.dumps(label_to_index) - h5file['/metadata/fine_grained_label_mapping'] = json.dumps( - fine_grained_label_to_index) - - logger.info('Finished preprocess federated dataset successfully!') - - -def preprocess_central_dataset(image_dir: str, labels_file: str, - output_file: str): - """ - Process images and labels into a HDF5 (not federated) dataset where - data is split by train/val/test partitions. - - Same parameters as `preprocess_federated_dataset`. - """ - logger.info('Preprocessing central dataset.') - (user_metadata, _, _) = load_user_metadata_and_label_counters(labels_file) - label_counter: Counter = Counter() - fine_grained_label_counter: Counter = Counter() - with h5py.File(output_file, 'w') as h5file: - # Iterate through users of each partition. - for i, user_id in enumerate(user_metadata): - # Load and concatenate all images of a user. - for metadata in user_metadata[user_id]: - image_id = metadata["image_id"] - image = Image.open(os.path.join(image_dir, f"{image_id}.jpg")) - partition = metadata["partition"] - h5file.create_dataset(f'/{partition}/{image_id}/image', - data=np.asarray(image)) - # Encode labels as a single string, separated by delimiter | - h5file[ - f'/{partition}/{image_id}/labels'] = LABEL_DELIMITER.join( - metadata["labels"]) - h5file[f'/{partition}/{image_id}/fine_grained_labels'] = ( - LABEL_DELIMITER.join(metadata["fine_grained_labels"])) - h5file[f'/{partition}/{image_id}/user_id'] = user_id - # Update label counter - label_counter.update(metadata["labels"]) - fine_grained_label_counter.update( - metadata["fine_grained_labels"]) - - if (i + 1) % LOG_INTERVAL == 0: - logger.info(f"Processed {i + 1}/{len(user_metadata)} users") - - # Write metadata - h5file['/metadata/label_mapping'] = json.dumps(label_counter) - h5file['/metadata/fine_grained_label_mapping'] = json.dumps( - fine_grained_label_counter) - - logger.info('Finished preprocessing central dataset successfully!') - - -if __name__ == '__main__': - logging.basicConfig(stream=sys.stdout, - level=logging.INFO, - format='%(asctime)s %(levelname)s: %(message)s') - - argument_parser = argparse.ArgumentParser( - description= - 'Preprocess the images and labels of FLAIR dataset into HDF5 files.') - argument_parser.add_argument( - '--dataset_dir', - required=True, - help='Path to directory of images and label file. ' - 'Can be downloaded using download_dataset.py') - argument_parser.add_argument( - '--output_file', - required=True, - help='Path to output HDF5 file that will be constructed by this script' - ) - argument_parser.add_argument('--not_group_data_by_user', - action='store_true', - default=False, - help='If true, do not group data by user IDs.' - 'If false, group data by user IDs to ' - 'make suitable for federated learning.') - arguments = argument_parser.parse_args() - - image_dir = os.path.join(arguments.dataset_dir, "small_images") - labels_file = os.path.join(arguments.dataset_dir, - "labels_and_metadata.json") - if arguments.not_group_data_by_user: - preprocess_central_dataset(image_dir, labels_file, - arguments.output_file) - else: - preprocess_federated_dataset(image_dir, labels_file, - arguments.output_file) diff --git a/benchmarks/flair/README.md b/benchmarks/flair/README.md index 49e177f..89e9fcf 100644 --- a/benchmarks/flair/README.md +++ b/benchmarks/flair/README.md @@ -13,8 +13,7 @@ Same as the [default setup](../README.md). ## Download and preprocess FLAIR dataset ``` -python -m dataset.flair.download_dataset --dataset_dir ./data/flair -python -m dataset.flair.prepare_dataset --dataset_dir data/flair/ --output_file data/flair/flair_federated.hdf5 +python -m dataset.flair.download_preprocess --output_file data/flair/flair_federated.hdf5 ``` ## Run benchmarks diff --git a/benchmarks/poetry.lock b/benchmarks/poetry.lock index fb31b53..83b6ce2 100644 --- a/benchmarks/poetry.lock +++ b/benchmarks/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "absl-py" @@ -11,6 +11,116 @@ files = [ {file = "absl_py-1.4.0-py3-none-any.whl", hash = "sha256:0d3fe606adfa4f7db64792dd4c7aee4ee0c38ab75dfd353b7a83ed3e957fcb47"}, ] +[[package]] +name = "aiohttp" +version = "3.9.5" +description = "Async http client/server framework (asyncio)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "aiohttp-3.9.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fcde4c397f673fdec23e6b05ebf8d4751314fa7c24f93334bf1f1364c1c69ac7"}, + {file = "aiohttp-3.9.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5d6b3f1fabe465e819aed2c421a6743d8debbde79b6a8600739300630a01bf2c"}, + {file = "aiohttp-3.9.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ae79c1bc12c34082d92bf9422764f799aee4746fd7a392db46b7fd357d4a17a"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d3ebb9e1316ec74277d19c5f482f98cc65a73ccd5430540d6d11682cd857430"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84dabd95154f43a2ea80deffec9cb44d2e301e38a0c9d331cc4aa0166fe28ae3"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c8a02fbeca6f63cb1f0475c799679057fc9268b77075ab7cf3f1c600e81dd46b"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c26959ca7b75ff768e2776d8055bf9582a6267e24556bb7f7bd29e677932be72"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:714d4e5231fed4ba2762ed489b4aec07b2b9953cf4ee31e9871caac895a839c0"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e7a6a8354f1b62e15d48e04350f13e726fa08b62c3d7b8401c0a1314f02e3558"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c413016880e03e69d166efb5a1a95d40f83d5a3a648d16486592c49ffb76d0db"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ff84aeb864e0fac81f676be9f4685f0527b660f1efdc40dcede3c251ef1e867f"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ad7f2919d7dac062f24d6f5fe95d401597fbb015a25771f85e692d043c9d7832"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:702e2c7c187c1a498a4e2b03155d52658fdd6fda882d3d7fbb891a5cf108bb10"}, + {file = "aiohttp-3.9.5-cp310-cp310-win32.whl", hash = "sha256:67c3119f5ddc7261d47163ed86d760ddf0e625cd6246b4ed852e82159617b5fb"}, + {file = "aiohttp-3.9.5-cp310-cp310-win_amd64.whl", hash = "sha256:471f0ef53ccedec9995287f02caf0c068732f026455f07db3f01a46e49d76bbb"}, + {file = "aiohttp-3.9.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e0ae53e33ee7476dd3d1132f932eeb39bf6125083820049d06edcdca4381f342"}, + {file = "aiohttp-3.9.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c088c4d70d21f8ca5c0b8b5403fe84a7bc8e024161febdd4ef04575ef35d474d"}, + {file = "aiohttp-3.9.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:639d0042b7670222f33b0028de6b4e2fad6451462ce7df2af8aee37dcac55424"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f26383adb94da5e7fb388d441bf09c61e5e35f455a3217bfd790c6b6bc64b2ee"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66331d00fb28dc90aa606d9a54304af76b335ae204d1836f65797d6fe27f1ca2"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4ff550491f5492ab5ed3533e76b8567f4b37bd2995e780a1f46bca2024223233"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f22eb3a6c1080d862befa0a89c380b4dafce29dc6cd56083f630073d102eb595"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a81b1143d42b66ffc40a441379387076243ef7b51019204fd3ec36b9f69e77d6"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f64fd07515dad67f24b6ea4a66ae2876c01031de91c93075b8093f07c0a2d93d"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:93e22add827447d2e26d67c9ac0161756007f152fdc5210277d00a85f6c92323"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:55b39c8684a46e56ef8c8d24faf02de4a2b2ac60d26cee93bc595651ff545de9"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4715a9b778f4293b9f8ae7a0a7cef9829f02ff8d6277a39d7f40565c737d3771"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:afc52b8d969eff14e069a710057d15ab9ac17cd4b6753042c407dcea0e40bf75"}, + {file = "aiohttp-3.9.5-cp311-cp311-win32.whl", hash = "sha256:b3df71da99c98534be076196791adca8819761f0bf6e08e07fd7da25127150d6"}, + {file = "aiohttp-3.9.5-cp311-cp311-win_amd64.whl", hash = "sha256:88e311d98cc0bf45b62fc46c66753a83445f5ab20038bcc1b8a1cc05666f428a"}, + {file = "aiohttp-3.9.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:c7a4b7a6cf5b6eb11e109a9755fd4fda7d57395f8c575e166d363b9fc3ec4678"}, + {file = "aiohttp-3.9.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:0a158704edf0abcac8ac371fbb54044f3270bdbc93e254a82b6c82be1ef08f3c"}, + {file = "aiohttp-3.9.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d153f652a687a8e95ad367a86a61e8d53d528b0530ef382ec5aaf533140ed00f"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82a6a97d9771cb48ae16979c3a3a9a18b600a8505b1115cfe354dfb2054468b4"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60cdbd56f4cad9f69c35eaac0fbbdf1f77b0ff9456cebd4902f3dd1cf096464c"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8676e8fd73141ded15ea586de0b7cda1542960a7b9ad89b2b06428e97125d4fa"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da00da442a0e31f1c69d26d224e1efd3a1ca5bcbf210978a2ca7426dfcae9f58"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18f634d540dd099c262e9f887c8bbacc959847cfe5da7a0e2e1cf3f14dbf2daf"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:320e8618eda64e19d11bdb3bd04ccc0a816c17eaecb7e4945d01deee2a22f95f"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:2faa61a904b83142747fc6a6d7ad8fccff898c849123030f8e75d5d967fd4a81"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:8c64a6dc3fe5db7b1b4d2b5cb84c4f677768bdc340611eca673afb7cf416ef5a"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:393c7aba2b55559ef7ab791c94b44f7482a07bf7640d17b341b79081f5e5cd1a"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c671dc117c2c21a1ca10c116cfcd6e3e44da7fcde37bf83b2be485ab377b25da"}, + {file = "aiohttp-3.9.5-cp312-cp312-win32.whl", hash = "sha256:5a7ee16aab26e76add4afc45e8f8206c95d1d75540f1039b84a03c3b3800dd59"}, + {file = "aiohttp-3.9.5-cp312-cp312-win_amd64.whl", hash = "sha256:5ca51eadbd67045396bc92a4345d1790b7301c14d1848feaac1d6a6c9289e888"}, + {file = "aiohttp-3.9.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:694d828b5c41255e54bc2dddb51a9f5150b4eefa9886e38b52605a05d96566e8"}, + {file = "aiohttp-3.9.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0605cc2c0088fcaae79f01c913a38611ad09ba68ff482402d3410bf59039bfb8"}, + {file = "aiohttp-3.9.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4558e5012ee03d2638c681e156461d37b7a113fe13970d438d95d10173d25f78"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dbc053ac75ccc63dc3a3cc547b98c7258ec35a215a92bd9f983e0aac95d3d5b"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4109adee842b90671f1b689901b948f347325045c15f46b39797ae1bf17019de"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6ea1a5b409a85477fd8e5ee6ad8f0e40bf2844c270955e09360418cfd09abac"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3c2890ca8c59ee683fd09adf32321a40fe1cf164e3387799efb2acebf090c11"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3916c8692dbd9d55c523374a3b8213e628424d19116ac4308e434dbf6d95bbdd"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8d1964eb7617907c792ca00b341b5ec3e01ae8c280825deadbbd678447b127e1"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d5ab8e1f6bee051a4bf6195e38a5c13e5e161cb7bad83d8854524798bd9fcd6e"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:52c27110f3862a1afbcb2af4281fc9fdc40327fa286c4625dfee247c3ba90156"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:7f64cbd44443e80094309875d4f9c71d0401e966d191c3d469cde4642bc2e031"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8b4f72fbb66279624bfe83fd5eb6aea0022dad8eec62b71e7bf63ee1caadeafe"}, + {file = "aiohttp-3.9.5-cp38-cp38-win32.whl", hash = "sha256:6380c039ec52866c06d69b5c7aad5478b24ed11696f0e72f6b807cfb261453da"}, + {file = "aiohttp-3.9.5-cp38-cp38-win_amd64.whl", hash = "sha256:da22dab31d7180f8c3ac7c7635f3bcd53808f374f6aa333fe0b0b9e14b01f91a"}, + {file = "aiohttp-3.9.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1732102949ff6087589408d76cd6dea656b93c896b011ecafff418c9661dc4ed"}, + {file = "aiohttp-3.9.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c6021d296318cb6f9414b48e6a439a7f5d1f665464da507e8ff640848ee2a58a"}, + {file = "aiohttp-3.9.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:239f975589a944eeb1bad26b8b140a59a3a320067fb3cd10b75c3092405a1372"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b7b30258348082826d274504fbc7c849959f1989d86c29bc355107accec6cfb"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd2adf5c87ff6d8b277814a28a535b59e20bfea40a101db6b3bdca7e9926bc24"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e9a3d838441bebcf5cf442700e3963f58b5c33f015341f9ea86dcd7d503c07e2"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e3a1ae66e3d0c17cf65c08968a5ee3180c5a95920ec2731f53343fac9bad106"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9c69e77370cce2d6df5d12b4e12bdcca60c47ba13d1cbbc8645dd005a20b738b"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0cbf56238f4bbf49dab8c2dc2e6b1b68502b1e88d335bea59b3f5b9f4c001475"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d1469f228cd9ffddd396d9948b8c9cd8022b6d1bf1e40c6f25b0fb90b4f893ed"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:45731330e754f5811c314901cebdf19dd776a44b31927fa4b4dbecab9e457b0c"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:3fcb4046d2904378e3aeea1df51f697b0467f2aac55d232c87ba162709478c46"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8cf142aa6c1a751fcb364158fd710b8a9be874b81889c2bd13aa8893197455e2"}, + {file = "aiohttp-3.9.5-cp39-cp39-win32.whl", hash = "sha256:7b179eea70833c8dee51ec42f3b4097bd6370892fa93f510f76762105568cf09"}, + {file = "aiohttp-3.9.5-cp39-cp39-win_amd64.whl", hash = "sha256:38d80498e2e169bc61418ff36170e0aad0cd268da8b38a17c4cf29d254a8b3f1"}, + {file = "aiohttp-3.9.5.tar.gz", hash = "sha256:edea7d15772ceeb29db4aff55e482d4bcfb6ae160ce144f2682de02f6d693551"}, +] + +[package.dependencies] +aiosignal = ">=1.1.2" +async-timeout = {version = ">=4.0,<5.0", markers = "python_version < \"3.11\""} +attrs = ">=17.3.0" +frozenlist = ">=1.1.1" +multidict = ">=4.5,<7.0" +yarl = ">=1.0,<2.0" + +[package.extras] +speedups = ["Brotli", "aiodns", "brotlicffi"] + +[[package]] +name = "aiosignal" +version = "1.3.1" +description = "aiosignal: a list of registered asynchronous callbacks" +optional = false +python-versions = ">=3.7" +files = [ + {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, + {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, +] + +[package.dependencies] +frozenlist = ">=1.1.0" + [[package]] name = "astunparse" version = "1.6.3" @@ -26,11 +136,22 @@ files = [ six = ">=1.6.1,<2.0" wheel = ">=0.23.0,<1.0" +[[package]] +name = "async-timeout" +version = "4.0.3" +description = "Timeout context manager for asyncio programs" +optional = false +python-versions = ">=3.7" +files = [ + {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"}, + {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, +] + [[package]] name = "attrs" version = "23.2.0" description = "Classes Without Boilerplate" -optional = true +optional = false python-versions = ">=3.7" files = [ {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, @@ -98,7 +219,7 @@ files = [ name = "certifi" version = "2023.7.22" description = "Python package for providing Mozilla's CA Bundle." -optional = true +optional = false python-versions = ">=3.6" files = [ {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, @@ -120,7 +241,7 @@ files = [ name = "charset-normalizer" version = "3.3.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -optional = true +optional = false python-versions = ">=3.7.0" files = [ {file = "charset-normalizer-3.3.0.tar.gz", hash = "sha256:63563193aec44bce707e0c5ca64ff69fa72ed7cf34ce6e11d5127555756fd2f6"}, @@ -266,6 +387,50 @@ files = [ {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, ] +[[package]] +name = "datasets" +version = "2.19.1" +description = "HuggingFace community-driven open-source library of datasets" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "datasets-2.19.1-py3-none-any.whl", hash = "sha256:f7a78d15896f45004ccac1c298f3c7121f92f91f6f2bfbd4e4f210f827e6e411"}, + {file = "datasets-2.19.1.tar.gz", hash = "sha256:0df9ef6c5e9138cdb996a07385220109ff203c204245578b69cca905eb151d3a"}, +] + +[package.dependencies] +aiohttp = "*" +dill = ">=0.3.0,<0.3.9" +filelock = "*" +fsspec = {version = ">=2023.1.0,<=2024.3.1", extras = ["http"]} +huggingface-hub = ">=0.21.2" +multiprocess = "*" +numpy = ">=1.17" +packaging = "*" +pandas = "*" +pyarrow = ">=12.0.0" +pyarrow-hotfix = "*" +pyyaml = ">=5.1" +requests = ">=2.19.0" +tqdm = ">=4.62.1" +xxhash = "*" + +[package.extras] +apache-beam = ["apache-beam (>=2.26.0)"] +audio = ["librosa", "soundfile (>=0.12.1)"] +benchmarks = ["tensorflow (==2.12.0)", "torch (==2.0.1)", "transformers (==4.30.1)"] +dev = ["Pillow (>=6.2.1)", "absl-py", "apache-beam (>=2.26.0)", "elasticsearch (<8.0.0)", "faiss-cpu (>=1.6.4)", "jax (>=0.3.14)", "jaxlib (>=0.3.14)", "joblib (<1.3.0)", "joblibspark", "librosa", "lz4", "polars[timezone] (>=0.20.0)", "protobuf (<4.0.0)", "py7zr", "pyspark (>=3.4)", "pytest", "pytest-datadir", "pytest-xdist", "rarfile (>=4.0)", "ruff (>=0.3.0)", "s3fs", "s3fs (>=2021.11.1)", "soundfile (>=0.12.1)", "sqlalchemy", "tensorflow (>=2.6.0)", "tiktoken", "torch", "torch (>=2.0.0)", "transformers", "typing-extensions (>=4.6.1)", "zstandard"] +docs = ["s3fs", "tensorflow (>=2.6.0)", "torch", "transformers"] +jax = ["jax (>=0.3.14)", "jaxlib (>=0.3.14)"] +metrics-tests = ["Werkzeug (>=1.0.1)", "accelerate", "bert-score (>=0.3.6)", "jiwer", "langdetect", "mauve-text", "nltk", "requests-file (>=1.5.1)", "rouge-score", "sacrebleu", "sacremoses", "scikit-learn", "scipy", "sentencepiece", "seqeval", "six (>=1.15.0,<1.16.0)", "spacy (>=3.0.0)", "texttable (>=1.6.3)", "tldextract", "tldextract (>=3.1.0)", "toml (>=0.10.1)", "typer (<0.5.0)"] +quality = ["ruff (>=0.3.0)"] +s3 = ["s3fs"] +tensorflow = ["tensorflow (>=2.6.0)"] +tensorflow-gpu = ["tensorflow (>=2.6.0)"] +tests = ["Pillow (>=6.2.1)", "absl-py", "apache-beam (>=2.26.0)", "elasticsearch (<8.0.0)", "faiss-cpu (>=1.6.4)", "jax (>=0.3.14)", "jaxlib (>=0.3.14)", "joblib (<1.3.0)", "joblibspark", "librosa", "lz4", "polars[timezone] (>=0.20.0)", "protobuf (<4.0.0)", "py7zr", "pyspark (>=3.4)", "pytest", "pytest-datadir", "pytest-xdist", "rarfile (>=4.0)", "s3fs (>=2021.11.1)", "soundfile (>=0.12.1)", "sqlalchemy", "tensorflow (>=2.6.0)", "tiktoken", "torch (>=2.0.0)", "transformers", "typing-extensions (>=4.6.1)", "zstandard"] +torch = ["torch"] +vision = ["Pillow (>=6.2.1)"] + [[package]] name = "decorator" version = "5.1.1" @@ -435,6 +600,130 @@ files = [ {file = "flatbuffers-23.5.26.tar.gz", hash = "sha256:9ea1144cac05ce5d86e2859f431c6cd5e66cd9c78c558317c7955fb8d4c78d89"}, ] +[[package]] +name = "frozenlist" +version = "1.4.1" +description = "A list-like structure which implements collections.abc.MutableSequence" +optional = false +python-versions = ">=3.8" +files = [ + {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac"}, + {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868"}, + {file = "frozenlist-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc"}, + {file = "frozenlist-1.4.1-cp310-cp310-win32.whl", hash = "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1"}, + {file = "frozenlist-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439"}, + {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0"}, + {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49"}, + {file = "frozenlist-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2"}, + {file = "frozenlist-1.4.1-cp311-cp311-win32.whl", hash = "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17"}, + {file = "frozenlist-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825"}, + {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae"}, + {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb"}, + {file = "frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8"}, + {file = "frozenlist-1.4.1-cp312-cp312-win32.whl", hash = "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89"}, + {file = "frozenlist-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5"}, + {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d"}, + {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826"}, + {file = "frozenlist-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7"}, + {file = "frozenlist-1.4.1-cp38-cp38-win32.whl", hash = "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497"}, + {file = "frozenlist-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09"}, + {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e"}, + {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d"}, + {file = "frozenlist-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6"}, + {file = "frozenlist-1.4.1-cp39-cp39-win32.whl", hash = "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932"}, + {file = "frozenlist-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0"}, + {file = "frozenlist-1.4.1-py3-none-any.whl", hash = "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7"}, + {file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"}, +] + +[[package]] +name = "fsspec" +version = "2024.3.1" +description = "File-system specification" +optional = false +python-versions = ">=3.8" +files = [ + {file = "fsspec-2024.3.1-py3-none-any.whl", hash = "sha256:918d18d41bf73f0e2b261824baeb1b124bcf771767e3a26425cd7dec3332f512"}, + {file = "fsspec-2024.3.1.tar.gz", hash = "sha256:f39780e282d7d117ffb42bb96992f8a90795e4d0fb0f661a70ca39fe9c43ded9"}, +] + +[package.dependencies] +aiohttp = {version = "<4.0.0a0 || >4.0.0a0,<4.0.0a1 || >4.0.0a1", optional = true, markers = "extra == \"http\""} + +[package.extras] +abfs = ["adlfs"] +adl = ["adlfs"] +arrow = ["pyarrow (>=1)"] +dask = ["dask", "distributed"] +devel = ["pytest", "pytest-cov"] +dropbox = ["dropbox", "dropboxdrivefs", "requests"] +full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "dask", "distributed", "dropbox", "dropboxdrivefs", "fusepy", "gcsfs", "libarchive-c", "ocifs", "panel", "paramiko", "pyarrow (>=1)", "pygit2", "requests", "s3fs", "smbprotocol", "tqdm"] +fuse = ["fusepy"] +gcs = ["gcsfs"] +git = ["pygit2"] +github = ["requests"] +gs = ["gcsfs"] +gui = ["panel"] +hdfs = ["pyarrow (>=1)"] +http = ["aiohttp (!=4.0.0a0,!=4.0.0a1)"] +libarchive = ["libarchive-c"] +oci = ["ocifs"] +s3 = ["s3fs"] +sftp = ["paramiko"] +smb = ["smbprotocol"] +ssh = ["paramiko"] +tqdm = ["tqdm"] + [[package]] name = "gast" version = "0.5.4" @@ -605,6 +894,40 @@ files = [ [package.dependencies] numpy = ">=1.17.3" +[[package]] +name = "huggingface-hub" +version = "0.23.1" +description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "huggingface_hub-0.23.1-py3-none-any.whl", hash = "sha256:720a5bffd2b1b449deb793da8b0df7a9390a7e238534d5a08c9fbcdecb1dd3cb"}, + {file = "huggingface_hub-0.23.1.tar.gz", hash = "sha256:4f62dbf6ae94f400c6d3419485e52bce510591432a5248a65d0cb72e4d479eb4"}, +] + +[package.dependencies] +filelock = "*" +fsspec = ">=2023.5.0" +packaging = ">=20.9" +pyyaml = ">=5.1" +requests = "*" +tqdm = ">=4.42.1" +typing-extensions = ">=3.7.4.3" + +[package.extras] +all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio", "jedi", "minijinja (>=1.0)", "mypy (==1.5.1)", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.3.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] +cli = ["InquirerPy (==0.3.4)"] +dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio", "jedi", "minijinja (>=1.0)", "mypy (==1.5.1)", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.3.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] +fastai = ["fastai (>=2.4)", "fastcore (>=1.3.27)", "toml"] +hf-transfer = ["hf-transfer (>=0.1.4)"] +inference = ["aiohttp", "minijinja (>=1.0)"] +quality = ["mypy (==1.5.1)", "ruff (>=0.3.0)"] +tensorflow = ["graphviz", "pydot", "tensorflow"] +tensorflow-testing = ["keras (<3.0)", "tensorflow"] +testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio", "jedi", "minijinja (>=1.0)", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "soundfile", "urllib3 (<2.0)"] +torch = ["safetensors", "torch"] +typing = ["types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)"] + [[package]] name = "identify" version = "2.5.30" @@ -623,7 +946,7 @@ license = ["ukkonen"] name = "idna" version = "3.4" description = "Internationalized Domain Names in Applications (IDNA)" -optional = true +optional = false python-versions = ">=3.5" files = [ {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, @@ -889,6 +1212,105 @@ docs = ["sphinx"] gmpy = ["gmpy2 (>=2.1.0a4)"] tests = ["pytest (>=4.6)"] +[[package]] +name = "multidict" +version = "6.0.5" +description = "multidict implementation" +optional = false +python-versions = ">=3.7" +files = [ + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc"}, + {file = "multidict-6.0.5-cp310-cp310-win32.whl", hash = "sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319"}, + {file = "multidict-6.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e"}, + {file = "multidict-6.0.5-cp311-cp311-win32.whl", hash = "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c"}, + {file = "multidict-6.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"}, + {file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"}, + {file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"}, + {file = "multidict-6.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc"}, + {file = "multidict-6.0.5-cp37-cp37m-win32.whl", hash = "sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee"}, + {file = "multidict-6.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44"}, + {file = "multidict-6.0.5-cp38-cp38-win32.whl", hash = "sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241"}, + {file = "multidict-6.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c"}, + {file = "multidict-6.0.5-cp39-cp39-win32.whl", hash = "sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b"}, + {file = "multidict-6.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755"}, + {file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"}, + {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"}, +] + [[package]] name = "multiprocess" version = "0.70.15" @@ -1087,6 +1509,75 @@ files = [ {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, ] +[[package]] +name = "pandas" +version = "2.2.2" +description = "Powerful data structures for data analysis, time series, and statistics" +optional = false +python-versions = ">=3.9" +files = [ + {file = "pandas-2.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:90c6fca2acf139569e74e8781709dccb6fe25940488755716d1d354d6bc58bce"}, + {file = "pandas-2.2.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c7adfc142dac335d8c1e0dcbd37eb8617eac386596eb9e1a1b77791cf2498238"}, + {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4abfe0be0d7221be4f12552995e58723c7422c80a659da13ca382697de830c08"}, + {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8635c16bf3d99040fdf3ca3db669a7250ddf49c55dc4aa8fe0ae0fa8d6dcc1f0"}, + {file = "pandas-2.2.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:40ae1dffb3967a52203105a077415a86044a2bea011b5f321c6aa64b379a3f51"}, + {file = "pandas-2.2.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8e5a0b00e1e56a842f922e7fae8ae4077aee4af0acb5ae3622bd4b4c30aedf99"}, + {file = "pandas-2.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:ddf818e4e6c7c6f4f7c8a12709696d193976b591cc7dc50588d3d1a6b5dc8772"}, + {file = "pandas-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:696039430f7a562b74fa45f540aca068ea85fa34c244d0deee539cb6d70aa288"}, + {file = "pandas-2.2.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8e90497254aacacbc4ea6ae5e7a8cd75629d6ad2b30025a4a8b09aa4faf55151"}, + {file = "pandas-2.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58b84b91b0b9f4bafac2a0ac55002280c094dfc6402402332c0913a59654ab2b"}, + {file = "pandas-2.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2123dc9ad6a814bcdea0f099885276b31b24f7edf40f6cdbc0912672e22eee"}, + {file = "pandas-2.2.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:2925720037f06e89af896c70bca73459d7e6a4be96f9de79e2d440bd499fe0db"}, + {file = "pandas-2.2.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0cace394b6ea70c01ca1595f839cf193df35d1575986e484ad35c4aeae7266c1"}, + {file = "pandas-2.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24"}, + {file = "pandas-2.2.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9dfde2a0ddef507a631dc9dc4af6a9489d5e2e740e226ad426a05cabfbd7c8ef"}, + {file = "pandas-2.2.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e9b79011ff7a0f4b1d6da6a61aa1aa604fb312d6647de5bad20013682d1429ce"}, + {file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cb51fe389360f3b5a4d57dbd2848a5f033350336ca3b340d1c53a1fad33bcad"}, + {file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eee3a87076c0756de40b05c5e9a6069c035ba43e8dd71c379e68cab2c20f16ad"}, + {file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3e374f59e440d4ab45ca2fffde54b81ac3834cf5ae2cdfa69c90bc03bde04d76"}, + {file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:43498c0bdb43d55cb162cdc8c06fac328ccb5d2eabe3cadeb3529ae6f0517c32"}, + {file = "pandas-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:d187d355ecec3629624fccb01d104da7d7f391db0311145817525281e2804d23"}, + {file = "pandas-2.2.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0ca6377b8fca51815f382bd0b697a0814c8bda55115678cbc94c30aacbb6eff2"}, + {file = "pandas-2.2.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9057e6aa78a584bc93a13f0a9bf7e753a5e9770a30b4d758b8d5f2a62a9433cd"}, + {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:001910ad31abc7bf06f49dcc903755d2f7f3a9186c0c040b827e522e9cef0863"}, + {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66b479b0bd07204e37583c191535505410daa8df638fd8e75ae1b383851fe921"}, + {file = "pandas-2.2.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a77e9d1c386196879aa5eb712e77461aaee433e54c68cf253053a73b7e49c33a"}, + {file = "pandas-2.2.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:92fd6b027924a7e178ac202cfbe25e53368db90d56872d20ffae94b96c7acc57"}, + {file = "pandas-2.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:640cef9aa381b60e296db324337a554aeeb883ead99dc8f6c18e81a93942f5f4"}, + {file = "pandas-2.2.2.tar.gz", hash = "sha256:9e79019aba43cb4fda9e4d983f8e88ca0373adbb697ae9c6c43093218de28b54"}, +] + +[package.dependencies] +numpy = {version = ">=1.22.4", markers = "python_version < \"3.11\""} +python-dateutil = ">=2.8.2" +pytz = ">=2020.1" +tzdata = ">=2022.7" + +[package.extras] +all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"] +aws = ["s3fs (>=2022.11.0)"] +clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] +compression = ["zstandard (>=0.19.0)"] +computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] +consortium-standard = ["dataframe-api-compat (>=0.1.7)"] +excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"] +feather = ["pyarrow (>=10.0.1)"] +fss = ["fsspec (>=2022.11.0)"] +gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] +hdf5 = ["tables (>=3.8.0)"] +html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] +mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] +output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] +parquet = ["pyarrow (>=10.0.1)"] +performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] +plot = ["matplotlib (>=3.6.3)"] +postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] +pyarrow = ["pyarrow (>=10.0.1)"] +spss = ["pyreadstat (>=1.2.0)"] +sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] +test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] +xml = ["lxml (>=4.9.2)"] + [[package]] name = "pfl" version = "0.1.0" @@ -1294,6 +1785,65 @@ scipy = "*" [package.extras] extra = ["flake8", "jupyter", "nbconvert", "pandas", "plotly", "pytest", "sympy", "tensorflow-privacy", "tqdm"] +[[package]] +name = "pyarrow" +version = "16.1.0" +description = "Python library for Apache Arrow" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyarrow-16.1.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:17e23b9a65a70cc733d8b738baa6ad3722298fa0c81d88f63ff94bf25eaa77b9"}, + {file = "pyarrow-16.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4740cc41e2ba5d641071d0ab5e9ef9b5e6e8c7611351a5cb7c1d175eaf43674a"}, + {file = "pyarrow-16.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:98100e0268d04e0eec47b73f20b39c45b4006f3c4233719c3848aa27a03c1aef"}, + {file = "pyarrow-16.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f68f409e7b283c085f2da014f9ef81e885d90dcd733bd648cfba3ef265961848"}, + {file = "pyarrow-16.1.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:a8914cd176f448e09746037b0c6b3a9d7688cef451ec5735094055116857580c"}, + {file = "pyarrow-16.1.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:48be160782c0556156d91adbdd5a4a7e719f8d407cb46ae3bb4eaee09b3111bd"}, + {file = "pyarrow-16.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:9cf389d444b0f41d9fe1444b70650fea31e9d52cfcb5f818b7888b91b586efff"}, + {file = "pyarrow-16.1.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:d0ebea336b535b37eee9eee31761813086d33ed06de9ab6fc6aaa0bace7b250c"}, + {file = "pyarrow-16.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2e73cfc4a99e796727919c5541c65bb88b973377501e39b9842ea71401ca6c1c"}, + {file = "pyarrow-16.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf9251264247ecfe93e5f5a0cd43b8ae834f1e61d1abca22da55b20c788417f6"}, + {file = "pyarrow-16.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ddf5aace92d520d3d2a20031d8b0ec27b4395cab9f74e07cc95edf42a5cc0147"}, + {file = "pyarrow-16.1.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:25233642583bf658f629eb230b9bb79d9af4d9f9229890b3c878699c82f7d11e"}, + {file = "pyarrow-16.1.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a33a64576fddfbec0a44112eaf844c20853647ca833e9a647bfae0582b2ff94b"}, + {file = "pyarrow-16.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:185d121b50836379fe012753cf15c4ba9638bda9645183ab36246923875f8d1b"}, + {file = "pyarrow-16.1.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:2e51ca1d6ed7f2e9d5c3c83decf27b0d17bb207a7dea986e8dc3e24f80ff7d6f"}, + {file = "pyarrow-16.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:06ebccb6f8cb7357de85f60d5da50e83507954af617d7b05f48af1621d331c9a"}, + {file = "pyarrow-16.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b04707f1979815f5e49824ce52d1dceb46e2f12909a48a6a753fe7cafbc44a0c"}, + {file = "pyarrow-16.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d32000693deff8dc5df444b032b5985a48592c0697cb6e3071a5d59888714e2"}, + {file = "pyarrow-16.1.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:8785bb10d5d6fd5e15d718ee1d1f914fe768bf8b4d1e5e9bf253de8a26cb1628"}, + {file = "pyarrow-16.1.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:e1369af39587b794873b8a307cc6623a3b1194e69399af0efd05bb202195a5a7"}, + {file = "pyarrow-16.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:febde33305f1498f6df85e8020bca496d0e9ebf2093bab9e0f65e2b4ae2b3444"}, + {file = "pyarrow-16.1.0-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:b5f5705ab977947a43ac83b52ade3b881eb6e95fcc02d76f501d549a210ba77f"}, + {file = "pyarrow-16.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0d27bf89dfc2576f6206e9cd6cf7a107c9c06dc13d53bbc25b0bd4556f19cf5f"}, + {file = "pyarrow-16.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d07de3ee730647a600037bc1d7b7994067ed64d0eba797ac74b2bc77384f4c2"}, + {file = "pyarrow-16.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fbef391b63f708e103df99fbaa3acf9f671d77a183a07546ba2f2c297b361e83"}, + {file = "pyarrow-16.1.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:19741c4dbbbc986d38856ee7ddfdd6a00fc3b0fc2d928795b95410d38bb97d15"}, + {file = "pyarrow-16.1.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:f2c5fb249caa17b94e2b9278b36a05ce03d3180e6da0c4c3b3ce5b2788f30eed"}, + {file = "pyarrow-16.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:e6b6d3cd35fbb93b70ade1336022cc1147b95ec6af7d36906ca7fe432eb09710"}, + {file = "pyarrow-16.1.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:18da9b76a36a954665ccca8aa6bd9f46c1145f79c0bb8f4f244f5f8e799bca55"}, + {file = "pyarrow-16.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:99f7549779b6e434467d2aa43ab2b7224dd9e41bdde486020bae198978c9e05e"}, + {file = "pyarrow-16.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f07fdffe4fd5b15f5ec15c8b64584868d063bc22b86b46c9695624ca3505b7b4"}, + {file = "pyarrow-16.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ddfe389a08ea374972bd4065d5f25d14e36b43ebc22fc75f7b951f24378bf0b5"}, + {file = "pyarrow-16.1.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:3b20bd67c94b3a2ea0a749d2a5712fc845a69cb5d52e78e6449bbd295611f3aa"}, + {file = "pyarrow-16.1.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:ba8ac20693c0bb0bf4b238751d4409e62852004a8cf031c73b0e0962b03e45e3"}, + {file = "pyarrow-16.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:31a1851751433d89a986616015841977e0a188662fcffd1a5677453f1df2de0a"}, + {file = "pyarrow-16.1.0.tar.gz", hash = "sha256:15fbb22ea96d11f0b5768504a3f961edab25eaf4197c341720c4a387f6c60315"}, +] + +[package.dependencies] +numpy = ">=1.16.6" + +[[package]] +name = "pyarrow-hotfix" +version = "0.6" +description = "" +optional = false +python-versions = ">=3.5" +files = [ + {file = "pyarrow_hotfix-0.6-py3-none-any.whl", hash = "sha256:dcc9ae2d220dff0083be6a9aa8e0cdee5182ad358d4931fce825c545e5c89178"}, + {file = "pyarrow_hotfix-0.6.tar.gz", hash = "sha256:79d3e030f7ff890d408a100ac16d6f00b14d44a502d7897cd9fc3e3a534e9945"}, +] + [[package]] name = "pyasn1" version = "0.5.0" @@ -1389,6 +1939,17 @@ files = [ [package.dependencies] six = ">=1.5" +[[package]] +name = "pytz" +version = "2024.1" +description = "World timezone definitions, modern and historical" +optional = false +python-versions = "*" +files = [ + {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, + {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, +] + [[package]] name = "pyyaml" version = "6.0.1" @@ -1452,7 +2013,7 @@ files = [ name = "requests" version = "2.31.0" description = "Python HTTP for Humans." -optional = true +optional = false python-versions = ">=3.7" files = [ {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, @@ -2163,6 +2724,17 @@ files = [ {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"}, ] +[[package]] +name = "tzdata" +version = "2024.1" +description = "Provider of IANA time zone data" +optional = false +python-versions = ">=2" +files = [ + {file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"}, + {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"}, +] + [[package]] name = "urllib3" version = "2.0.6" @@ -2314,6 +2886,123 @@ files = [ {file = "wrapt-1.14.1.tar.gz", hash = "sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d"}, ] +[[package]] +name = "xxhash" +version = "3.4.1" +description = "Python binding for xxHash" +optional = false +python-versions = ">=3.7" +files = [ + {file = "xxhash-3.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:91dbfa55346ad3e18e738742236554531a621042e419b70ad8f3c1d9c7a16e7f"}, + {file = "xxhash-3.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:665a65c2a48a72068fcc4d21721510df5f51f1142541c890491afc80451636d2"}, + {file = "xxhash-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb11628470a6004dc71a09fe90c2f459ff03d611376c1debeec2d648f44cb693"}, + {file = "xxhash-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5bef2a7dc7b4f4beb45a1edbba9b9194c60a43a89598a87f1a0226d183764189"}, + {file = "xxhash-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c0f7b2d547d72c7eda7aa817acf8791f0146b12b9eba1d4432c531fb0352228"}, + {file = "xxhash-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00f2fdef6b41c9db3d2fc0e7f94cb3db86693e5c45d6de09625caad9a469635b"}, + {file = "xxhash-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:23cfd9ca09acaf07a43e5a695143d9a21bf00f5b49b15c07d5388cadf1f9ce11"}, + {file = "xxhash-3.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6a9ff50a3cf88355ca4731682c168049af1ca222d1d2925ef7119c1a78e95b3b"}, + {file = "xxhash-3.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:f1d7c69a1e9ca5faa75546fdd267f214f63f52f12692f9b3a2f6467c9e67d5e7"}, + {file = "xxhash-3.4.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:672b273040d5d5a6864a36287f3514efcd1d4b1b6a7480f294c4b1d1ee1b8de0"}, + {file = "xxhash-3.4.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4178f78d70e88f1c4a89ff1ffe9f43147185930bb962ee3979dba15f2b1cc799"}, + {file = "xxhash-3.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9804b9eb254d4b8cc83ab5a2002128f7d631dd427aa873c8727dba7f1f0d1c2b"}, + {file = "xxhash-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c09c49473212d9c87261d22c74370457cfff5db2ddfc7fd1e35c80c31a8c14ce"}, + {file = "xxhash-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:ebbb1616435b4a194ce3466d7247df23499475c7ed4eb2681a1fa42ff766aff6"}, + {file = "xxhash-3.4.1-cp310-cp310-win_arm64.whl", hash = "sha256:25dc66be3db54f8a2d136f695b00cfe88018e59ccff0f3b8f545869f376a8a46"}, + {file = "xxhash-3.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:58c49083801885273e262c0f5bbeac23e520564b8357fbb18fb94ff09d3d3ea5"}, + {file = "xxhash-3.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b526015a973bfbe81e804a586b703f163861da36d186627e27524f5427b0d520"}, + {file = "xxhash-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36ad4457644c91a966f6fe137d7467636bdc51a6ce10a1d04f365c70d6a16d7e"}, + {file = "xxhash-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:248d3e83d119770f96003271fe41e049dd4ae52da2feb8f832b7a20e791d2920"}, + {file = "xxhash-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2070b6d5bbef5ee031666cf21d4953c16e92c2f8a24a94b5c240f8995ba3b1d0"}, + {file = "xxhash-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2746035f518f0410915e247877f7df43ef3372bf36cfa52cc4bc33e85242641"}, + {file = "xxhash-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a8ba6181514681c2591840d5632fcf7356ab287d4aff1c8dea20f3c78097088"}, + {file = "xxhash-3.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0aac5010869240e95f740de43cd6a05eae180c59edd182ad93bf12ee289484fa"}, + {file = "xxhash-3.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4cb11d8debab1626181633d184b2372aaa09825bde709bf927704ed72765bed1"}, + {file = "xxhash-3.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b29728cff2c12f3d9f1d940528ee83918d803c0567866e062683f300d1d2eff3"}, + {file = "xxhash-3.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:a15cbf3a9c40672523bdb6ea97ff74b443406ba0ab9bca10ceccd9546414bd84"}, + {file = "xxhash-3.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6e66df260fed01ed8ea790c2913271641c58481e807790d9fca8bfd5a3c13844"}, + {file = "xxhash-3.4.1-cp311-cp311-win32.whl", hash = "sha256:e867f68a8f381ea12858e6d67378c05359d3a53a888913b5f7d35fbf68939d5f"}, + {file = "xxhash-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:200a5a3ad9c7c0c02ed1484a1d838b63edcf92ff538770ea07456a3732c577f4"}, + {file = "xxhash-3.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:1d03f1c0d16d24ea032e99f61c552cb2b77d502e545187338bea461fde253583"}, + {file = "xxhash-3.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c4bbba9b182697a52bc0c9f8ec0ba1acb914b4937cd4a877ad78a3b3eeabefb3"}, + {file = "xxhash-3.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9fd28a9da300e64e434cfc96567a8387d9a96e824a9be1452a1e7248b7763b78"}, + {file = "xxhash-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6066d88c9329ab230e18998daec53d819daeee99d003955c8db6fc4971b45ca3"}, + {file = "xxhash-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93805bc3233ad89abf51772f2ed3355097a5dc74e6080de19706fc447da99cd3"}, + {file = "xxhash-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:64da57d5ed586ebb2ecdde1e997fa37c27fe32fe61a656b77fabbc58e6fbff6e"}, + {file = "xxhash-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a97322e9a7440bf3c9805cbaac090358b43f650516486746f7fa482672593df"}, + {file = "xxhash-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bbe750d512982ee7d831838a5dee9e9848f3fb440e4734cca3f298228cc957a6"}, + {file = "xxhash-3.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:fd79d4087727daf4d5b8afe594b37d611ab95dc8e29fe1a7517320794837eb7d"}, + {file = "xxhash-3.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:743612da4071ff9aa4d055f3f111ae5247342931dedb955268954ef7201a71ff"}, + {file = "xxhash-3.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:b41edaf05734092f24f48c0958b3c6cbaaa5b7e024880692078c6b1f8247e2fc"}, + {file = "xxhash-3.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:a90356ead70d715fe64c30cd0969072de1860e56b78adf7c69d954b43e29d9fa"}, + {file = "xxhash-3.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ac56eebb364e44c85e1d9e9cc5f6031d78a34f0092fea7fc80478139369a8b4a"}, + {file = "xxhash-3.4.1-cp312-cp312-win32.whl", hash = "sha256:911035345932a153c427107397c1518f8ce456f93c618dd1c5b54ebb22e73747"}, + {file = "xxhash-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:f31ce76489f8601cc7b8713201ce94b4bd7b7ce90ba3353dccce7e9e1fee71fa"}, + {file = "xxhash-3.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:b5beb1c6a72fdc7584102f42c4d9df232ee018ddf806e8c90906547dfb43b2da"}, + {file = "xxhash-3.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6d42b24d1496deb05dee5a24ed510b16de1d6c866c626c2beb11aebf3be278b9"}, + {file = "xxhash-3.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b685fab18876b14a8f94813fa2ca80cfb5ab6a85d31d5539b7cd749ce9e3624"}, + {file = "xxhash-3.4.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:419ffe34c17ae2df019a4685e8d3934d46b2e0bbe46221ab40b7e04ed9f11137"}, + {file = "xxhash-3.4.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0e041ce5714f95251a88670c114b748bca3bf80cc72400e9f23e6d0d59cf2681"}, + {file = "xxhash-3.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc860d887c5cb2f524899fb8338e1bb3d5789f75fac179101920d9afddef284b"}, + {file = "xxhash-3.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:312eba88ffe0a05e332e3a6f9788b73883752be63f8588a6dc1261a3eaaaf2b2"}, + {file = "xxhash-3.4.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:e01226b6b6a1ffe4e6bd6d08cfcb3ca708b16f02eb06dd44f3c6e53285f03e4f"}, + {file = "xxhash-3.4.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9f3025a0d5d8cf406a9313cd0d5789c77433ba2004b1c75439b67678e5136537"}, + {file = "xxhash-3.4.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:6d3472fd4afef2a567d5f14411d94060099901cd8ce9788b22b8c6f13c606a93"}, + {file = "xxhash-3.4.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:43984c0a92f06cac434ad181f329a1445017c33807b7ae4f033878d860a4b0f2"}, + {file = "xxhash-3.4.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a55e0506fdb09640a82ec4f44171273eeabf6f371a4ec605633adb2837b5d9d5"}, + {file = "xxhash-3.4.1-cp37-cp37m-win32.whl", hash = "sha256:faec30437919555b039a8bdbaba49c013043e8f76c999670aef146d33e05b3a0"}, + {file = "xxhash-3.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:c9e1b646af61f1fc7083bb7b40536be944f1ac67ef5e360bca2d73430186971a"}, + {file = "xxhash-3.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:961d948b7b1c1b6c08484bbce3d489cdf153e4122c3dfb07c2039621243d8795"}, + {file = "xxhash-3.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:719a378930504ab159f7b8e20fa2aa1896cde050011af838af7e7e3518dd82de"}, + {file = "xxhash-3.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74fb5cb9406ccd7c4dd917f16630d2e5e8cbbb02fc2fca4e559b2a47a64f4940"}, + {file = "xxhash-3.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5dab508ac39e0ab988039bc7f962c6ad021acd81fd29145962b068df4148c476"}, + {file = "xxhash-3.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c59f3e46e7daf4c589e8e853d700ef6607afa037bfad32c390175da28127e8c"}, + {file = "xxhash-3.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cc07256eff0795e0f642df74ad096f8c5d23fe66bc138b83970b50fc7f7f6c5"}, + {file = "xxhash-3.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e9f749999ed80f3955a4af0eb18bb43993f04939350b07b8dd2f44edc98ffee9"}, + {file = "xxhash-3.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7688d7c02149a90a3d46d55b341ab7ad1b4a3f767be2357e211b4e893efbaaf6"}, + {file = "xxhash-3.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a8b4977963926f60b0d4f830941c864bed16aa151206c01ad5c531636da5708e"}, + {file = "xxhash-3.4.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:8106d88da330f6535a58a8195aa463ef5281a9aa23b04af1848ff715c4398fb4"}, + {file = "xxhash-3.4.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4c76a77dbd169450b61c06fd2d5d436189fc8ab7c1571d39265d4822da16df22"}, + {file = "xxhash-3.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:11f11357c86d83e53719c592021fd524efa9cf024dc7cb1dfb57bbbd0d8713f2"}, + {file = "xxhash-3.4.1-cp38-cp38-win32.whl", hash = "sha256:0c786a6cd74e8765c6809892a0d45886e7c3dc54de4985b4a5eb8b630f3b8e3b"}, + {file = "xxhash-3.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:aabf37fb8fa27430d50507deeab2ee7b1bcce89910dd10657c38e71fee835594"}, + {file = "xxhash-3.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6127813abc1477f3a83529b6bbcfeddc23162cece76fa69aee8f6a8a97720562"}, + {file = "xxhash-3.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef2e194262f5db16075caea7b3f7f49392242c688412f386d3c7b07c7733a70a"}, + {file = "xxhash-3.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71be94265b6c6590f0018bbf73759d21a41c6bda20409782d8117e76cd0dfa8b"}, + {file = "xxhash-3.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:10e0a619cdd1c0980e25eb04e30fe96cf8f4324758fa497080af9c21a6de573f"}, + {file = "xxhash-3.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa122124d2e3bd36581dd78c0efa5f429f5220313479fb1072858188bc2d5ff1"}, + {file = "xxhash-3.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17032f5a4fea0a074717fe33477cb5ee723a5f428de7563e75af64bfc1b1e10"}, + {file = "xxhash-3.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca7783b20e3e4f3f52f093538895863f21d18598f9a48211ad757680c3bd006f"}, + {file = "xxhash-3.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d77d09a1113899fad5f354a1eb4f0a9afcf58cefff51082c8ad643ff890e30cf"}, + {file = "xxhash-3.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:21287bcdd299fdc3328cc0fbbdeaa46838a1c05391264e51ddb38a3f5b09611f"}, + {file = "xxhash-3.4.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:dfd7a6cc483e20b4ad90224aeb589e64ec0f31e5610ab9957ff4314270b2bf31"}, + {file = "xxhash-3.4.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:543c7fcbc02bbb4840ea9915134e14dc3dc15cbd5a30873a7a5bf66039db97ec"}, + {file = "xxhash-3.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:fe0a98d990e433013f41827b62be9ab43e3cf18e08b1483fcc343bda0d691182"}, + {file = "xxhash-3.4.1-cp39-cp39-win32.whl", hash = "sha256:b9097af00ebf429cc7c0e7d2fdf28384e4e2e91008130ccda8d5ae653db71e54"}, + {file = "xxhash-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:d699b921af0dcde50ab18be76c0d832f803034d80470703700cb7df0fbec2832"}, + {file = "xxhash-3.4.1-cp39-cp39-win_arm64.whl", hash = "sha256:2be491723405e15cc099ade1280133ccfbf6322d2ef568494fb7d07d280e7eee"}, + {file = "xxhash-3.4.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:431625fad7ab5649368c4849d2b49a83dc711b1f20e1f7f04955aab86cd307bc"}, + {file = "xxhash-3.4.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc6dbd5fc3c9886a9e041848508b7fb65fd82f94cc793253990f81617b61fe49"}, + {file = "xxhash-3.4.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3ff8dbd0ec97aec842476cb8ccc3e17dd288cd6ce3c8ef38bff83d6eb927817"}, + {file = "xxhash-3.4.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef73a53fe90558a4096e3256752268a8bdc0322f4692ed928b6cd7ce06ad4fe3"}, + {file = "xxhash-3.4.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:450401f42bbd274b519d3d8dcf3c57166913381a3d2664d6609004685039f9d3"}, + {file = "xxhash-3.4.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a162840cf4de8a7cd8720ff3b4417fbc10001eefdd2d21541a8226bb5556e3bb"}, + {file = "xxhash-3.4.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b736a2a2728ba45017cb67785e03125a79d246462dfa892d023b827007412c52"}, + {file = "xxhash-3.4.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d0ae4c2e7698adef58710d6e7a32ff518b66b98854b1c68e70eee504ad061d8"}, + {file = "xxhash-3.4.1-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6322c4291c3ff174dcd104fae41500e75dad12be6f3085d119c2c8a80956c51"}, + {file = "xxhash-3.4.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:dd59ed668801c3fae282f8f4edadf6dc7784db6d18139b584b6d9677ddde1b6b"}, + {file = "xxhash-3.4.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:92693c487e39523a80474b0394645b393f0ae781d8db3474ccdcead0559ccf45"}, + {file = "xxhash-3.4.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4603a0f642a1e8d7f3ba5c4c25509aca6a9c1cc16f85091004a7028607ead663"}, + {file = "xxhash-3.4.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fa45e8cbfbadb40a920fe9ca40c34b393e0b067082d94006f7f64e70c7490a6"}, + {file = "xxhash-3.4.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:595b252943b3552de491ff51e5bb79660f84f033977f88f6ca1605846637b7c6"}, + {file = "xxhash-3.4.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:562d8b8f783c6af969806aaacf95b6c7b776929ae26c0cd941d54644ea7ef51e"}, + {file = "xxhash-3.4.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:41ddeae47cf2828335d8d991f2d2b03b0bdc89289dc64349d712ff8ce59d0647"}, + {file = "xxhash-3.4.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c44d584afdf3c4dbb3277e32321d1a7b01d6071c1992524b6543025fb8f4206f"}, + {file = "xxhash-3.4.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd7bddb3a5b86213cc3f2c61500c16945a1b80ecd572f3078ddbbe68f9dabdfb"}, + {file = "xxhash-3.4.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9ecb6c987b62437c2f99c01e97caf8d25660bf541fe79a481d05732e5236719c"}, + {file = "xxhash-3.4.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:696b4e18b7023527d5c50ed0626ac0520edac45a50ec7cf3fc265cd08b1f4c03"}, + {file = "xxhash-3.4.1.tar.gz", hash = "sha256:0379d6cf1ff987cd421609a264ce025e74f346e3e145dd106c0cc2e3ec3f99a9"}, +] + [[package]] name = "yapf" version = "0.40.2" @@ -2330,6 +3019,109 @@ importlib-metadata = ">=6.6.0" platformdirs = ">=3.5.1" tomli = ">=2.0.1" +[[package]] +name = "yarl" +version = "1.9.4" +description = "Yet another URL library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e"}, + {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2"}, + {file = "yarl-1.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541"}, + {file = "yarl-1.9.4-cp310-cp310-win32.whl", hash = "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d"}, + {file = "yarl-1.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98"}, + {file = "yarl-1.9.4-cp311-cp311-win32.whl", hash = "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31"}, + {file = "yarl-1.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10"}, + {file = "yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7"}, + {file = "yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984"}, + {file = "yarl-1.9.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434"}, + {file = "yarl-1.9.4-cp37-cp37m-win32.whl", hash = "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749"}, + {file = "yarl-1.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3"}, + {file = "yarl-1.9.4-cp38-cp38-win32.whl", hash = "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece"}, + {file = "yarl-1.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0"}, + {file = "yarl-1.9.4-cp39-cp39-win32.whl", hash = "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575"}, + {file = "yarl-1.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15"}, + {file = "yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad"}, + {file = "yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf"}, +] + +[package.dependencies] +idna = ">=2.0" +multidict = ">=4.0" + [[package]] name = "zipp" version = "3.17.0" @@ -2352,4 +3144,4 @@ tf = ["pfl", "pfl", "tensorflow", "tensorflow_addons"] [metadata] lock-version = "2.0" python-versions = ">=3.10,<3.11" -content-hash = "46ec49debe16e94d0c654c385c8a0386938fd4beac106ffbf6eee551671cff1a" +content-hash = "041acca8627b3f11a5d041a9e99fb06a09dc1109424881d944e33c8be6d38476" diff --git a/benchmarks/pyproject.toml b/benchmarks/pyproject.toml index e928a86..d7cf297 100644 --- a/benchmarks/pyproject.toml +++ b/benchmarks/pyproject.toml @@ -29,6 +29,7 @@ pfl = [ { path = "../", extras = ["pytorch"], markers="extra=='pytorch'", develop = true }, ] pillow = ">=10.2.0" +datasets = "^2.19.1" [tool.poetry.extras] tf = ["pfl", "tensorflow_addons", "tensorflow"] From d73c07bcfe0c0bafb085967200107919f36ca460 Mon Sep 17 00:00:00 2001 From: Mona Chitnis Date: Thu, 30 May 2024 19:05:14 +0200 Subject: [PATCH 14/22] option to lowercase metric keys on serialization. --- pfl/metrics.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/pfl/metrics.py b/pfl/metrics.py index 12cfb3a..0664a06 100644 --- a/pfl/metrics.py +++ b/pfl/metrics.py @@ -575,9 +575,9 @@ def __or__(self, other) -> 'Metrics': return Metrics(itertools.chain(self, other)) def to_simple_dict( - self, - force_serialize_all_metrics: bool = False - ) -> Dict[str, Union[float, int]]: + self, + force_serialize_all_metrics: bool = False, + to_lowercase: bool = False) -> Dict[str, Union[float, int]]: """ Returns a python dictionary of name-value pairs of metrics and their values, e.g. {'Loss': 0.12, 'Accuracy': 0.45}. All metric names are @@ -586,6 +586,12 @@ def to_simple_dict( :param force_serialize_all_metrics: Default to False. Indicate whether or not to include metrics that are marked to be ignored on serialization. + :param to_lowercase: + Default to False. Indicate lowercasing entire metrics key name. + This uniformity is necessary for downstream analytics pipelines + such as Splunk and Delphi. + On the contrary, Proper-casing might be better for readability + in stdout in iPython notebooks and logs. """ def convert(metric_name, weighted_value): @@ -599,9 +605,10 @@ def convert(metric_name, weighted_value): metric_name = str(metric_name) - # Uppercase the first character. - name_uppercase = metric_name[0].upper() + metric_name[1:] - return (name_uppercase, get_overall_value(weighted_value)) + # conditionally Uppercase the first character + modified_name = metric_name.lower( + ) if to_lowercase else metric_name[0].upper() + metric_name[1:] + return (modified_name, get_overall_value(weighted_value)) return dict( convert(*value) for value in self._hash_to_keyvalue.values() From ad9cc5e0b5937621e7c460b4bcb844879a197424 Mon Sep 17 00:00:00 2001 From: fgranqvist Date: Fri, 31 May 2024 11:55:51 +0200 Subject: [PATCH 15/22] Relax Pytorch version to >2,<3 (#69) --- benchmarks/poetry.lock | 8 ++++---- benchmarks/pyproject.toml | 8 ++++---- poetry.lock | 4 ++-- pyproject.toml | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/benchmarks/poetry.lock b/benchmarks/poetry.lock index 83b6ce2..2a27500 100644 --- a/benchmarks/poetry.lock +++ b/benchmarks/poetry.lock @@ -1598,13 +1598,13 @@ tensorflow = {version = ">=2.14,<3.0", optional = true, markers = "sys_platform tensorflow-macos = {version = "^2.14", optional = true, markers = "sys_platform == \"darwin\" and platform_machine == \"arm64\""} tensorflow-probability = {version = "^0.22", optional = true} torch = [ - {version = "2.0.1+cu118", optional = true, markers = "sys_platform == \"linux\""}, - {version = "2.0.1", optional = true, markers = "sys_platform == \"darwin\""}, + {version = ">=2.0.1+cu118,<3.0.0", optional = true, markers = "sys_platform == \"linux\""}, + {version = ">=2.0.1,<3.0.0", optional = true, markers = "sys_platform == \"darwin\""}, ] wheel = "^0.41.2" [package.extras] -pytorch = ["cmake (>=3.27.5,<4.0.0)", "torch (==2.0.1)", "torch (==2.0.1+cu118)"] +pytorch = ["cmake (>=3.27.5,<4.0.0)", "torch (>=2.0.1+cu118,<3.0.0)", "torch (>=2.0.1,<3.0.0)"] tf = ["cmake (>=3.27.5,<4.0.0)", "tensorflow (>=2.14,<3.0)", "tensorflow (>=2.14,<3.0)", "tensorflow-macos (>=2.14,<3.0)", "tensorflow-probability (>=0.22,<0.23)"] trees = ["scikit-learn (>=1.0.2,<2.0.0)", "xgboost (>=1.4.2,<2.0.0)"] @@ -3144,4 +3144,4 @@ tf = ["pfl", "pfl", "tensorflow", "tensorflow_addons"] [metadata] lock-version = "2.0" python-versions = ">=3.10,<3.11" -content-hash = "041acca8627b3f11a5d041a9e99fb06a09dc1109424881d944e33c8be6d38476" +content-hash = "2c4a3e255f8fd453e4048dc5aaf861c95169cc74ad99f2b3e501f43cbdab1833" diff --git a/benchmarks/pyproject.toml b/benchmarks/pyproject.toml index d7cf297..1ed3bc9 100644 --- a/benchmarks/pyproject.toml +++ b/benchmarks/pyproject.toml @@ -16,12 +16,12 @@ tensorflow = { version = "^2.14.0", optional = true } tensorflow_probability = { version = "^0.22", optional = true } tensorflow_addons = { version = ">=0.20.0,<1", optional = true } torch = [ - { version = "2.0.1+cu118", source = "torch_cu118", markers = "sys_platform == 'linux'", optional = true }, - { version = "2.0.1", source = "PyPI", markers = "sys_platform == 'darwin'", optional = true }, + { version = "^2.0.1+cu118", source = "torch_cu118", markers = "sys_platform == 'linux'", optional = true }, + { version = "^2.0.1", source = "PyPI", markers = "sys_platform == 'darwin'", optional = true }, ] torchvision = [ - { version = "0.15.2+cu118", source = "torch_cu118", markers = "sys_platform == 'linux'", optional = true }, - { version = "0.15.2", source = "PyPI", markers = "sys_platform == 'darwin'", optional = true }, + { version = "^0.15.2+cu118", source = "torch_cu118", markers = "sys_platform == 'linux'", optional = true }, + { version = "^0.15.2", source = "PyPI", markers = "sys_platform == 'darwin'", optional = true }, ] # Installs pfl from source. pfl = [ diff --git a/poetry.lock b/poetry.lock index bbd03f3..241f194 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "absl-py" @@ -2661,4 +2661,4 @@ trees = ["scikit-learn", "xgboost"] [metadata] lock-version = "2.0" python-versions = ">=3.10,<3.12" -content-hash = "edf6985c2d793fdc44b121ae23867d960e3d884c089103aa2e53db8a45ddc498" +content-hash = "f9141fce1445e145c3fbe2c3f7bb9ada28750d8a10a819b3c6dd4f3b107f8013" diff --git a/pyproject.toml b/pyproject.toml index 73673fc..bb3b6dc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,8 +23,8 @@ dp-accounting = "^0.4" prv-accountant = "^0.2.0" #### Will be installed only with "pytorch" install extra torch = [ - { version = "2.0.1+cu118", source = "torch_cu118", markers = "sys_platform == 'linux'", optional = true }, - { version = "2.0.1", source = "PyPI", markers = "sys_platform == 'darwin'", optional = true }, + { version = "^2.0.1+cu118", source = "torch_cu118", markers = "sys_platform == 'linux'", optional = true }, + { version = "^2.0.1", source = "PyPI", markers = "sys_platform == 'darwin'", optional = true }, ] #### Will be installed only with "tf" install extra tensorflow = [ From 82bf921bd00e5a595951198f8ed63cacc7fe3c92 Mon Sep 17 00:00:00 2001 From: fgranqvist Date: Fri, 31 May 2024 15:14:49 +0200 Subject: [PATCH 16/22] return local metadata from training (#71) --- pfl/context.py | 13 +++++++++++++ pfl/model/pytorch.py | 10 +++++++--- pfl/model/tensorflow.py | 9 +++++++-- tests/model/test_pytorch_model.py | 16 +++++++++++----- tests/model/test_tensorflow_model.py | 14 ++++++++++++++ 5 files changed, 52 insertions(+), 10 deletions(-) diff --git a/pfl/context.py b/pfl/context.py index a7658bf..c14d7db 100644 --- a/pfl/context.py +++ b/pfl/context.py @@ -7,6 +7,19 @@ from pfl.metrics import Metrics +@dataclass(frozen=True) +class LocalResultMetaData: + """ + Data that is typically returned by a model's local optimization procedure, + e.g. ``PyTorchModel.do_multiple_epochs_of``. Can have useful information + needed by the algorithm. + + :param num_steps: + The number of local steps taken during the local optimization procedure. + """ + num_steps: int + + @dataclass(frozen=True) class UserContext: """ diff --git a/pfl/model/pytorch.py b/pfl/model/pytorch.py index bae6ee4..19c77c9 100644 --- a/pfl/model/pytorch.py +++ b/pfl/model/pytorch.py @@ -6,6 +6,7 @@ import torch +from pfl.context import LocalResultMetaData from pfl.data.dataset import AbstractDatasetType from pfl.exception import CheckpointNotFoundError from pfl.hyperparam import NNEvalHyperParams, NNTrainHyperParams @@ -314,7 +315,8 @@ def _get_local_num_steps(train_params: NNTrainHyperParams, def do_multiple_epochs_of(self, user_dataset: AbstractDatasetType, train_params: NNTrainHyperParams, - train_step_fn: Callable, **kwargs) -> None: + train_step_fn: Callable, + **kwargs) -> LocalResultMetaData: """ Perform multiple epochs of training. The customizable training function that will use a batch of data to update the local @@ -350,13 +352,14 @@ def do_multiple_epochs_of(self, user_dataset: AbstractDatasetType, local_optimizer.zero_grad() # Common arguments used in `train_step_fn` + local_num_steps = self._get_local_num_steps(train_params, + len(user_dataset)) train_step_args = pytorch_ops.PyTorchTrainStepArgs( amp_context=self._amp_context or contextlib.nullcontext(), grad_scaler=self._grad_scaler, max_grad_norm=train_params.local_max_grad_norm, grad_accumulation_state=pytorch_ops.GradAccumulationState( - self._get_local_num_steps(train_params, len(user_dataset)), - train_params.grad_accumulation_steps)) + local_num_steps, train_params.grad_accumulation_steps)) for _ in range(num_epochs): for batch_ix, batch in enumerate( user_dataset.iter(train_params.get('local_batch_size'))): @@ -366,6 +369,7 @@ def do_multiple_epochs_of(self, user_dataset: AbstractDatasetType, train_step_fn(self._model, local_optimizer, batch, user_dataset.train_kwargs, train_step_args, **kwargs) + return LocalResultMetaData(num_steps=local_num_steps) def evaluate(self, dataset: AbstractDatasetType, diff --git a/pfl/model/tensorflow.py b/pfl/model/tensorflow.py index f235c95..6819505 100644 --- a/pfl/model/tensorflow.py +++ b/pfl/model/tensorflow.py @@ -5,8 +5,9 @@ import uuid from typing import Callable, Dict, Optional, Tuple, Union -import tensorflow as tf # type: ignore +import tensorflow as tf +from pfl.context import LocalResultMetaData from pfl.data.dataset import AbstractDatasetType from pfl.exception import CheckpointNotFoundError from pfl.hyperparam import NNEvalHyperParams, NNTrainHyperParams @@ -271,7 +272,8 @@ def _reset_local_optimizer(self, optimizer, learning_rate): def do_multiple_epochs_of(self, user_dataset: AbstractDatasetType, train_params: NNTrainHyperParams, - train_step_fn: Callable, **kwargs) -> None: + train_step_fn: Callable, + **kwargs) -> LocalResultMetaData: """ Perform multiple epochs of training. The customizable training function that will use a batch of data to update the local @@ -308,6 +310,7 @@ def do_multiple_epochs_of(self, user_dataset: AbstractDatasetType, assert train_params.grad_accumulation_steps == 1, ( "Gradient accumulation is not yet supported in TensorFlow") + num_steps_taken = 0 for _ in range(num_epochs): for batch_ix, batch in enumerate( user_dataset.iter(train_params.get('local_batch_size'))): @@ -319,6 +322,8 @@ def do_multiple_epochs_of(self, user_dataset: AbstractDatasetType, *batch, user_dataset.train_kwargs, **kwargs) + num_steps_taken += 1 + return LocalResultMetaData(num_steps=num_steps_taken) def evaluate(self, dataset: AbstractDatasetType, diff --git a/tests/model/test_pytorch_model.py b/tests/model/test_pytorch_model.py index 67066f8..ccd1b69 100644 --- a/tests/model/test_pytorch_model.py +++ b/tests/model/test_pytorch_model.py @@ -71,21 +71,27 @@ def step_side_effect(): def new_local_optimizer(*args, **kwargs): return mock_local_optimizer + local_batch_size = 1 pytorch_model_setup.model.new_local_optimizer = new_local_optimizer - bridges.sgd_bridge().do_sgd( - pytorch_model_setup.model, user_dataset, + # This is same as bridges.sgd_bridge().do_sgd, but we want + # to check the returned metadata as well. + from pfl.internal.bridge.pytorch.sgd import _sgd_train_step + train_metadata = pytorch_model_setup.model.do_multiple_epochs_of( + user_dataset, NNTrainHyperParams( local_learning_rate=local_learning_rate, local_num_epochs=local_num_epochs, - local_batch_size=1, - grad_accumulation_steps=grad_accumulation_steps)) + local_batch_size=local_batch_size, + grad_accumulation_steps=grad_accumulation_steps), + _sgd_train_step) # Check if optimizer step is called correct number of times - total_steps = 2 * local_num_epochs + total_steps = len(user_dataset) / local_batch_size * local_num_epochs expected_optimizer_calls = ( total_steps // grad_accumulation_steps + int(total_steps % grad_accumulation_steps != 0)) assert mock_local_optimizer.step.call_count == expected_optimizer_calls + assert train_metadata.num_steps == total_steps # Check if each step the gradient is accumulated correctly assert len(step_grads) == len(expected_step_grads) diff --git a/tests/model/test_tensorflow_model.py b/tests/model/test_tensorflow_model.py index 1a58248..dd95192 100644 --- a/tests/model/test_tensorflow_model.py +++ b/tests/model/test_tensorflow_model.py @@ -3,6 +3,7 @@ import numpy as np import pytest +from pfl.hyperparam.base import NNTrainHyperParams from pfl.internal.ops import get_tf_major_version from pfl.internal.ops.selector import _internal_reset_framework_module @@ -155,3 +156,16 @@ def test_save_and_load_central_optimizer_impl( Test if central optimizer could be save and restored """ check_save_and_load_central_optimizer_impl(tensorflow_model_setup) + + def test_local_train_metadata(self, tensorflow_model_setup, user_dataset): + model = tensorflow_model_setup.model + from pfl.internal.bridge.tensorflow.sgd import _make_train_step + step_fn = _make_train_step(model) + train_metadata = model.do_multiple_epochs_of( + user_dataset, + NNTrainHyperParams(local_learning_rate=0.1, + local_num_epochs=3, + local_batch_size=1), + step_fn, + max_grad_norm=None) + assert train_metadata.num_steps == 6 From 9f1878d21c23b07bb01cdba102fa3613a718ca09 Mon Sep 17 00:00:00 2001 From: fgranqvist Date: Tue, 4 Jun 2024 12:32:47 +0200 Subject: [PATCH 17/22] Put model to default device before initializing optimizer (#76) --- benchmarks/flair/train.py | 4 +++- benchmarks/image_classification/pytorch/train.py | 4 +++- benchmarks/llm/train.py | 3 +++ benchmarks/lm/pytorch/train.py | 3 +++ benchmarks/poetry.lock | 11 ++++++----- benchmarks/pyproject.toml | 3 +++ 6 files changed, 21 insertions(+), 7 deletions(-) diff --git a/benchmarks/flair/train.py b/benchmarks/flair/train.py index e4580ba..ce935ba 100644 --- a/benchmarks/flair/train.py +++ b/benchmarks/flair/train.py @@ -33,7 +33,7 @@ WandbCallback, ) from pfl.hyperparam import NNEvalHyperParams, NNTrainHyperParams -from pfl.internal.ops.pytorch_ops import to_tensor +from pfl.internal.ops.pytorch_ops import get_default_device, to_tensor from pfl.model.pytorch import PyTorchModel from .argument_parsing import add_flair_training_arguments @@ -96,6 +96,8 @@ def main(): arguments.num_classes = num_classes pytorch_model = get_model_pytorch(arguments) + # Put on GPU if available. + pytorch_model = pytorch_model.to(get_default_device()) variables = [p for p in pytorch_model.parameters() if p.requires_grad] if arguments.central_optimizer == 'adam': diff --git a/benchmarks/image_classification/pytorch/train.py b/benchmarks/image_classification/pytorch/train.py index 0397da0..62bc667 100644 --- a/benchmarks/image_classification/pytorch/train.py +++ b/benchmarks/image_classification/pytorch/train.py @@ -31,7 +31,7 @@ WandbCallback, ) from pfl.hyperparam import NNEvalHyperParams, NNTrainHyperParams -from pfl.internal.ops.pytorch_ops import to_tensor +from pfl.internal.ops.pytorch_ops import get_default_device, to_tensor from pfl.model.pytorch import PyTorchModel from pfl.privacy import CentrallyAppliedPrivacyMechanism @@ -81,6 +81,8 @@ def main(): _) = get_datasets(arguments) pytorch_model = get_model_pytorch(arguments) + # Put on GPU if available. + pytorch_model = pytorch_model.to(get_default_device()) params = [p for p in pytorch_model.parameters() if p.requires_grad] diff --git a/benchmarks/llm/train.py b/benchmarks/llm/train.py index 1e205fe..1321623 100644 --- a/benchmarks/llm/train.py +++ b/benchmarks/llm/train.py @@ -25,6 +25,7 @@ from pfl.aggregate.simulate import SimulatedBackend from pfl.callback import AggregateMetricsToDisk, CentralEvaluationCallback, StopwatchCallback, WandbCallback from pfl.hyperparam import NNEvalHyperParams, NNTrainHyperParams +from pfl.internal.ops import pytorch_ops from pfl.model.pytorch import PyTorchModel @@ -88,6 +89,8 @@ def main(): peft_config = parse_peft_config(arguments) hf_model = wrap_hugging_face_model(hf_model, peft_config, causal_lm_metrics_fn) + # Put on GPU if available. + hf_model = hf_model.to(pytorch_ops.get_default_device()) params = [p for p in hf_model.parameters() if p.requires_grad] if arguments.central_optimizer == 'adam': diff --git a/benchmarks/lm/pytorch/train.py b/benchmarks/lm/pytorch/train.py index e175e96..72ae60b 100644 --- a/benchmarks/lm/pytorch/train.py +++ b/benchmarks/lm/pytorch/train.py @@ -31,6 +31,7 @@ WandbCallback, ) from pfl.hyperparam import NNEvalHyperParams, NNTrainHyperParams +from pfl.internal.ops.pytorch_ops import get_default_device from pfl.model.pytorch import PyTorchModel from pfl.privacy import CentrallyAppliedPrivacyMechanism @@ -88,6 +89,8 @@ def main(): arguments.max_sequence_length = metadata['max_sequence_length'] pytorch_model = get_model_pytorch(arguments) + # Put on GPU if available. + pytorch_model = pytorch_model.to(get_default_device()) params = [p for p in pytorch_model.parameters() if p.requires_grad] if arguments.central_optimizer == 'adam': diff --git a/benchmarks/poetry.lock b/benchmarks/poetry.lock index 2a27500..986c974 100644 --- a/benchmarks/poetry.lock +++ b/benchmarks/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. [[package]] name = "absl-py" @@ -1082,7 +1082,7 @@ testing = ["coverage", "pyyaml"] name = "markupsafe" version = "2.1.3" description = "Safely add untrusted strings to HTML/XML markup." -optional = true +optional = false python-versions = ">=3.7" files = [ {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"}, @@ -1601,6 +1601,7 @@ torch = [ {version = ">=2.0.1+cu118,<3.0.0", optional = true, markers = "sys_platform == \"linux\""}, {version = ">=2.0.1,<3.0.0", optional = true, markers = "sys_platform == \"darwin\""}, ] +werkzeug = ">=3.0.3" wheel = "^0.41.2" [package.extras] @@ -2257,7 +2258,7 @@ requests = ">=2.21.0,<3" setuptools = ">=41.0.0" six = ">1.9" tensorboard-data-server = ">=0.7.0,<0.8.0" -werkzeug = ">=3.0.3" +werkzeug = ">=1.0.1" [[package]] name = "tensorboard-data-server" @@ -2776,7 +2777,7 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess name = "werkzeug" version = "3.0.3" description = "The comprehensive WSGI web application library." -optional = true +optional = false python-versions = ">=3.8" files = [ {file = "werkzeug-3.0.3-py3-none-any.whl", hash = "sha256:fc9645dc43e03e4d630d23143a04a7f947a9a3b5727cd535fdfe155a17cc48c8"}, @@ -3144,4 +3145,4 @@ tf = ["pfl", "pfl", "tensorflow", "tensorflow_addons"] [metadata] lock-version = "2.0" python-versions = ">=3.10,<3.11" -content-hash = "2c4a3e255f8fd453e4048dc5aaf861c95169cc74ad99f2b3e501f43cbdab1833" +content-hash = "0443f4cbcdf7aa09adf1ff78133d37ee5735b4ffc33f43e88b54ff7bd28df52e" diff --git a/benchmarks/pyproject.toml b/benchmarks/pyproject.toml index 1ed3bc9..6ec985a 100644 --- a/benchmarks/pyproject.toml +++ b/benchmarks/pyproject.toml @@ -30,6 +30,9 @@ pfl = [ ] pillow = ">=10.2.0" datasets = "^2.19.1" +# Fixes vulnerability https://github.com/advisories/GHSA-2g68-c3qc-8985 +werkzeug = ">=3.0.3" + [tool.poetry.extras] tf = ["pfl", "tensorflow_addons", "tensorflow"] From cdc991a10e0f600dfdb99abc5b6acd1062374955 Mon Sep 17 00:00:00 2001 From: fgranqvist Date: Tue, 4 Jun 2024 13:17:47 +0200 Subject: [PATCH 18/22] Improved greedy worker scheduling (#73) --- benchmarks/dataset/argument_parsing.py | 16 +++++++ benchmarks/dataset/flair/__init__.py | 13 +++--- benchmarks/dataset/flair/numpy.py | 33 ++++++++++++-- benchmarks/flair/configs/baseline.yaml | 1 + pfl/data/federated_dataset.py | 63 +++++++++++++++++--------- tests/data/test_federated_dataset.py | 2 +- 6 files changed, 97 insertions(+), 31 deletions(-) diff --git a/benchmarks/dataset/argument_parsing.py b/benchmarks/dataset/argument_parsing.py index d72c1fb..3304284 100644 --- a/benchmarks/dataset/argument_parsing.py +++ b/benchmarks/dataset/argument_parsing.py @@ -132,6 +132,20 @@ def add_dataset_arguments( default=100, help='Maximum number of images per user') + parser.add_argument( + '--scheduling_base_weight_multiplier', + type=float, + default=1.0, + help=('Figure 3b in pfl-research paper ' + 'https://arxiv.org/abs/2404.06430 show adding a' + 'base value for each user\'s weight for scheduling ' + 'in distributed simulations speeds up training. ' + 'This parameter adds a ' + 'multiplicative factor of the median user weight ' + 'as base value. 0.0 means no base value added and ' + '~1.0 is the optimal value for the FLAIR benchmark ' + 'according to Figure 3b (can be different for ' + 'other setups).')) elif known_args.dataset == 'alpaca': parser = add_artificial_fed_dataset_arguments(parser) @@ -289,6 +303,8 @@ def get_datasets( data_path=args.data_path, use_fine_grained_labels=args.use_fine_grained_labels, max_num_user_images=args.max_num_user_images, + scheduling_base_weight_multiplier=args. + scheduling_base_weight_multiplier, numpy_to_tensor=numpy_to_tensor) elif args.dataset == 'flair_pytorch': from .flair import make_flair_pytorch_datasets diff --git a/benchmarks/dataset/flair/__init__.py b/benchmarks/dataset/flair/__init__.py index 8f5cb82..b2fa017 100644 --- a/benchmarks/dataset/flair/__init__.py +++ b/benchmarks/dataset/flair/__init__.py @@ -24,7 +24,9 @@ def get_central_data_and_metadata(data_path: str, def make_flair_datasets(data_path: str, use_fine_grained_labels: bool, - max_num_user_images: int, numpy_to_tensor: Callable): + max_num_user_images: int, + scheduling_base_weight_multiplier: float, + numpy_to_tensor: Callable): """ Create a train and val ``FederatedDataset`` as well as a central dataset from the FLAIR dataset. @@ -33,11 +35,10 @@ def make_flair_datasets(data_path: str, use_fine_grained_labels: bool, training_federated_dataset = make_federated_dataset( data_path, 'train', use_fine_grained_labels, max_num_user_images, - numpy_to_tensor) - val_federated_dataset = make_federated_dataset(data_path, 'val', - use_fine_grained_labels, - max_num_user_images, - numpy_to_tensor) + scheduling_base_weight_multiplier, numpy_to_tensor) + val_federated_dataset = make_federated_dataset( + data_path, 'val', use_fine_grained_labels, max_num_user_images, + scheduling_base_weight_multiplier, numpy_to_tensor) central_data, metadata = get_central_data_and_metadata( data_path, use_fine_grained_labels) diff --git a/benchmarks/dataset/flair/numpy.py b/benchmarks/dataset/flair/numpy.py index 7920634..05d65e6 100644 --- a/benchmarks/dataset/flair/numpy.py +++ b/benchmarks/dataset/flair/numpy.py @@ -1,5 +1,6 @@ # Copyright © 2023-2024 Apple Inc. +import logging from typing import Callable import h5py @@ -11,12 +12,15 @@ from .common import get_label_mapping, get_multi_hot_targets, get_user_num_images +logger = logging.getLogger(name=__name__) + def make_federated_dataset( hdf5_path: str, partition: str, use_fine_grained_labels: bool, max_num_user_images: int, + scheduling_base_weight_multiplier: float = 1., numpy_to_tensor: Callable = lambda x: x) -> FederatedDataset: """ Create federated dataset from the flair dataset, to use in simulations. @@ -31,14 +35,37 @@ def make_federated_dataset( Whether to use fine-grained label taxonomy. :param max_num_user_images: Maximum number of images each user can have. + :param scheduling_base_weight_multiplier: + The number of datapoints per user is used as a weight to greedily + schedule users in distributed simulations. Figure 3b in pfl-research + paper https://arxiv.org/abs/2404.06430 show adding a base value for + each user\'s weight for scheduling in distributed simulations + speeds up training. + This parameter adds a multiplicative factor of the median user weight + as base value. 0.0 means no base value added and ~1.0 is the optimal + value for the FLAIR benchmark according to Figure 3b (can be different + for other setups. :param numpy_to_tensor: Function that convert numpy array to ML framework tensor. :return: Federated dataset from the HDF5 data file. """ num_classes = len(get_label_mapping(hdf5_path, use_fine_grained_labels)) - user_num_images = get_user_num_images(hdf5_path, partition) - user_ids = sorted(user_num_images.keys()) + user_id_to_weight = { + k: min(v, max_num_user_images) + for k, v in get_user_num_images(hdf5_path, partition).items() + } + median_datapoints = np.median(list(user_id_to_weight.values())) + base_value = scheduling_base_weight_multiplier * median_datapoints + logger.info( + f'User mean datapoints: {np.mean(list(user_id_to_weight.values()))}, median datapoints: {median_datapoints}, base_value: {base_value}' + ) + user_id_to_weight = { + k: v + base_value + for k, v in user_id_to_weight.items() + } + + user_ids = sorted(user_id_to_weight.keys()) sampler = get_user_sampler('random', user_ids) def make_dataset_fn(user_id): @@ -59,7 +86,7 @@ def make_dataset_fn(user_id): return FederatedDataset(make_dataset_fn, sampler, - user_id_to_weight=user_num_images) + user_id_to_weight=user_id_to_weight) def make_artificial_federated_dataset( diff --git a/benchmarks/flair/configs/baseline.yaml b/benchmarks/flair/configs/baseline.yaml index dbf46b4..7a91c9a 100644 --- a/benchmarks/flair/configs/baseline.yaml +++ b/benchmarks/flair/configs/baseline.yaml @@ -25,6 +25,7 @@ evaluation_frequency: 20 central_eval_batch_size: 512 pretrained: true #save_model_path: './checkpoints' +scheduling_base_weight_multiplier: 1.0 # Simulate I.I.D. data by ignoring user ID # - dataset: flair_iid diff --git a/pfl/data/federated_dataset.py b/pfl/data/federated_dataset.py index 15dd394..c7cb82e 100644 --- a/pfl/data/federated_dataset.py +++ b/pfl/data/federated_dataset.py @@ -49,8 +49,9 @@ def _distributed_sampler(sampler, get_seed, rank, world_size): yield users_all_workers[rank], seeds_all_workers[rank] -def _sorted_cohort_subprocess(q_send, q_request, sampler, seed_sampler, rank, - world_size, user_id_to_weight): +def _sorted_cohort_subprocess(q_send, q_request, q_send_num, sampler, + seed_sampler, rank, world_size, + user_id_to_weight): cache = [] cohort_size = None cache_size = _INITIAL_USER_SAMPLES_CACHE_SIZE @@ -68,15 +69,26 @@ def _sorted_cohort_subprocess(q_send, q_request, sampler, seed_sampler, rank, if cohort_size is not None and len(cache) > cohort_size: # Perform request cohort_samples = cache[:cohort_size] - if user_id_to_weight is not None: - cohort_samples = sorted( - cohort_samples, - key=lambda tup: user_id_to_weight[tup[0]], - reverse=True) - q_send.put(cohort_samples) - + cohort_samples = sorted(cohort_samples, + key=lambda tup: user_id_to_weight[tup[0]], + reverse=True) + + # This optimization procedure should be deterministic + # across all worker processes. + worker_samples = [[] for _ in range(world_size)] + worker_total_weight = np.zeros(world_size) + for sample in cohort_samples: + # Add user to worker with the minimum load. + min_worker_index = np.argmin(worker_total_weight) + worker_samples[min_worker_index].append(sample) + worker_total_weight[min_worker_index] += user_id_to_weight[ + sample[0]] + + q_send_num.put(len(worker_samples[rank])) + q_send.put(worker_samples[rank]) cache = cache[cohort_size:] cohort_size = None + # Check if the queue is full if len(cache) < cache_size: # Generate multiple samples at a time @@ -119,21 +131,22 @@ def __init__(self, sampler, seed_sampler, rank, world_size, self._samples_q = mp.Queue() self._cohort_request_q = mp.Queue() + self._cohort_num_response_q = mp.Queue() self._sample_process = mp.Process( target=_sorted_cohort_subprocess, - args=(self._samples_q, self._cohort_request_q, sampler, - seed_sampler, rank, world_size, user_id_to_weight)) + args=(self._samples_q, self._cohort_request_q, + self._cohort_num_response_q, sampler, seed_sampler, rank, + world_size, user_id_to_weight)) self._sample_process.start() atexit.register(self.__del__) def __iter__(self): while True: - for i, sample in enumerate(self._samples_q.get()): - if i % self._world_size == self._rank: - yield sample + yield from self._samples_q.get() def set_cohort_size(self, cohort_size): self._cohort_request_q.put(cohort_size) + return self._cohort_num_response_q.get() def __del__(self): self._samples_q.close() @@ -353,10 +366,12 @@ def __init__(self, def _try_set_cohort_size(self, cohort_size: int): # Doesn't need a cohort to be set, can continue. + worker_cohort_size = None with contextlib.suppress(AttributeError): # pytype: disable=attribute-error - self._sample_fn.set_cohort_size(cohort_size) + worker_cohort_size = self._sample_fn.set_cohort_size(cohort_size) # pytype: enable=attribute-error + return worker_cohort_size def __next__(self) -> Tuple[AbstractDataset, int]: # Each worker will make a dataset with its own sampled user. @@ -429,12 +444,18 @@ def from_slices_with_dirichlet_class_distribution( def get_cohort(self, cohort_size: int) -> Iterable[Tuple[AbstractDataset, int]]: - self._try_set_cohort_size(cohort_size) - for i in range(cohort_size): - if (i % get_ops().distributed.world_size - ) == get_ops().distributed.global_rank: - user_ids, seed = next(self.sampler) - yield self.make_dataset_fn(user_ids), seed + # Set next cohort size for sampler if possible + worker_cohort_size = self._try_set_cohort_size(cohort_size) + if worker_cohort_size is None: + for i in range(cohort_size): + if (i % get_ops().distributed.world_size + ) == get_ops().distributed.global_rank: + user_id, seed = next(self.sampler) + yield self.make_dataset_fn(user_id), seed + else: + for _ in range(worker_cohort_size): + user_id, seed = next(self.sampler) + yield self.make_dataset_fn(user_id), seed class FederatedDatasetMixture(FederatedDatasetBase): diff --git a/tests/data/test_federated_dataset.py b/tests/data/test_federated_dataset.py index 20331e7..0818bb1 100644 --- a/tests/data/test_federated_dataset.py +++ b/tests/data/test_federated_dataset.py @@ -266,7 +266,7 @@ def test_3_workers(self, mock_get_ops, federated_dataset_mixture, @pytest.fixture def user_id_to_weight(request): if hasattr(request, 'param') and request.param: - return {i: i for i in range(100)} + return {i: i + 1 for i in range(100)} else: return None From 2173c3b381e70ee40a6b8f2d07352c2c7f5c9975 Mon Sep 17 00:00:00 2001 From: ac554 <47990575+ac554@users.noreply.github.com> Date: Tue, 4 Jun 2024 12:18:33 +0100 Subject: [PATCH 19/22] Code to accompany MDM paper (#75) --- publications/mdm/README.md | 26 + publications/mdm/mdm/__init__.py | 4 + publications/mdm/mdm/algorithm.py | 290 ++++++++++ publications/mdm/mdm/bridge/base.py | 46 ++ publications/mdm/mdm/bridge/factory.py | 104 ++++ .../mdm/mdm/bridge/pytorch/__init__.py | 0 .../mdm/mdm/bridge/pytorch/polya_mixture.py | 102 ++++ publications/mdm/mdm/init_algorithm.py | 266 +++++++++ publications/mdm/mdm/model.py | 137 +++++ publications/mdm/mdm_paper/README.md | 3 + publications/mdm/mdm_paper/__init__.py | 0 .../notebooks/MSE_cifar10_experiments.ipynb | 501 +++++++++++++++++ .../notebooks/cifar10_visualisations.ipynb | 241 ++++++++ .../notebooks/femnist_visualisations.ipynb | 516 ++++++++++++++++++ .../mdm/mdm_paper/training/__init__.py | 0 publications/mdm/mdm_paper/training/mle.py | 102 ++++ publications/mdm/mdm_paper/training/train.py | 149 +++++ .../mdm/mdm_paper/training/train_femnist.py | 101 ++++ .../training/train_femnist_rebuttal.py | 117 ++++ publications/mdm/mdm_utils/__init__.py | 0 .../mdm/mdm_utils/datasets/__init__.py | 3 + .../mdm/mdm_utils/datasets/cifar10_dataset.py | 158 ++++++ .../mdm/mdm_utils/datasets/femnist_dataset.py | 324 +++++++++++ .../mdm/mdm_utils/datasets/mixture_dataset.py | 154 ++++++ .../mdm/mdm_utils/datasets/sampler.py | 123 +++++ publications/mdm/mdm_utils/models/__init__.py | 1 + .../mdm/mdm_utils/models/argument_parsing.py | 188 +++++++ .../mdm/mdm_utils/models/pytorch/__init__.py | 6 + .../mdm/mdm_utils/models/pytorch/cnn.py | 226 ++++++++ .../mdm/mdm_utils/models/pytorch/dnn.py | 51 ++ .../mdm/mdm_utils/models/pytorch/layer.py | 88 +++ .../mdm/mdm_utils/models/pytorch/metrics.py | 54 ++ .../models/pytorch/module_modification.py | 131 +++++ .../mdm/mdm_utils/models/pytorch_model.py | 105 ++++ publications/mdm/mdm_utils/utils/__init__.py | 5 + .../mdm/mdm_utils/utils/argument_parsing.py | 154 ++++++ publications/mdm/mdm_utils/utils/tools.py | 55 ++ .../mdm/mdm_utils/utils/visualize_results.py | 71 +++ .../run_cifar10_mse_alpha_phi_experiments.sh | 70 +++ publications/mdm/run_femnist.sh | 34 ++ 40 files changed, 4706 insertions(+) create mode 100644 publications/mdm/README.md create mode 100644 publications/mdm/mdm/__init__.py create mode 100644 publications/mdm/mdm/algorithm.py create mode 100644 publications/mdm/mdm/bridge/base.py create mode 100644 publications/mdm/mdm/bridge/factory.py create mode 100644 publications/mdm/mdm/bridge/pytorch/__init__.py create mode 100644 publications/mdm/mdm/bridge/pytorch/polya_mixture.py create mode 100644 publications/mdm/mdm/init_algorithm.py create mode 100644 publications/mdm/mdm/model.py create mode 100644 publications/mdm/mdm_paper/README.md create mode 100644 publications/mdm/mdm_paper/__init__.py create mode 100644 publications/mdm/mdm_paper/notebooks/MSE_cifar10_experiments.ipynb create mode 100644 publications/mdm/mdm_paper/notebooks/cifar10_visualisations.ipynb create mode 100644 publications/mdm/mdm_paper/notebooks/femnist_visualisations.ipynb create mode 100644 publications/mdm/mdm_paper/training/__init__.py create mode 100644 publications/mdm/mdm_paper/training/mle.py create mode 100644 publications/mdm/mdm_paper/training/train.py create mode 100644 publications/mdm/mdm_paper/training/train_femnist.py create mode 100644 publications/mdm/mdm_paper/training/train_femnist_rebuttal.py create mode 100644 publications/mdm/mdm_utils/__init__.py create mode 100644 publications/mdm/mdm_utils/datasets/__init__.py create mode 100644 publications/mdm/mdm_utils/datasets/cifar10_dataset.py create mode 100644 publications/mdm/mdm_utils/datasets/femnist_dataset.py create mode 100644 publications/mdm/mdm_utils/datasets/mixture_dataset.py create mode 100644 publications/mdm/mdm_utils/datasets/sampler.py create mode 100644 publications/mdm/mdm_utils/models/__init__.py create mode 100644 publications/mdm/mdm_utils/models/argument_parsing.py create mode 100644 publications/mdm/mdm_utils/models/pytorch/__init__.py create mode 100644 publications/mdm/mdm_utils/models/pytorch/cnn.py create mode 100644 publications/mdm/mdm_utils/models/pytorch/dnn.py create mode 100644 publications/mdm/mdm_utils/models/pytorch/layer.py create mode 100644 publications/mdm/mdm_utils/models/pytorch/metrics.py create mode 100644 publications/mdm/mdm_utils/models/pytorch/module_modification.py create mode 100644 publications/mdm/mdm_utils/models/pytorch_model.py create mode 100644 publications/mdm/mdm_utils/utils/__init__.py create mode 100644 publications/mdm/mdm_utils/utils/argument_parsing.py create mode 100644 publications/mdm/mdm_utils/utils/tools.py create mode 100644 publications/mdm/mdm_utils/utils/visualize_results.py create mode 100755 publications/mdm/run_cifar10_mse_alpha_phi_experiments.sh create mode 100755 publications/mdm/run_femnist.sh diff --git a/publications/mdm/README.md b/publications/mdm/README.md new file mode 100644 index 0000000..38e2a26 --- /dev/null +++ b/publications/mdm/README.md @@ -0,0 +1,26 @@ +# Improved Modelling of Federated Datasets using Mixtures-of-Dirichlet-Multinomials (MDMs) + +This software project accompanies the research paper, "Improved Modelling of Federated Datasets using Mixtures-of-Dirichlet-Multinomials". + +Mixture-of-Dirichlet-Multinomial (MDM) models allow one to model heterogeneous federated datasets, and such MDM models can be trained with privacy preserving federated learning. + +## Documentation + +This repo contains the code to run all experiments in the paper "Improved Modelling of Federated Datasets using Mixtures-of-Dirichlet-Multinomials", and to process the results to produce the plots shown in the paper are available in the `mdm-paper` directory on this fork of the `pfl-research` framework, for running simulations using Private Federated Learning. + +The structure of the `mdm` repo is: +- `mdm/`: This directory contains the algorithmic code, implementing the MDM model algorithm in the pfl-research framework. +- `mdm_paper/`: This directory contains subdirectories: `training/` contains the python training scripts to run inference of MDM parameters on the CIFAR-10 and FEMNIST datasets; `notebooks/` contains Jupyter notebooks used to visualise results and create plots shown in the paper. +- `mdm_utils/`: This directory contains utilities to help with training setup, e.g. argument parsers, dataset helper functions, etc. + + +## Setup for experiments + +It is assumed you first follow the default setup for benchmarks in the pfl-research framework. The details to follow for this default setup are available [here](https://github.com/apple/pfl-research/blob/develop/benchmarks/README.md). + +It is next assumed that you have the FEMNIST and CIFAR-10 datasets downloaded locally in directories data/femnist/ and data/cifar10/ respectively. To download the data and ensure it is preprocessed correctly, please follow the pfl-research instructions for data setup [here](https://github.com/apple/pfl-research/tree/develop/benchmarks/image_classification). + +## Running experiments in paper +To run MDM parameter inference on CIFAR-10: ` bash publications/mdm/run_cifar10_mse_alpha_phi_experiments.sh`. + +To run MDM parameter inference on FEMNIST, where the users are split between the server-side dataset and the live dataset: `bash publications/mdm/run_femnist.sh`. diff --git a/publications/mdm/mdm/__init__.py b/publications/mdm/mdm/__init__.py new file mode 100644 index 0000000..7ae9963 --- /dev/null +++ b/publications/mdm/mdm/__init__.py @@ -0,0 +1,4 @@ +from .model import (MDMModelHyperParams, MDMModel) +from .init_algorithm import (MDMInitializationAlgorithmParams, + MDMInitializationAlgorithm) +from .algorithm import (MDMAlgorithmParams, MDMAlgorithm) diff --git a/publications/mdm/mdm/algorithm.py b/publications/mdm/mdm/algorithm.py new file mode 100644 index 0000000..0f3be49 --- /dev/null +++ b/publications/mdm/mdm/algorithm.py @@ -0,0 +1,290 @@ +# -*- coding: utf-8 -*- + +from dataclasses import dataclass +from typing import Tuple, Optional, TypeVar, Callable, Union + +import numpy as np +import torch + +from pfl.common_types import Population +from pfl.data.dataset import AbstractDataset +from pfl.hyperparam import get_param_value +from pfl.metrics import Metrics +from pfl.context import CentralContext +from pfl.stats import MappedVectorStatistics +from pfl.algorithm.base import FederatedAlgorithm, AlgorithmHyperParams +from pfl.data.dataset import AbstractDatasetType + +from publications.mdm.mdm.model import MDMModelType, MDMModelHyperParamsType +from publications.mdm.mdm.bridge.factory import FrameworkBridgeFactory as bridges + + +@dataclass(frozen=True) +class MDMAlgorithmParams(AlgorithmHyperParams): + """ + Parameters for initialization algorithm of Polya Mixture. + + :param central_num_iterations: + Number of iterations of training + :param extract_categories_fn: + Function to extract categories from user dataset. By default return + labels of user dataset. + """ + cohort_size: int + num_samples_mixture_bins: np.ndarray + central_num_iterations: int = 1 + extract_categories_fn: Callable[[AbstractDataset], Union[ + np.ndarray, + torch.Tensor]] = lambda user_dataset: user_dataset.raw_data[1] + + +MDMAlgorithmParamsType = TypeVar('MDMAlgorithmParamsType', + bound=MDMAlgorithmParams) + + +class MDMAlgorithm(FederatedAlgorithm[MDMAlgorithmParamsType, + MDMModelHyperParamsType, MDMModelType, + MappedVectorStatistics, AbstractDatasetType]): + """ + Federated algorithm class for learning mixture of Polya + (Dirichlet-Multinomial) distribution using MLE algorithm. + """ + + def get_next_central_contexts( + self, + model: MDMModelType, + iteration: int, + algorithm_params: MDMAlgorithmParamsType, + model_train_params: MDMModelHyperParamsType, + model_eval_params: Optional[MDMModelHyperParamsType] = None, + ) -> Tuple[Optional[Tuple[CentralContext[MDMAlgorithmParamsType, + MDMModelHyperParamsType], ...]], + MDMModelType, Metrics]: + + if (model.alphas <= 0).any(): + raise AssertionError( + f'Cannot have zero elements in alphas: {model.alphas}') + if (model.num_samples_distribution <= 0).any(): + raise AssertionError( + f'Cannot have zero elements in num_samples_distribution: {model.num_samples_distribution}' + ) + if (model.phi <= 0).any(): + raise AssertionError( + f'Cannot have zero elements in phi: {model.phi}') + + if iteration == algorithm_params.central_num_iterations: + return None, model, Metrics() + + configs = [ + CentralContext( + current_central_iteration=iteration, + do_evaluation=False, + cohort_size=get_param_value(algorithm_params.cohort_size), + population=Population.TRAIN, + model_train_params=model_train_params.static_clone(), + model_eval_params=None, + algorithm_params=algorithm_params.static_clone(), + seed=self._get_seed()) + ] + return tuple(configs), model, Metrics() + + def simulate_one_user( + self, + model: MDMModelType, + user_dataset: AbstractDataset, + central_context: CentralContext[MDMAlgorithmParamsType, + MDMModelHyperParamsType], + ) -> Tuple[Optional[MappedVectorStatistics], Metrics]: + """ + Encode user's dataset into statistics with a `MDMModel`. + + central_context.algorithm_params.extract_categories_fn is a callable + used to extract the categories tracked with the Polya-Mixture model. + """ + + if (model.alphas <= 0).any(): + raise AssertionError( + '> 0 alpha params have zero values, which would cause algorithm to fail. Cannot proceed.' + ) + + if (model.phi <= 0).any(): + raise AssertionError( + '> 0 phi params have zero values, which would cause algorithm to fail. Cannot proceed.' + ) + + if (model.num_samples_distribution <= 0).any(): + raise AssertionError( + '> 0 num_samples_distribution have zero values, which would cause algorithm to fail. Cannot proceed.' + ) + + # Get counts + categories = central_context.algorithm_params.extract_categories_fn( + user_dataset) + #num_user_samples = len(categories) + category_counts = bridges.polya_mixture_bridge( + ).category_counts_polya_mixture( + categories, central_context.model_train_params.num_categories) + + e = torch.zeros( + (central_context.model_train_params.num_components, + central_context.algorithm_params.num_samples_mixture_bins.shape[1] + )) + + num_samples = len(categories) + + # TODO make more flexible so it supports if each mixture has different bin edges. + # TODO here I just assume that all components have the same bin edges, which is why I index 0 in central_context.algorithm_params.num_samples_mixture_bins[0] + selected_bin = -1 + for i, bin_edge in enumerate( + central_context.algorithm_params.num_samples_mixture_bins[0]): + bin_edge = int(bin_edge) + if num_samples <= bin_edge: + selected_bin = i + break + + user_num_samples_distribution = model.num_samples_distribution[:, + selected_bin] + + # E Step - compute posterior probability of each component + posterior_probabilities = bridges.polya_mixture_bridge( + ).expectation_step(model.phi, model.alphas, + user_num_samples_distribution, category_counts) + + # M Step - compute client update to alphas for fixed point update + # which will be applied by the model in process_aggregated_statistics. + # Note the numerator and denominator are both weighted by w (the + # probability vector giving the client belonging to each component). + (numerator, + denominator) = bridges.polya_mixture_bridge().maximization_step( + posterior_probabilities, category_counts, model.alphas) + + e[:, selected_bin] = posterior_probabilities.view(-1) + + statistics = MappedVectorStatistics() + statistics['posterior_probabilities'] = posterior_probabilities.to('cpu') + statistics['numerator'] = numerator.to('cpu') + statistics['denominator'] = denominator.to('cpu') + statistics['num_samples_distribution'] = e.to('cpu') + + return statistics, Metrics() + + def process_aggregated_statistics( + self, central_context: CentralContext[MDMAlgorithmParamsType, + MDMModelHyperParamsType], + aggregate_metrics: Metrics, model: MDMModelType, + statistics: MappedVectorStatistics + ) -> Tuple[MDMModelType, Metrics]: + + # The new weight of a mixture component is the mean client weight of + # that component + + # TODO prevent any <= 0 values in posterior_probabilities, numerator and denominator and num_samples_distribution + posterior_probabilities = statistics['posterior_probabilities'] + numerator = statistics['numerator'] + denominator = statistics['denominator'] + num_samples_distribution = statistics['num_samples_distribution'] + + posterior_probabilities = torch.clamp(posterior_probabilities, min=0) + numerator = torch.clamp(numerator, min=0) + denominator = torch.clamp(denominator, min=0) + num_samples_distribution = torch.clamp(num_samples_distribution, min=0) + + print('\n\nProcess aggregated statistics') + print('numerator', numerator.shape, numerator) + print('denominator', denominator.shape, denominator) + print('num_samples_distribution', num_samples_distribution.shape, + num_samples_distribution) + + def prevent_zero(tensor, min_val=0, mass_reallocation_percentage=0.01): + if not (tensor == 0).any(): + print('no zeros in tensor') + return tensor + num_zero = torch.sum(tensor <= min_val, dim=1, keepdim=True) + total_mass = torch.sum(tensor, dim=1, keepdim=True) + if total_mass > 0: + extra_mass = total_mass * mass_reallocation_percentage / num_zero + tensor = torch.where(tensor > min_val, tensor, + extra_mass.expand_as(tensor)) + tensor = tensor / torch.sum(tensor, dim=1, + keepdim=True) * total_mass + return tensor + # no probability mass - instead force set all zero elements to 0.02 + return torch.ones_like(tensor) * 0.02 + + if (posterior_probabilities == 0).any(): + num_zero = torch.sum(posterior_probabilities == 0) + total_mass = torch.sum(posterior_probabilities) + extra_mass = total_mass * 0.01 / num_zero + posterior_probabilities = torch.where(posterior_probabilities > 0, + posterior_probabilities, + extra_mass) + posterior_probabilities = posterior_probabilities / torch.sum( + posterior_probabilities) * total_mass + assert total_mass == torch.sum(posterior_probabilities) + + if (numerator == 0).any(): + numerator = prevent_zero(numerator, min_val=1) + if (numerator == 0).any(): + raise AssertionError('prevent zero did not work on numerator') + + if (denominator == 0).any(): + denominator = prevent_zero(denominator) + if (denominator == 0).any(): + raise AssertionError( + 'prevent zero did not work on denominator') + + if (num_samples_distribution == 0).any(): + modified_num_samples_distribution = prevent_zero( + num_samples_distribution, min_val=0.001) + mass_reallocation_percentage = 0.01 + while (modified_num_samples_distribution == 0).any(): + mass_reallocation_percentage *= 2 + if mass_reallocation_percentage >= 1: + raise AssertionError( + f'prevent zero did not work on num_samples_distribution: {num_samples_distribution}' + ) + modified_num_samples_distribution = prevent_zero( + num_samples_distribution, + min_val=0.001, + mass_reallocation_percentage=mass_reallocation_percentage) + num_samples_distribution = modified_num_samples_distribution + + phi = posterior_probabilities / central_context.algorithm_params.cohort_size + + # Each alpha is updated using the fixed point update, note that the + # numerator and denominator are weighted by each client before being + # aggregated, so this is a weighted update. + + if (model.alphas == 0).any(): + raise AssertionError('model.alphas had zeros before update') + alphas = bridges.polya_mixture_bridge().update_alpha( + model.alphas, numerator, denominator) + if (alphas == 0).any(): + raise AssertionError('alphas has zeros after update') + + num_samples_distribution = num_samples_distribution / posterior_probabilities.reshape( + -1, 1).expand_as(num_samples_distribution) + + # renormalise num_samples_distribution again on server, since DP might mean that statistics don't sum to 1 per mixture component + num_samples_distribution = num_samples_distribution / num_samples_distribution.sum( + dim=1, keepdim=True) + if (num_samples_distribution == 0).any(): + num_samples_distribution = prevent_zero(num_samples_distribution, + min_val=0.001) + + # renormalise phi + phi = phi / phi.sum() + + model, metrics = model.apply_model_update( + MappedVectorStatistics({ + 'alphas': + alphas, + 'phi': + phi, + 'num_samples_distribution': + num_samples_distribution + })) + metrics['alphas'] = alphas + metrics['phi'] = phi + metrics['num_samples_distribution'] = num_samples_distribution + return model, metrics diff --git a/publications/mdm/mdm/bridge/base.py b/publications/mdm/mdm/bridge/base.py new file mode 100644 index 0000000..f63e763 --- /dev/null +++ b/publications/mdm/mdm/bridge/base.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- + +from typing import Any, Dict, Protocol, TypeVar, Tuple + + +Tensor = TypeVar('Tensor') + + +class PolyaMixtureFrameworkBridge(Protocol[Tensor]): + """ + Interface for Polya-Mixture algorithm for a particular Deep Learning + framework. + """ + + @staticmethod + def category_counts_polya_mixture(categories: Tensor, + num_categories: int) -> Tensor: + """ + """ + pass + + @staticmethod + def category_probabilities_polya_mixture_initialization( + num_components, num_categories, component, categories) -> Tensor: + """ + """ + pass + + @staticmethod + def expectation_step(phi, alphas, category_counts) -> Tensor: + """ + """ + pass + + @staticmethod + def maximization_step(posterior_probabilities, category_counts, + alphas) -> Tensor: + """ + """ + pass + + @staticmethod + def update_alpha(alphas, numerator, denominator) -> Tensor: + """ + """ + pass diff --git a/publications/mdm/mdm/bridge/factory.py b/publications/mdm/mdm/bridge/factory.py new file mode 100644 index 0000000..c395e26 --- /dev/null +++ b/publications/mdm/mdm/bridge/factory.py @@ -0,0 +1,104 @@ +# Copyright © 2023-2024 Apple Inc. +from pfl.internal.bridge.base import ( + CommonFrameworkBridge, + FedProxFrameworkBridge, + FTRLFrameworkBridge, + SCAFFOLDFrameworkBridge, + SGDFrameworkBridge, +) +from pfl.internal.ops.framework_types import MLFramework +from pfl.internal.ops.selector import get_framework_module + +from publications.mdm.mdm.bridge.base import PolyaMixtureFrameworkBridge + + +class FrameworkBridgeFactory: + """ + A collection of bridges to deep learning specific + implementations for several algorithms. + The bridge returned depends on the Deep Learning + framework in use. + This way, we can inject framework-specific code + into an algorithm, and only have one implementation + of each algorithm in the public interface, e.g. one + public FedAvg class instead of one for each of TF, + PyTorch, etc. + + Each method returns a class with utility functions + for a particular algorithm. + """ + + @staticmethod + def common_bridge() -> CommonFrameworkBridge: + framework = get_framework_module().FRAMEWORK_TYPE + if framework == MLFramework.PYTORCH: + from .pytorch import common as common_pt + return common_pt.PyTorchCommonBridge + elif framework == MLFramework.TENSORFLOW: + from .tensorflow import common as common_tf + return common_tf.TFCommonBridge + elif framework == MLFramework.NUMPY: + from .numpy import common as common_np + return common_np.NumpyCommonBridge + else: + raise NotImplementedError("Common bridge not available " + f"for framework {framework}") + + @staticmethod + def sgd_bridge() -> SGDFrameworkBridge: + framework = get_framework_module().FRAMEWORK_TYPE + if framework == MLFramework.PYTORCH: + from .pytorch import sgd as sgd_pt + return sgd_pt.PyTorchSGDBridge + elif framework == MLFramework.TENSORFLOW: + from .tensorflow import sgd as sgd_tf + return sgd_tf.TFSGDBridge + else: + raise NotImplementedError("SGD bridge not available " + f"for framework {framework}") + + @staticmethod + def fedprox_bridge() -> FedProxFrameworkBridge: + framework = get_framework_module().FRAMEWORK_TYPE + if framework == MLFramework.PYTORCH: + from .pytorch import proximal as proximal_pt + return proximal_pt.PyTorchFedProxBridge + elif framework == MLFramework.TENSORFLOW: + from .tensorflow import proximal as proximal_tf + return proximal_tf.TFFedProxBridge + else: + raise NotImplementedError("FedProx bridge not available " + f"for framework {framework}") + + @staticmethod + def scaffold_bridge() -> SCAFFOLDFrameworkBridge: + framework = get_framework_module().FRAMEWORK_TYPE + if framework == MLFramework.PYTORCH: + from .pytorch import scaffold as scaffold_pt + return scaffold_pt.PyTorchSCAFFOLDBridge + else: + raise NotImplementedError("SCAFFOLD bridge not available " + f"for framework {framework}") + + @staticmethod + def ftrl_bridge() -> FTRLFrameworkBridge: + framework = get_framework_module().FRAMEWORK_TYPE + if framework == MLFramework.PYTORCH: + from .pytorch import ftrl as ftrl_pt + return ftrl_pt.PyTorchFTRLBridge + elif framework == MLFramework.TENSORFLOW: + from .tensorflow import ftrl as ftrl_tf + return ftrl_tf.TFFTRLBridge + else: + raise NotImplementedError("FTRL bridge not available " + f"for framework {framework}") + + @staticmethod + def polya_mixture_bridge() -> PolyaMixtureFrameworkBridge: + framework = get_framework_module().FRAMEWORK_TYPE + if framework == MLFramework.PYTORCH: + from .pytorch import polya_mixture as polya_mixture_pt + return polya_mixture_pt.PyTorchPolyaMixtureBridge + else: + raise NotImplementedError("PolyaMixture bridge not available " + f"for framework {framework}") diff --git a/publications/mdm/mdm/bridge/pytorch/__init__.py b/publications/mdm/mdm/bridge/pytorch/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/publications/mdm/mdm/bridge/pytorch/polya_mixture.py b/publications/mdm/mdm/bridge/pytorch/polya_mixture.py new file mode 100644 index 0000000..a43ed9c --- /dev/null +++ b/publications/mdm/mdm/bridge/pytorch/polya_mixture.py @@ -0,0 +1,102 @@ +# -*- coding: utf-8 -*- + +from typing import Tuple +import torch + +from ..base import PolyaMixtureFrameworkBridge + + +class PyTorchPolyaMixtureBridge(PolyaMixtureFrameworkBridge[torch.Tensor]): + """ + Interface for Polya-Mixture algorithm in PyTorch. + """ + + @staticmethod + def category_counts_polya_mixture(categories: torch.Tensor, + num_categories: int) -> torch.Tensor: + categories = categories.to('cpu') + uniques, counts = torch.unique(categories, return_counts=True) + category_counts = torch.zeros(num_categories).int() + category_counts[uniques.int().to(torch.int64)] = counts.int() + return category_counts + + @staticmethod + def category_probabilities_polya_mixture_initialization( + num_components, num_categories, component, + categories) -> torch.Tensor: + # Compute counts of each class and normalize to probability vectors + uniques, counts = torch.unique(categories, return_counts=True) + counts = counts.to('cpu') + uniques = uniques.to('cpu') + p = torch.zeros((num_components, num_categories)) + p = p.to('cpu') + p[component][uniques.int().to(torch.int64)] = counts.float( + ) # User contributes only to estimate for their mixture component + p[component] /= torch.sum(p[component]) + + return p + + @staticmethod + def expectation_step(phi, alphas, num_samples_distribution, + category_counts) -> torch.Tensor: + if (num_samples_distribution == 0).any(): + raise AssertionError('num_samples_distribution contains zero values, which cannot work with expectation step on clients') + + # E Step - compute posterior probability of each component + # Compute log prior + log likelihood + # TODO log_v might be missing + torch.lgamma(torch.sum(counts)+1) - torch.sum(torch.lgamma(category_counts+1), dim=1, keepdim=False) + phi = torch.Tensor(phi).to('cpu') + alphas = torch.Tensor(alphas).to('cpu') + category_counts = category_counts.to('cpu') + num_samples_distribution = num_samples_distribution.to('cpu') + log_v = torch.log(phi) + ( + torch.lgamma(torch.sum(alphas, dim=1, keepdim=False)) - + torch.lgamma( + torch.sum(category_counts + alphas, dim=1, keepdim=False)) + + torch.sum( + torch.lgamma(category_counts + alphas) - torch.lgamma(alphas), + dim=1, + keepdim=False)) + torch.log(num_samples_distribution) + + # TODO Ignore this as log(0) => NaN + # TODO fix this equation so that it works with num_samples_distribution = 0 + # + torch.log(num_samples_distribution[:, num_user_samples]) + + # Compute log probability of the data, computed like this for numerical stability + # computes sum(v) + log_normalization_constant = log_v[0] + torch.log( + torch.sum(torch.exp(log_v - log_v[0]))) + #print('log_normalization_constant', log_normalization_constant) + + # Compute posterior probability + w = torch.exp(log_v - log_normalization_constant) + + return w + + @staticmethod + def maximization_step(posterior_probabilities, category_counts, + alphas) -> torch.Tensor: + # M Step - compute client update to alphas for fixed point update + # which will be applied by the model in process_aggregated_statistics. + # Note the numerator and denominator are both weighted by w (the + # probability vector giving the client belonging to each component). + posterior_probabilities = torch.Tensor(posterior_probabilities).to('cpu') + category_counts = torch.Tensor(category_counts).to('cpu') + alphas = torch.Tensor(alphas).to('cpu') + numerator = posterior_probabilities.reshape( + (-1, 1)) * (torch.digamma(category_counts + alphas) - + torch.digamma(alphas)) + # Paper currently says something different, where alphas should all be summed first. + denominator = posterior_probabilities.reshape( + (-1, 1)) * (torch.digamma( + torch.sum(category_counts + alphas, dim=1, keepdim=True)) - + torch.digamma(torch.sum(alphas, dim=1, keepdim=True))) + + return numerator, denominator + + @staticmethod + def update_alpha(alphas, numerator, denominator) -> torch.Tensor: + alphas = alphas.to('cpu') + numerator = numerator.to('cpu') + denominator = denominator.to('cpu') + return torch.Tensor(alphas) * numerator / denominator diff --git a/publications/mdm/mdm/init_algorithm.py b/publications/mdm/mdm/init_algorithm.py new file mode 100644 index 0000000..9a24c1b --- /dev/null +++ b/publications/mdm/mdm/init_algorithm.py @@ -0,0 +1,266 @@ +# -*- coding: utf-8 -*- + +from dataclasses import dataclass +from typing import Tuple, Optional, TypeVar, Callable, Union +from collections import defaultdict + +import numpy as np +import torch + +from pfl.common_types import Population +from pfl.data.dataset import AbstractDataset +from pfl.hyperparam import get_param_value +from pfl.metrics import Metrics +from pfl.context import CentralContext +from pfl.stats import MappedVectorStatistics +from pfl.internal.ops import get_ops +from pfl.algorithm.base import FederatedAlgorithm, AlgorithmHyperParams +from pfl.data.dataset import AbstractDatasetType + +from publications.mdm.mdm.model import MDMModelType, MDMModelHyperParamsType +from publications.mdm.mdm.bridge.factory import FrameworkBridgeFactory as bridges + + +@dataclass(frozen=True) +class MDMInitializationAlgorithmParams(AlgorithmHyperParams): + """ + Parameters for initialization algorithm of Polya Mixture. + + :param strategy: + Strategy for a user to decide which component to contribute + to for initialization. Currently only 'random' implemented. + :param central_num_iterations: + Number of iterations to perform in algorithm. + :param cohort_size: + Number of users over which to aggregate statistics in each + iteration. + """ + cohort_size: int + num_samples_mixture_bins: np.ndarray + strategy: str = 'random' + central_num_iterations: int = 1 + extract_categories_fn: Callable[[AbstractDataset], Union[ + np.ndarray, + torch.Tensor]] = lambda user_dataset: user_dataset.raw_data[1] + + def __post_init__(self): + assert self.strategy in [ + 'random' + ], (f'strategy {self.strategy} is not supported') + assert self.central_num_iterations >= 1 + assert self.cohort_size > 0 + assert np.all(self.num_samples_mixture_bins > 0) + + +MDMInitializationAlgorithmParamsType = TypeVar( + 'MDMInitializationAlgorithmParamsType', + bound=MDMInitializationAlgorithmParams) + + +class MDMInitializationAlgorithm( + FederatedAlgorithm[MDMInitializationAlgorithmParamsType, + MDMModelHyperParamsType, MDMModelType, + MappedVectorStatistics, AbstractDatasetType]): + """ + Federated algorithm class for learning initialization of mixture of Polya + (Dirichlet-Multinomial) distribution. + """ + + def __init__(self, statistics_dir: Optional[str] = None): + super().__init__() + self._running_sums = defaultdict(int) + + def get_next_central_contexts( + self, + model: MDMModelType, + iteration: int, + algorithm_params: MDMInitializationAlgorithmParamsType, + model_train_params: MDMModelHyperParamsType, + model_eval_params: Optional[MDMModelHyperParamsType] = None, + ) -> Tuple[Optional[Tuple[CentralContext[ + MDMInitializationAlgorithmParamsType, MDMModelHyperParamsType], + ...]], MDMModelType, Metrics]: + + if iteration == algorithm_params.central_num_iterations: + return None, model, Metrics() + + configs = [ + CentralContext( + current_central_iteration=iteration, + do_evaluation=False, + cohort_size=get_param_value(algorithm_params.cohort_size), + population=Population.TRAIN, + model_train_params=model_train_params.static_clone(), + model_eval_params=None, + algorithm_params=algorithm_params.static_clone(), + seed=self._get_seed()) + ] + return tuple(configs), model, Metrics() + + def simulate_one_user( + self, + model: MDMModelType, + user_dataset: AbstractDataset, + central_context: CentralContext[MDMInitializationAlgorithmParamsType, + MDMModelHyperParamsType], + ) -> Tuple[Optional[MappedVectorStatistics], Metrics]: + """ + Encode user's dataset into statistics with a `MDMModel`. + """ + algorithm_params = central_context.algorithm_params + + if algorithm_params.strategy == 'random': + # Randomly assign user to a mixture component + # TODO this approach might not work when num mixture > 1 and the + # cohort size is large, as the p and q values will likely be very + # similar for all clusters and this symmetry could hurt convergence. + component = np.random.choice( + range(central_context.model_train_params.num_components)) + else: + raise ValueError( + f'Strategy {algorithm_params.strategy} not recognized.' + 'Only "random" strategy is implemented.') + + # Compute counts of each class and normalize to probability vectors + # User contributes only to estimate for their mixture component + categories = central_context.algorithm_params.extract_categories_fn( + user_dataset) + p = bridges.polya_mixture_bridge( + ).category_probabilities_polya_mixture_initialization( + central_context.model_train_params.num_components, + central_context.model_train_params.num_categories, component, + categories) + q = p**2 + + # Record user mixture component + # component sizes are needed for initialization computation + e = torch.zeros( + (central_context.model_train_params.num_components, + central_context.algorithm_params.num_samples_mixture_bins.shape[1] + )) + + num_samples = len(categories) + + selected_bin = -1 + for i, bin_edge in enumerate(central_context.algorithm_params. + num_samples_mixture_bins[component]): + bin_edge = int(bin_edge) + if num_samples <= bin_edge: + selected_bin = i + break + + e[component, selected_bin] = 1 + + statistics = MappedVectorStatistics() + statistics['p'] = p.to('cpu') + statistics['q'] = q.to('cpu') + statistics['e'] = e.to('cpu') + return statistics, Metrics() + + def process_aggregated_statistics( + self, central_context: CentralContext[ + MDMInitializationAlgorithmParamsType, + MDMModelHyperParamsType], aggregate_metrics: Metrics, + model: MDMModelType, statistics: MappedVectorStatistics + ) -> Tuple[MDMModelType, Metrics]: + + # Directly aggregate running sum of statistics + # only relevant if num_central_iterations > 1 + for key, val in statistics.items(): + self._running_sums[key] += val + + if (central_context.current_central_iteration == + central_context.algorithm_params.central_num_iterations - 1): + + num_components = central_context.model_train_params.num_components + + p = self._running_sums['p'] + q = self._running_sums['q'] + e = self._running_sums['e'] + + print('init aggregated statistics') + print('p', p) + print('q', q) + print('e', e) + + # Set all elements < 0 to 0 + # This may arise due to differential privacy noise + p = torch.clamp(p, min=0) + q = torch.clamp(q, min=0) + e = torch.clamp(e, min=0) + + # Need to prevent p, q, and subsequently alpha, and num_samples_distribution from having no non-zero values. + # Fix issue of alpha = 0 by assigning some small prob to all categories + # Cannot have alpha = 0 for any of the categories. + # In practice, we might get alpha = 0 if the cohort size used for the initialisation step was too small, + # such that we did not see any instances of this category occuring in the population. + # In practice, one should go over the entire population to find the probability of each category. + # Fix this issue by apportioning a small amount of the probability to that value of alpha. + + # Check if any element is equal to zero + if (p == 0).any(): + num_categories_leq_zero = torch.sum(p <= 0, dim=1) + extra_mass = torch.sum(p, + dim=1) * 0.01 / num_categories_leq_zero + + p = torch.where(p > 0, p, extra_mass.unsqueeze(1).expand_as(p)) + # Note fix zero issue in p and q separately because q >= p^2 + + # TODO Consider approximating p as p/(cohort size/num_components), + # since users are randomly assigned to components + # Similarly can approximate q as q/(cohort_size/num_components). + # This might make the results more accurate, since DP noise will + # be added to e, component_sums will be noisy. + #component_sums = torch.sum(e, dim=1, keepdim=True) + num_users_component = central_context.algorithm_params.cohort_size / num_components + p = torch.divide(p, num_users_component) + + if (q == 0).any(): + q[q == 0] = torch.pow(p[q == 0], 2) * 1.1 + q = torch.divide(q, num_users_component) + + if (e == 0).any(): + num_zero = torch.sum(e == 0, dim=1, keepdim=True) + extra_mass = torch.sum(e, dim=1, + keepdim=True) * 0.01 / num_zero + e = torch.where(e > 0, e, extra_mass.expand_as(e)) + + num_samples_distribution = torch.divide(e, num_users_component) + + # Compute alpha that matches the first two moments + # of the empirical distribution + + # Use either category with max probability or else average/median over all categories + init_coefficient = (p - q) / (q - torch.pow(p, 2)) + + k_pmax = torch.argmax(p, dim=1) + k_pmax_coefficient = init_coefficient[ + torch.arange(init_coefficient.size(0)), k_pmax] + + moment_matching_alpha_k_pmax = p * k_pmax_coefficient.reshape( + -1, 1) + + alphas = moment_matching_alpha_k_pmax + + # if only two categories and one component + #alpha_0 = 0.5 * (1 - p[0,1]) / (1 - p[0,0] - p[0,1]) + #alpha_1 = 0.5 * (1 - p[0,0]) / (1 - p[0,0] - p[0,1]) + #alphas = [torch.Tensor([alpha_0, alpha_1])] + + phi = 1 / num_components * torch.ones(num_components) + + model, metrics = model.apply_model_update( + MappedVectorStatistics({ + 'alphas': + alphas, + 'phi': + phi, + 'num_samples_distribution': + num_samples_distribution + })) + metrics['alphas'] = alphas + metrics['phi'] = phi + metrics['num_samples_distribution'] = num_samples_distribution + return model, metrics + else: + return model, Metrics() diff --git a/publications/mdm/mdm/model.py b/publications/mdm/mdm/model.py new file mode 100644 index 0000000..3372fa3 --- /dev/null +++ b/publications/mdm/mdm/model.py @@ -0,0 +1,137 @@ +# -*- coding: utf-8 -*- + +from typing import TypeVar, Generic, Tuple, List, Union, Optional +from dataclasses import dataclass +import os +import joblib + +import numpy as np + +from pfl.hyperparam.base import ModelHyperParams +from pfl.model.base import Model +from pfl.metrics import Metrics +from pfl.stats import MappedVectorStatistics +from pfl.exception import CheckpointNotFoundError +from pfl.internal.ops.selector import set_framework_module +from pfl.internal.ops import pytorch_ops +from pfl.internal.ops.selector import get_default_framework_module as get_ops + +Tensor = TypeVar('Tensor') +FrameworkModelType = TypeVar('FrameworkModelType') + + +@dataclass(frozen=True) +class MDMModelHyperParams(ModelHyperParams): + """ + Parameters for Polya-Mixture model. + """ + num_components: int + num_categories: int + + def __post_init__(self): + if self.num_components is not None: + assert self.num_components >= 1, ( + 'Must have >= 1 component in Polya-Mixture model') + if self.num_categories is not None: + assert self.num_categories >= 2, ( + 'Must have >= 2 categories being modelled with Polya-Mixture') + + +MDMModelHyperParamsType = TypeVar('MDMModelHyperParamsType', + bound=MDMModelHyperParams) + + +class MDMModel(Model, Generic[MDMModelHyperParamsType, Tensor]): + """ + Polya Mixture model. + + Used Fixed-Point solver. + + Model that applies a weighted version of the fixed point Polya update from + https://tminka.github.io/papers/dirichlet/minka-dirichlet.pdf to the alpha + of each mixture component. + :param phi: + np.ndarray of shape (number_mixture_components,) giving the weight of + each component, sums to 1. + :param alphas: + np.ndarray of shape (number_mixture_components, num_categories), stores + the alpha parameter for the Dirichlet of each mixture component. + """ + set_framework_module(pytorch_ops) + _MODEL_CKPT_NAME = "polya-mixture.joblib" + + def __init__(self, + alphas: Optional[Union[List, np.ndarray]] = None, + phi: Optional[Union[List, np.ndarray]] = None, + num_samples_distribution: Optional[Union[List, + np.ndarray]] = None): + + self._alphas = get_ops().to_tensor( + alphas) if alphas is not None else None + self._phi = get_ops().to_tensor(phi) if phi is not None else None + self._num_samples_distribution = get_ops().to_tensor( + num_samples_distribution + ) if num_samples_distribution is not None else None + + def _to_dict(self): + return { + 'alphas': self._alphas, + 'phi': self._phi, + 'num_samples_distribution': self._num_samples_distribution + } + + def save(self, dir_path: str) -> None: + """ + Save a Polya-Mixture model to disk. + + :param dir_path: + Path to which to save Polya-Mixture model will be saved. + """ + if not os.path.isdir(dir_path): + os.makedirs(dir_path) + + save_path = os.path.join(dir_path, self._MODEL_CKPT_NAME) + joblib.dump(self._to_dict(), save_path) + + def load(self, dir_path: str) -> None: + save_path = os.path.join(dir_path, self._MODEL_CKPT_NAME) + if not os.path.exists(save_path): + raise CheckpointNotFoundError(save_path) + + parameters = joblib.load(save_path) + try: + self._alphas = parameters['alphas'] + self._phi = parameters['phi'] + self._num_samples_distribution = parameters[ + 'num_samples_distribution'] + except KeyError as e: + raise KeyError( + 'Polya-Mixture model checkpoint does not ' + 'contain required keys: "alpha", "phi", ' + f'"num_components", "num_categories", "num_samples_distribution": {e}' + ) + + @property + def phi(self) -> Union[np.ndarray, List[float]]: + return self._phi + + @property + def alphas(self) -> Union[np.ndarray, List[float]]: + return self._alphas + + @property + def num_samples_distribution(self) -> Union[np.ndarray, List[float]]: + return self._num_samples_distribution + + def apply_model_update( + self, + statistics: MappedVectorStatistics) -> Tuple['MDMModel', Metrics]: + + self._alphas = statistics['alphas'] + self._phi = statistics['phi'] + self._num_samples_distribution = statistics['num_samples_distribution'] + + return self, Metrics() + + +MDMModelType = TypeVar('MDMModelType', bound=MDMModel) diff --git a/publications/mdm/mdm_paper/README.md b/publications/mdm/mdm_paper/README.md new file mode 100644 index 0000000..0a7e824 --- /dev/null +++ b/publications/mdm/mdm_paper/README.md @@ -0,0 +1,3 @@ +# Code for paper "Improved Modelling of Federated Datasets using Mixtures-of-Dirichlet-Multinomials" + +The code to run all experiments in the paper, and to process the results to produce the plots shown in the paper are available here. diff --git a/publications/mdm/mdm_paper/__init__.py b/publications/mdm/mdm_paper/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/publications/mdm/mdm_paper/notebooks/MSE_cifar10_experiments.ipynb b/publications/mdm/mdm_paper/notebooks/MSE_cifar10_experiments.ipynb new file mode 100644 index 0000000..5d3ce36 --- /dev/null +++ b/publications/mdm/mdm_paper/notebooks/MSE_cifar10_experiments.ipynb @@ -0,0 +1,501 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 20, + "id": "d168630b-085e-4ad9-82fe-413abc04c6b0", + "metadata": {}, + "outputs": [], + "source": [ + "import joblib\n", + "import os\n", + "from collections import defaultdict\n", + "\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": 315, + "id": "0eb31238-e448-4ba9-a15a-e64cbc2459a4", + "metadata": {}, + "outputs": [], + "source": [ + "results = defaultdict(dict)" + ] + }, + { + "cell_type": "code", + "execution_count": 348, + "id": "49c3fd57-e79f-4f01-95a1-d100794f3dd3", + "metadata": {}, + "outputs": [], + "source": [ + "def mse(y, t):\n", + " return np.linalg.norm(y-t, ord=2) / np.linalg.norm(t, ord=2) #np.size(y)\n", + "\n", + "def get_results(dirpath, targets):\n", + " mse_alphas = []\n", + " mse_phi = []\n", + " \n", + " i = 0\n", + " while True:\n", + " path = f'{dirpath}/{str(i)}/polya-mixture.joblib'\n", + " if os.path.exists(path):\n", + " d = joblib.load(f'{dirpath}/{str(i)}/polya-mixture.joblib')\n", + " y_a = d['alphas'].numpy() \n", + " y_p = d['phi'].numpy()\n", + " t_a = np.array(targets['alphas']).reshape(y_a.shape)\n", + " t_p = np.array(targets['phi']).reshape(y_p.shape)\n", + "\n", + " if False: # instead of this, just reorder targets\n", + " # Order according to increasing phi value\n", + " y_sorting_indices = np.argsort(y_p)\n", + " t_sorting_indices = np.argsort(t_p)\n", + " y_a = y_a[y_sorting_indices, :] if y_a.ndim == 2 else y_a[y_sorting_indices]\n", + " t_a = t_a[t_sorting_indices, :] if t_a.ndim == 2 else t_a[t_sorting_indices]\n", + " y_p = y_p[y_sorting_indices]\n", + " t_p = t_p[t_sorting_indices]\n", + " \n", + " mse_alphas.append(mse(y_a, t_a))\n", + " mse_phi.append(mse(y_p, t_p))\n", + " i += 1\n", + " else:\n", + " break\n", + " print('y_a', y_a)\n", + " print('t_a', t_a)\n", + " print('y_p', y_p)\n", + " print('t_p', t_p)\n", + "\n", + " return mse_alphas, mse_phi" + ] + }, + { + "cell_type": "code", + "execution_count": 349, + "id": "34f11c71-e68e-4a6b-a548-684632ac2e45", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "y_a [[0.9830888 0.9836113 0.949971 1.0266845 0.98187065 0.93955207\n", + " 1.0021306 1.0542753 0.98674315 0.9831437 ]]\n", + "t_a [[1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]]\n", + "y_p [1.]\n", + "t_p [1.]\n" + ] + } + ], + "source": [ + "dirpath = '../mle_params/cifar10_1_mixture_easy_iteration_models'\n", + "targets = {'phi': 1.0, 'alphas': [1.0]*10}\n", + "\n", + "a, p = get_results(dirpath, targets)\n", + "results['Low heterogeneity - 1 mixture component'] = {'alphas': a, 'phi': p}" + ] + }, + { + "cell_type": "code", + "execution_count": 350, + "id": "a44366a7-d41e-43cf-a2a4-0d2104a4c77d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "y_a [[0.8949972 0.8292597 0.8842902 0.8516318 0.85689884 0.8867707\n", + " 0.8828852 0.8397239 0.8045578 0.89611095]\n", + " [0.9422966 0.91131413 0.9135793 0.90758824 0.94545484 0.94940096\n", + " 0.9347347 0.91238105 0.90499514 0.96489817]]\n", + "t_a [[0.8 0.8 0.8 0.8 0.8 0.8 0.8 0.8 0.8 0.8]\n", + " [1. 1. 1. 1. 1. 1. 1. 1. 1. 1. ]]\n", + "y_p [0.38324493 0.6167551 ]\n", + "t_p [0.5 0.5]\n" + ] + } + ], + "source": [ + "dirpath = '../mle_params/cifar10_2_mixture_easy_iteration_models'\n", + "targets = {'phi': [0.5, 0.5], 'alphas': [[0.8]*10, [1.0]*10]}\n", + "\n", + "a, p = get_results(dirpath, targets)\n", + "results['Low heterogeneity - 2 mixture components'] = {'alphas': a, 'phi': p}" + ] + }, + { + "cell_type": "code", + "execution_count": 351, + "id": "090350bd-bbc9-4b57-b893-5350a2f8a389", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "y_a [[1.066593 1.0640484 0.99796337 0.99338555 1.0719604 1.0735439\n", + " 1.0606164 0.99636525 1.0607691 1.0325032 ]\n", + " [0.8113324 0.7412155 0.7421719 0.76742476 0.7978137 0.80386424\n", + " 0.8376431 0.7696238 0.78532445 0.78983146]\n", + " [0.88768315 0.8750244 0.8565851 0.8092215 0.9191889 0.90774536\n", + " 0.9050219 0.8186563 0.82398546 0.86230224]]\n", + "t_a [[1.1 1.1 1.1 1.1 1.1 1.1 1.1 1.1 1.1 1.1]\n", + " [0.8 0.8 0.8 0.8 0.8 0.8 0.8 0.8 0.8 0.8]\n", + " [1. 1. 1. 1. 1. 1. 1. 1. 1. 1. ]]\n", + "y_p [0.6212769 0.13670582 0.2420173 ]\n", + "t_p [0.334 0.333 0.333]\n" + ] + } + ], + "source": [ + "dirpath = '../mle_params/cifar10_3_mixture_easy_iteration_models'\n", + "targets = {'phi': [0.334, 0.333, 0.333], 'alphas': [[1.1]*10, [0.8]*10, [1.0]*10]}\n", + "\n", + "a, p = get_results(dirpath, targets)\n", + "results['Low heterogeneity - 3 mixture components'] = {'alphas': a, 'phi': p}" + ] + }, + { + "cell_type": "code", + "execution_count": 352, + "id": "3af0041b-ef85-4d82-a8e0-d24c3113e9b0", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "y_a [[0.09486745 0.18039015 0.6038319 1.0086943 1.9933786 0.09489949\n", + " 0.99804974 2.0103388 0.5047902 0.501056 ]]\n", + "t_a [[0.1 0.2 0.6 1. 2. 0.1 1. 2. 0.5 0.5]]\n", + "y_p [1.]\n", + "t_p [1.]\n" + ] + } + ], + "source": [ + "dirpath = '../mle_params/cifar10_1_mixture_medium_iteration_models'\n", + "targets = {'phi': 1.0, 'alphas': [0.1, 0.2, 0.6, 1.0, 2.0, 0.1, 1.0, 2.0, 0.5, 0.5]}\n", + "\n", + "a, p = get_results(dirpath, targets)\n", + "results['Medium heterogeneity - 1 mixture component'] = {'alphas': a, 'phi': p}" + ] + }, + { + "cell_type": "code", + "execution_count": 353, + "id": "c23bfe0d-d870-4410-8fca-fe4b08040ec3", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "y_a [[0.09601912 0.203612 0.576978 0.9885703 1.942201 0.09881581\n", + " 0.9899525 2.032183 0.52628845 0.511908 ]\n", + " [1.1092798 0.1123076 0.6980247 0.90534943 1.0147401 0.18994084\n", + " 0.5059109 0.9570854 0.79806316 1.5191599 ]]\n", + "t_a [[0.1 0.2 0.6 1. 2. 0.1 1. 2. 0.5 0.5]\n", + " [1.1 0.1 0.7 0.9 1. 0.2 0.5 1. 0.8 1.5]]\n", + "y_p [0.37693217 0.6230678 ]\n", + "t_p [0.4 0.6]\n" + ] + } + ], + "source": [ + "dirpath = '../mle_params/cifar10_2_mixture_medium_iteration_models'\n", + "targets = {'phi': [0.4, 0.6], 'alphas': [[0.1, 0.2, 0.6, 1.0, 2.0, 0.1, 1.0, 2.0, 0.5, 0.5], [1.1, 0.1, 0.7, 0.9, 1.0, 0.2, 0.5, 1.0, 0.8, 1.5]]}\n", + "\n", + "a, p = get_results(dirpath, targets)\n", + "results['Medium heterogeneity - 2 mixture components'] = {'alphas': a, 'phi': p}" + ] + }, + { + "cell_type": "code", + "execution_count": 354, + "id": "2e1b0397-184b-4c0c-81fb-979899e35e11", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "y_a [[0.51219416 0.51829547 0.47929743 0.53371894 0.50652635 0.499473\n", + " 0.47228953 0.4900735 0.4821596 0.48754203]\n", + " [0.13210084 0.17273213 0.5936526 0.997307 1.9424596 0.10008831\n", + " 1.0737354 2.0053742 0.52007437 0.49917984]\n", + " [1.039937 0.09993631 0.75087065 0.89299226 0.9463883 0.17576067\n", + " 0.5173786 1.0259137 0.78837794 1.5182108 ]]\n", + "t_a [[0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5]\n", + " [0.1 0.2 0.6 1. 2. 0.1 1. 2. 0.5 0.5]\n", + " [1.1 0.1 0.7 0.9 1. 0.2 0.5 1. 0.8 1.5]]\n", + "y_p [0.20531842 0.3174111 0.47727048]\n", + "t_p [0.2 0.3 0.5]\n" + ] + } + ], + "source": [ + "dirpath = '../mle_params/cifar10_3_mixture_medium_iteration_models'\n", + "targets = {'phi': [0.2, 0.3, 0.5], 'alphas': [[0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5], [0.1, 0.2, 0.6, 1.0, 2.0, 0.1, 1.0, 2.0, 0.5, 0.5], [1.1, 0.1, 0.7, 0.9, 1.0, 0.2, 0.5, 1.0, 0.8, 1.5]]}\n", + "\n", + "a, p = get_results(dirpath, targets)\n", + "results['Medium heterogeneity - 3 mixture components'] = {'alphas': a, 'phi': p}" + ] + }, + { + "cell_type": "code", + "execution_count": 355, + "id": "64a00cc7-e66b-494f-adea-df47c093b755", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "y_a [[0.10798693 0.08479945 0.09277119 0.10356809 0.0958684 0.09630357\n", + " 0.08943666 0.10059562 0.10332205 0.09725104]]\n", + "t_a [[0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1]]\n", + "y_p [1.]\n", + "t_p [1.]\n" + ] + } + ], + "source": [ + "dirpath = '../mle_params/cifar10_1_mixture_hard_iteration_models'\n", + "targets = {'phi': 1.0, 'alphas': [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]}\n", + "\n", + "a, p = get_results(dirpath, targets)\n", + "results['High heterogeneity - 1 mixture component'] = {'alphas': a, 'phi': p}" + ] + }, + { + "cell_type": "code", + "execution_count": 356, + "id": "4514fb77-c061-4d90-863c-f8901b1baf90", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "y_a [[0.1807397 0.17358837 0.1946859 0.18628934 0.19083592 0.17438039\n", + " 0.18713334 0.18131252 0.18108001 0.19267383]\n", + " [0.34003973 0.34449705 0.35007524 0.35807556 0.36345354 0.3291148\n", + " 0.33449852 0.3500933 0.3563593 0.3211949 ]]\n", + "t_a [[0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1]\n", + " [0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3]]\n", + "y_p [0.37103534 0.6289647 ]\n", + "t_p [0.1 0.9]\n" + ] + } + ], + "source": [ + "dirpath = '../mle_params/cifar10_2_mixture_hard_iteration_models'\n", + "targets = {'phi': [0.1, 0.9], 'alphas': [[0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1], [0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3]]}\n", + "\n", + "a, p = get_results(dirpath, targets)\n", + "results['High heterogeneity - 2 mixture components'] = {'alphas': a, 'phi': p}" + ] + }, + { + "cell_type": "code", + "execution_count": 357, + "id": "44415ead-b5ee-4a28-b42b-14ad43aff582", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "y_a [[1.1966388 0.08676551 0.72974104 0.9376729 1.0623652 0.20623356\n", + " 0.51617557 1.0524946 0.8251987 1.5541486 ]\n", + " [0.24933581 0.2668144 0.27757534 0.25659457 0.2190239 0.25226066\n", + " 0.25375283 0.26445332 0.2606129 0.21766934]\n", + " [1.0591303 0.08694185 0.626189 0.8334799 0.9366921 0.16620831\n", + " 0.47646916 0.944582 0.7469978 1.4314592 ]]\n", + "t_a [[1.1 0.1 0.7 0.9 1. 0.2 0.5 1. 0.8 1.5]\n", + " [0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1]\n", + " [0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3]]\n", + "y_p [0.5383507 0.19458508 0.2670642 ]\n", + "t_p [0.8 0.05 0.15]\n" + ] + } + ], + "source": [ + "dirpath = '../mle_params/cifar10_3_mixture_hard_iteration_models'\n", + "targets = {'phi': [0.8, 0.05, 0.15], 'alphas': [[1.1, 0.1, 0.7, 0.9, 1.0, 0.2, 0.5, 1.0, 0.8, 1.5], [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1], [0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3]]}\n", + "\n", + "a, p = get_results(dirpath, targets)\n", + "results['High heterogeneity - 3 mixture components'] = {'alphas': a, 'phi': p}" + ] + }, + { + "cell_type": "code", + "execution_count": 358, + "id": "5bdb12e7-6422-4636-b5a3-2b224e60ab7e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Normalised MSE of alpha parameters during training\\non artificially federated CIFAR-10\\nunder different target heterogeneity conditions\\nand using different numbers of mixture components')" + ] + }, + "execution_count": 358, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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XJmqVasyZ84c9u/fz88//8yYMWMctqlRowYBAQGsWLGCEydOcOHChXzHqVixIk899RTjxo1jxYoV7N69myeeeIKLFy8yePBgr15XZmYmw4cPZ+3atRw+fJjffvuNrVu30rBhQ6+vjRBCCCGEEFcTCVwIIazefvttKleuTJs2bejWrRtdunQhKirqirdj/Pjx9O/fn4cffpjWrVsTGBhIly5drFOTeqNXr1507dqVDh06UL16dRYsWIDBYOCHH37gjjvu4NFHH6VBgwY88MADHD58mNDQUJfH8vHx4csvvyQhIYFGjRoxevRopk2b5rCNr68v7777LrNnz6ZWrVp0797d6bHeeOMNevXqxUMPPURUVBT79+9n5cqVVK5c2avXZTQaOXPmDA8//DANGjSgb9++3H333UyZMsXrayOEEEIIIcTVxKCuxMByIYQoArPZTMOGDenbty+vvPJKaTdHCCGEEEIIcQVJcU4hRJlz+PBhfvzxR9q3b09WVhbvv/8+Bw8eZMCAAaXdNCGEEEIIIcQVJkNFhBBljo+PD/PmzePWW2+lbdu27Ny5k1WrVkkdByGEEEIIIa5BMlRECCGEEEIIIYQQZZZkXAghhBBCCCGEEKLMksCFEEIIIYQQQgghyiwJXAghhBBCCCGEEKLMksCFEEIIIYQQQgghyiwJXAghhBBCCCGEEKLMksCFEEIIIYQQQgghyiwJXAghhBBCCCGEEKLMksCFEEIIIYQQQgghyqz/B4bDHK5S/FYIAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for k in results.keys():\n", + " if 'Low' in k:\n", + " line = '--+'\n", + " elif 'Medium' in k:\n", + " line = '-o'\n", + " else:\n", + " line = '--'\n", + "\n", + " if '1' in k:\n", + " colour = 'red'\n", + " elif '2' in k:\n", + " colour = 'green'\n", + " elif '3' in k:\n", + " colour = 'blue'\n", + " plt.plot(results[k]['alphas'], line, color=colour, label=k+' - MSE alphas')\n", + "\n", + "\n", + " \n", + "plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')\n", + "plt.xlabel('Training iterations')\n", + "plt.ylabel('Normalised MSE')\n", + "plt.title('Normalised MSE of alpha parameters during training\\non artificially federated CIFAR-10\\nunder different target heterogeneity conditions\\nand using different numbers of mixture components')" + ] + }, + { + "cell_type": "code", + "execution_count": 359, + "id": "e3be4caa-0215-491f-aee9-6dda4aa1f08d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]\n", + "[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]\n", + "[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]\n" + ] + }, + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Normalised MSE of phi parameters during training\\non artificially federated CIFAR-10\\nunder different target heterogeneity conditions\\nand using different numbers of mixture components')" + ] + }, + "execution_count": 359, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABBYAAAIFCAYAAABmsH6lAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy81sbWrAAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOzdd1gUxxsH8O9xcPQmHUQQUJoaFMVYEKIodrERNSpgJMSusRsV0Cgae68Re6LYorEbxR479q5oVOyAUizA+/vjfrey3AEHomh8P89zD9zs7Ozs7NzBzk6REBGBMcYYY4wxxhhjrBg0SjsDjDHGGGOMMcYY+3xxwwJjjDHGGGOMMcaKjRsWGGOMMcYYY4wxVmzcsMAYY4wxxhhjjLFi44YFxhhjjDHGGGOMFRs3LDDGGGOMMcYYY6zYuGGBMcYYY4wxxhhjxcYNC4wxxhhjjDHGGCs2blhgjDHGGGOMMcZYsXHDAisV/v7+8Pf3F94nJiZCIpFg6dKlHzUfoaGhcHR0/KjHLG2PHj1Cu3btYGZmBolEgunTp793mqGhoTAwMFArrkQiQVRU1Hsfk306oqKiIJFIPpt0S9v7ft/xZ4gxxhhjnxpuWPhELV26FBKJBDo6Orh//77Sdn9/f1SqVKkUcvZl8vf3h0QiQYUKFVRu3717NyQSCSQSCdatWyfadv78ebRr1w4ODg7Q0dGBnZ0dGjZsiFmzZoniOTo6CmnkfTVu3LjEzmXAgAHYuXMnhg8fjhUrVpRo2qxkZGRkICoqCvHx8aWdlS/W6tWrS6TRjTHGGGPsS6BZ2hlgBXv9+jUmTJigdBP6X+Pg4IDMzExoaWmVdlbypaOjgxs3buD48ePw8fERbVu1ahV0dHTw6tUrUfiRI0fwzTffoFy5cggPD4e1tTX+/fdf/PPPP5gxYwb69Okjiu/l5YWBAwcqHdvW1rbEzmPv3r1o1aoVBg0aVGJpFkVmZiY0NfmrpyAZGRmIjo4GAFHPni/NyJEjMWzYsFI59urVq3HhwgX079+/xNN+3+87/gwxxhhj7FPD/5l84ry8vLBo0SIMHz68RG8ucyMivHr1Crq6uh8kfXUoemd8ypydnZGVlYXff/9d1LDw6tUrbNy4Ec2aNcP69etF+4wbNw7GxsY4ceIETExMRNseP36sdAw7Ozt07tz5g+Q/93Hz5uVj+pSuc3p6OvT19Us7Gx/N53K+inxqamp+FjfQr169gkwmg4aGep0A3/f77lP6DDHGGGOMATwU4pM3YsQIZGdnY8KECYXGzcrKwtixY+Hs7AxtbW04OjpixIgReP36tSieo6Mjmjdvjp07d6J69erQ1dXFggULEB8fD4lEgrVr1yI6Ohp2dnYwNDREu3btkJqaitevX6N///6wtLSEgYEBwsLClNKOjY1F/fr1YWlpCW1tbXh4eGDevHmF5l3VmOOHDx8iLCwMZcuWhba2NmxsbNCqVSskJiaK9t2+fTt8fX2hr68PQ0NDNGvWDBcvXlQ6xqZNm1CpUiXo6OigUqVK2LhxY6H5yqtjx45Ys2YNcnJyhLAtW7YgIyMDwcHBSvFv3rwJT09PlTfylpaWRT5+QW7duoX27dujTJky0NPTw9dff42tW7cK2xXDa4gIc+bMEYZZ5EdxTSZPnoxp06bBwcEBurq68PPzw4ULF1Tuc//+fQQFBcHAwAAWFhYYNGgQsrOzRXHUGR+uqItr1qzBiBEjYG1tDX19fbRs2RL//vuvKO7BgwfRvn17lCtXDtra2rC3t8eAAQOQmZkpiqeYB+LmzZto2rQpDA0N8d133xUrjbt376J58+YwMDCAnZ0d5syZA0A+7KV+/frQ19eHg4MDVq9erXRuKSkp6N+/P+zt7aGtrQ0XFxdMnDhRqFOJiYmwsLAAAERHRwvXKXeZXblyBe3atUOZMmWgo6OD6tWrY/PmzaLjKK73/v370bNnT1haWqJs2bIAgJcvX6J///5wdHSEtrY2LC0t0bBhQ5w+fbrA6wIAhw4dQo0aNaCjowNnZ2csWLBAKU5BcwjkPRfFPAqXLl1Cp06dYGpqirp164q25d2/d+/ewudZW1sbnp6e2LFjh9Kx4uPjUb16dVFe1Zm3wd/fH1u3bsWdO3eE8lfMxaKom3/88QdGjhwJOzs76Onp4cWLF3j+/DkGDRqEypUrw8DAAEZGRmjSpAnOnj1baPko6lZxPkOKc7px4wZCQ0NhYmICY2NjhIWFISMjQ7RvZmYm+vbtC3NzcxgaGqJly5a4f/8+z9vAGGOMsffy6T8K+sKVL18eXbt2xaJFizBs2LACey10794dy5YtQ7t27TBw4EAcO3YMMTExuHz5stJN9NWrV9GxY0dEREQgPDwcrq6uwraYmBjo6upi2LBhuHHjBmbNmgUtLS1oaGggOTkZUVFR+Oeff7B06VKUL18eo0ePFvadN28ePD090bJlS2hqamLLli3o2bMncnJy0KtXryKde9u2bXHx4kX06dMHjo6OePz4MXbv3o27d+8K/+SvWLECISEhCAwMxMSJE5GRkYF58+ahbt26OHPmjBBv165daNu2LTw8PBATE4Nnz54JjRZF0alTJ2Hse/369QHIu0w3aNBAZUOBg4MDjh49igsXLqg1J8bbt2/x9OlTpXB9ff0Ce5Q8evQItWvXRkZGBvr27QszMzMsW7YMLVu2xLp169C6dWvUq1cPK1asQJcuXdCwYUN07dpVrXNevnw5Xr58iV69euHVq1eYMWMG6tevj/Pnz8PKykqIl52djcDAQNSsWROTJ0/Gnj17MGXKFDg7O6NHjx5qHSuvcePGQSKRYOjQoXj8+DGmT5+OgIAAJCQkCOURFxeHjIwM9OjRA2ZmZjh+/DhmzZqFe/fuIS4uTpReVlYWAgMDUbduXUyePBl6enpFTiM7OxtNmjRBvXr18Ouvv2LVqlXo3bs39PX18fPPP+O7775DmzZtMH/+fHTt2hW1atVC+fLlAciHOPj5+eH+/fuIiIhAuXLlcOTIEQwfPhxJSUmYPn06LCwsMG/ePPTo0QOtW7dGmzZtAABVqlQBAFy8eBF16tSBnZ0dhg0bBn19faxduxZBQUFYv349WrduLcpvz549YWFhgdGjRyM9PR0A8OOPP2LdunXo3bs3PDw88OzZMxw6dAiXL19GtWrV8r0e58+fR6NGjWBhYYGoqChkZWUhMjJSVA+Kq3379qhQoQLGjx8PIiow7qFDh7Bhwwb07NkThoaGmDlzJtq2bYu7d+/CzMwMAHDmzBk0btwYNjY2iI6ORnZ2NsaMGSM02hTk559/RmpqKu7du4dp06YBgNLkpGPHjoVMJsOgQYPw+vVryGQyXLp0CZs2bUL79u1Rvnx5PHr0CAsWLICfnx8uXbpUaK+z9/0MBQcHo3z58oiJicHp06exePFiWFpaYuLEiUKc0NBQrF27Fl26dMHXX3+N/fv3o1mzZoWmzRhjjDFWIGKfpNjYWAJAJ06coJs3b5Kmpib17dtX2O7n50eenp7C+4SEBAJA3bt3F6UzaNAgAkB79+4VwhwcHAgA7dixQxR33759BIAqVapEb968EcI7duxIEomEmjRpIopfq1YtcnBwEIVlZGQonUtgYCA5OTmJwvz8/MjPz094f/v2bQJAsbGxRESUnJxMAGjSpEkqSkfu5cuXZGJiQuHh4aLwhw8fkrGxsSjcy8uLbGxsKCUlRQjbtWsXAVA6B1Vyl3f16tXp+++/F/Ipk8lo2bJlQvnFxcWJjiGVSkkqlVKtWrVoyJAhtHPnTlH5Kiiui6pXTExMgfnr378/AaCDBw+Kyqd8+fLk6OhI2dnZQjgA6tWrV6HnrLgmurq6dO/ePSH82LFjBIAGDBgghIWEhBAAGjNmjCiNqlWrkre3tygMAEVGRhZ4bEVZ2tnZ0YsXL4TwtWvXEgCaMWOGEKaqzsXExJBEIqE7d+4o5XHYsGFK8Yuaxvjx44Ww5ORk0tXVJYlEQn/88YcQfuXKFaVzHTt2LOnr69O1a9dExxo2bBhJpVK6e/cuERE9efIk33Jq0KABVa5cmV69eiWE5eTkUO3atalChQpCmOI7pG7dupSVlSVKw9jYWK06kFdQUBDp6OiIyuTSpUsklUop95+TvJ/n3PKeV2RkJAGgjh07KsVVbMu7v0wmoxs3bghhZ8+eJQA0a9YsIaxFixakp6dH9+/fF8KuX79OmpqaSmmq0qxZM5XfDYq66eTkpFRvXr16JfqsEcnLQltbW/TZUFU+7/MZUpRTt27dRPFat25NZmZmwvtTp04RAOrfv78oXmhoqFqfS8YYY4yx/PBQiM+Ak5MTunTpgoULFyIpKUllnG3btgEAfvrpJ1G4YiLA3F3iAXlPiMDAQJVpde3aVTSpWM2aNUFE6NatmyhezZo18e+//yIrK0sIy/1UPTU1FU+fPoWfnx9u3bqF1NTUwk5VlI5MJkN8fDySk5NVxtm9ezdSUlLQsWNHPH36VHhJpVLUrFkT+/btAwAkJSUhISEBISEhMDY2FvZv2LAhPDw81M6TQqdOnbBhwwa8efMG69atg1QqVXpKnPsYR48eRcuWLXH27Fn8+uuvCAwMhJ2dnVLXdUBeprt371Z6dezYscA8bdu2DT4+PkIXckD+hPWHH35AYmIiLl26VOTzVAgKCoKdnZ3w3sfHBzVr1hTqXG4//vij6L2vry9u3bpV7GN37doVhoaGwvt27drBxsZGdOzcdS49PR1Pnz5F7dq1QUQ4c+aMUpqqnvwWNY3u3bsLv5uYmMDV1RX6+vqi4TCurq4wMTERnX9cXBx8fX1hamoqqrMBAQHIzs7GgQMHCiyP58+fY+/evQgODsbLly+F/Z89e4bAwEBcv35daRWZ8PBwSKVSUZiJiQmOHTuGBw8eFHi83LKzs7Fz504EBQWhXLlyQri7u3u+3yVFkbfuFCQgIADOzs7C+ypVqsDIyEgo6+zsbOzZswdBQUGiXgIuLi5o0qTJe+cVAEJCQpR6EWlrawvzLGRnZ+PZs2cwMDCAq6urWsNMgPf7DKna99mzZ3jx4gUACMNFevbsKYqXdxJZxhhjjLGi4oaFz8TIkSORlZWV71wLd+7cgYaGBlxcXETh1tbWMDExwZ07d0Thiq7ZquS+aQAg3Izb29srhefk5IgaDA4fPoyAgADo6+vDxMQEFhYWGDFiBAAUqWFBW1sbEydOxPbt22FlZSV0O3/48KEQ5/r16wCA+vXrw8LCQvTatWuXMDmi4txVLRWZewiIujp06IDU1FRs374dq1atQvPmzUU3v3nVqFEDGzZsQHJyMo4fP47hw4fj5cuXaNeundINv7m5OQICApReDg4OBebpzp07Ks/F3d1d2F5cqsqtYsWKSnNd6OjoKHUzNzU1zbdhqDjHlkgkcHFxER377t27CA0NRZkyZYRx6X5+fgCU65ympqbK4S9FSUPVeRobG6Ns2bJKY/eNjY1F53/9+nXs2LFDqb4GBAQAUD2hZ243btwAEWHUqFFKaURGRqpMQ9Vn/ddff8WFCxdgb28PHx8fREVFFXrz+uTJE2RmZpbY5yivgr6T8sr7HQWI69rjx4+RmZmp9H0IQGVYcajKb05ODqZNm4YKFSpAW1sb5ubmsLCwwLlz59T6/nvfz1DecjE1NQUAYX/F34m8eS+pMmGMMcbYl4vnWPhMODk5oXPnzli4cGGBy68VNimZQkHj9fM+3SwsnP4/HvrmzZto0KAB3NzcMHXqVNjb20Mmk2Hbtm2YNm2aaMJDdfTv3x8tWrTApk2bsHPnTowaNQoxMTHYu3cvqlatKqS3YsUKWFtbK+3/oWaTt7Gxgb+/P6ZMmYLDhw8rrQSRH5lMhho1aqBGjRqoWLEiwsLCEBcXJ9wQfu7yqx8fUnZ2Nho2bIjnz59j6NChcHNzg76+Pu7fv4/Q0FClOpf7iXJx0yju5wOQ33g2bNgQQ4YMURm3YsWKBZ6vIi+DBg3Kt5dA3ptEVZ/14OBg+Pr6YuPGjdi1axcmTZqEiRMnYsOGDSXyRD+/76G8kxAWls/8qFPWH5qq/I4fPx6jRo1Ct27dMHbsWJQpUwYaGhro37+/Wt9/7/sZ+hTKhTHGGGNfJm5Y+IyMHDkSK1euFE3EpeDg4ICcnBxcv35deEoNyCf1S0lJKfSJd0nYsmULXr9+jc2bN4uenCmGJBSHs7MzBg4ciIEDB+L69evw8vLClClTsHLlSqErtKWlpfDEVxXFuSt6OOR29erVYuWrU6dO6N69O0xMTNC0adMi71+9enUAyHdoS1E5ODioPJcrV64I24tLVbldu3ZNmBjzQ8p7bCLCjRs3hIkMz58/j2vXrmHZsmWiySh3796t9jFKIg11OTs7Iy0trcD6CuR/Y+7k5AQA0NLSKjSNwtjY2KBnz57o2bMnHj9+jGrVqmHcuHH5NixYWFhAV1dXrc+R4kl5SkqKKPx9es4UhaWlJXR0dHDjxg2lbarCVFG3kTa3devW4ZtvvsFvv/0mCk9JSYG5uXmR0ytpir8Tt2/fFvU8UbdMGGOMMcbyw0MhPiPOzs7o3LkzFixYIBoSAEC4uZ0+fboofOrUqQDwUWb9Vjwty/10LDU1FbGxsUVOKyMjA69evRKFOTs7w9DQUFjiMjAwEEZGRhg/fjzevn2rlMaTJ08AyG+gvLy8sGzZMlF35N27dxd77oF27dohMjISc+fOhUwmyzfevn37VD4tVMwRUBJdyAH59T9+/DiOHj0qhKWnp2PhwoVwdHQs1lwSCps2bRKN2z9+/DiOHTtWYmPVC6JYkUJh3bp1SEpKEo6tqs4REWbMmKH2MUoiDXUFBwfj6NGj2Llzp9K2lJQUYb4SxWoVeW/MLS0t4e/vjwULFqhslFLU+YJkZ2crdcu3tLSEra2t0vKxuUmlUgQGBmLTpk24e/euEH758mWl8zEyMoK5ubnSnBFz584tNH8lQSqVIiAgAJs2bRLNI3Hjxg1s375drTT09fWLNHxLcdy8n/e4uDileS9Ki6KXS97rMGvWrNLIDmOMMcb+Q7jHwmfm559/xooVK3D16lV4enoK4V999RVCQkKwcOFCpKSkwM/PD8ePH8eyZcsQFBSEb7755oPnrVGjRpDJZGjRogUiIiKQlpaGRYsWwdLSsshP5q9du4YGDRogODgYHh4e0NTUxMaNG/Ho0SN06NABgPzmZd68eejSpQuqVauGDh06wMLCAnfv3sXWrVtRp04dzJ49G4B8Cc1mzZqhbt266NatG54/f45Zs2bB09MTaWlpRT5XY2NjtdZ879OnDzIyMtC6dWu4ubnhzZs3OHLkCNasWQNHR0eEhYWJ4t+/fx8rV65USsfAwABBQUH5HmfYsGH4/fff0aRJE/Tt2xdlypTBsmXLcPv2baxfv16p+39RuLi4oG7duujRowdev36N6dOnw8zMLN/u/CWpTJkyqFu3LsLCwvDo0SNMnz4dLi4uCA8PBwC4ubnB2dkZgwYNwv3792FkZIT169cXaV6HkkhDXYMHD8bmzZvRvHlzhIaGwtvbG+np6Th//jzWrVuHxMREmJubQ1dXFx4eHlizZg0qVqyIMmXKoFKlSqhUqRLmzJmDunXronLlyggPD4eTkxMePXqEo0eP4t69ezh79myBeXj58iXKli2Ldu3a4auvvoKBgQH27NmDEydOYMqUKQXuGx0djR07dsDX1xc9e/ZEVlaW8Dk6d+6cKG737t0xYcIEdO/eHdWrV8eBAwdw7dq19y5DdUVFRWHXrl2oU6cOevTogezsbMyePRuVKlVCQkJCoft7e3tjzZo1+Omnn1CjRg0YGBigRYsWBe7TvHlzjBkzBmFhYahduzbOnz+PVatWCT1NSpu3tzfatm2L6dOn49mzZ8Jyk4rrUpxeGowxxhhjADcsfHZcXFzQuXNnLFu2TGnb4sWL4eTkhKVLl2Ljxo2wtrbG8OHDP9oYfldXV6xbtw4jR47EoEGDYG1tjR49esDCwkJpRYnC2Nvbo2PHjvj777+xYsUKaGpqws3NDWvXrkXbtm2FeJ06dYKtrS0mTJiASZMm4fXr17Czs4Ovr6/opr1x48aIi4vDyJEjMXz4cDg7OyM2NhZ//vkn4uPjS6oIlEyePBlxcXHYtm0bFi5ciDdv3qBcuXLo2bMnRo4cCRMTE1H8hIQEdOnSRSkdBweHAhsWrKyscOTIEQwdOhSzZs3Cq1evUKVKFWzZsuW9e6t07doVGhoamD59Oh4/fgwfHx/Mnj0bNjY275WuOkaMGIFz584hJiYGL1++RIMGDTB37lzhib6Wlha2bNmCvn37IiYmBjo6OmjdujV69+6Nr776Sq1jlEQa6tLT08P+/fsxfvx4xMXFYfny5TAyMkLFihURHR0tWrVk8eLF6NOnDwYMGIA3b94gMjISlSpVgoeHB06ePIno6GgsXboUz549g6WlJapWrYrRo0erlYeePXti165d2LBhA3JycuDi4oK5c+eqXDEjtypVqmDnzp346aefMHr0aJQtWxbR0dFISkpSalgYPXo0njx5gnXr1mHt2rVo0qQJtm/fDktLy+IVXhF5e3tj+/btGDRoEEaNGgV7e3uMGTMGly9fFoYIFaRnz55ISEhAbGwspk2bBgcHh0IbFkaMGIH09HSsXr0aa9asQbVq1bB169YC58X52JYvXw5ra2v8/vvv2LhxIwICArBmzRq4urpCR0entLPHGGOMsc+UhHhWJ8aYComJiShfvjwmTZqEQYMGfdRjx8fH45tvvkFcXBzatWv3UY/N/tuCgoJw8eJFlXNFfKkSEhJQtWpVrFy5Et99911pZ4cxxhhjnyGeY4Exxth/UmZmpuj99evXsW3bNvj7+5dOhj4BecsEkM/No6GhgXr16pVCjhhjjDH2X8BDIRhjjP0nOTk5ITQ0FE5OTrhz5w7mzZsHmUz2UeYH+VT9+uuvOHXqFL755htoampi+/bt2L59O3744QfY29uXdvYYY4wx9pnihgXGGGP/SY0bN8bvv/+Ohw8fQltbG7Vq1cL48eNFSy1+aWrXro3du3dj7NixSEtLQ7ly5RAVFYWff/65tLPGGGOMsc8Yz7HAGGOMMcYYY4yxYuM5FhhjjDHGGGOMMVZs3LDAGGOMMcYYY4yxYuOGBcZKkUQiQVRUlCjsxIkTqF27NvT19SGRSJCQkICoqChIJJIip+/v71/sGfDz5m3p0qWQSCRITEwsVnqqrFixAm5ubtDS0oKJiUmJpBkaGgpHR8cSSetTkpiYCIlEgqVLl5Z2VhhjjDHGGBPhhgXGPrBt27YpNR7k5+3bt2jfvj2eP3+OadOmYcWKFXBwcPiwGSwlV65cQWhoKJydnbFo0SIsXLiwtLNUIubOnftJ3Pw/evQIgwYNgpubG/T09KCvrw9vb2/88ssvSElJEeL5+/ujUqVKon0dHR0hkUhUvl69eiXEy87Ohq2tLSQSCbZv364yH4pGMcVLS0sLjo6O6Nu3rygfBbl69SoGDBiA2rVrQ0dHp9AGrs2bN6NatWrQ0dFBuXLlEBkZiaysLLWOxRhjjDHGio5XhWDsA9u2bRvmzJmjsnEhMzMTmprvPoY3b97EnTt3sGjRInTv3l0IHzlyJIYNG1bkY+/atatYef4Y4uPjkZOTgxkzZsDFxaW0s1Ni5s6dC3Nzc4SGhpZaHk6cOIGmTZsiLS0NnTt3hre3NwDg5MmTmDBhAg4cOFBo3fDy8sLAgQOVwmUymfD73r17kZSUBEdHR6xatQpNmjTJN7158+bBwMAA6enp+PvvvzFr1iycPn0ahw4dKvR8jh49ipkzZ8LDwwPu7u5ISEjIN+727dsRFBQEf39/zJo1C+fPn8cvv/yCx48fY968eYUeizHGGGOMFR03LDD2gaSnp0NfX7/AODo6OqL3jx8/BgClYQGampqiBgh15b4J/NTkd66fEiLCq1evoKurW9pZUVtKSgpat24NqVSKM2fOwM3NTbR93LhxWLRoUaHp2NnZoXPnzgXGWblyJapVq4aQkBCMGDGiwDrfrl07mJubAwAiIiLQoUMHrFmzBsePH4ePj0+Bx2nZsiVSUlJgaGiIyZMnF9iwMGjQIFSpUgW7du0SPjNGRkYYP348+vXrp1QejDHGGGPs/fFQCPbZOnPmDJo0aQIjIyMYGBigQYMG+Oeff0RxFPMCHD58GD/99BMsLCygr6+P1q1b48mTJ4Ue49y5cwgNDYWTkxN0dHRgbW2Nbt264dmzZ6J4iu7ely5dQqdOnWBqaoq6desiNDQUc+bMAQBRd3CF3PMYhIaGws/PDwDQvn17SCQSYX6E/OZYWLlyJXx8fKCnpwdTU1PUq1dP9CQ67xwLb968wejRo+Ht7Q1jY2Po6+vD19cX+/btK7Qs8goJCYG5uTnevn2rtK1Ro0ZwdXXNd19HR0dERkYCACwsLJTmc9i+fTt8fX2hr68PQ0NDNGvWDBcvXlRKZ9OmTahUqRJ0dHRQqVIlbNy4UeXxcnJyMH36dHh6ekJHRwdWVlaIiIhAcnKyUr6aN2+OnTt3onr16tDV1cWCBQsAALGxsahfvz4sLS2hra0NDw8PpSfgjo6OuHjxIvbv3y9c69zln5KSgv79+8Pe3h7a2tpwcXHBxIkTkZOTI0onJSUFoaGhMDY2homJCUJCQtQeNrBgwQLcv38fU6dOVXkTbWVlhZEjR6qVVkEyMzOxceNGdOjQAcHBwcjMzMSff/6p9v6+vr4A5L10ClOmTBkYGhoWGu/SpUu4dOkSfvjhB1FDXM+ePUFEWLdundr5Y4wxxhhj6uMeC+yzdPHiRfj6+sLIyAhDhgyBlpYWFixYAH9/f+zfvx81a9YUxe/Tpw9MTU0RGRmJxMRETJ8+Hb1798aaNWsKPM7u3btx69YthIWFwdraGhcvXsTChQtx8eJF/PPPP0o3++3bt0eFChUwfvx4EBGqVq2KBw8eYPfu3VixYkWBx4qIiICdnR3Gjx+Pvn37okaNGrCysso3fnR0NKKiolC7dm2MGTMGMpkMx44dw969e9GoUSOV+7x48QKLFy9Gx44dER4ejpcvX+K3335DYGAgjh8/Di8vrwLzmFuXLl2wfPly7Ny5E82bNxfCHz58iL179woNB6pMnz4dy5cvx8aNG4Uu8lWqVAEgn9AxJCQEgYGBmDhxIjIyMjBv3jzUrVsXZ86cESZm3LVrF9q2bQsPDw/ExMTg2bNnCAsLQ9myZZWOFxERgaVLlyIsLAx9+/bF7du3MXv2bJw5cwaHDx+GlpaWEPfq1avo2LEjIiIiEB4eLjSQzJs3D56enmjZsiU0NTWxZcsW9OzZEzk5OejVq5dwXn369IGBgQF+/vlnABCuYUZGBvz8/HD//n1ERESgXLlyOHLkCIYPH46kpCRMnz4dgLyXRKtWrXDo0CH8+OOPcHd3x8aNGxESEqLWddm8eTN0dXXRrl07teLn5+3bt3j69KkoTE9PD3p6esJx0tLS0KFDB1hbW8Pf3x+rVq1Cp06d1EpfMUeCqanpe+UztzNnzgAAqlevLgq3tbVF2bJlhe2MMcYYY6yEEWOfoaCgIJLJZHTz5k0h7MGDB2RoaEj16tUTwmJjYwkABQQEUE5OjhA+YMAAkkqllJKSUuBxMjIylMJ+//13AkAHDhwQwiIjIwkAdezYUSl+r169KL+PGgCKjIwU3u/bt48AUFxcnCieIn2F69evk4aGBrVu3Zqys7NFcXOfp5+fH/n5+Qnvs7Ky6PXr16L4ycnJZGVlRd26dSswb4qyvH37NhERZWdnU9myZenbb78V7Td16lSSSCR069Ytleec95yePHkihL18+ZJMTEwoPDxcFPfhw4dkbGwsCvfy8iIbGxvRNdy1axcBIAcHByHs4MGDBIBWrVolSnPHjh1K4Q4ODgSAduzYoZRfVXUhMDCQnJycRGGenp6iMlcYO3Ys6evr07Vr10Thw4YNI6lUSnfv3iUiok2bNhEA+vXXX4U4WVlZ5OvrSwAoNjZWKe3cTE1N6auvviowTm5+fn7k6ekpClOUQ95X7vrQvHlzqlOnjvB+4cKFpKmpSY8fPxalpbjOV69epSdPnlBiYiItWbKEdHV1ycLCgtLT09XOKxHRpEmTRPVQ1TZFWeZWo0YN+vrrr4t0LMYYY4wxph4eCsE+O9nZ2di1axeCgoLg5OQkhNvY2KBTp044dOgQXrx4Idrnhx9+EPUu8PX1RXZ2Nu7cuVPgsXKPrX/16hWePn2Kr7/+GgBw+vRppfg//vhjsc6pqDZt2oScnByMHj0aGhrij3FBy1JKpVJh3oWcnBw8f/4cWVlZqF69usrzKYiGhga+++47bN68GS9fvhTCV61ahdq1a6N8+fJFSg+Q9xBJSUlBx44d8fTpU+EllUpRs2ZNYchGUlISEhISEBISAmNjY2H/hg0bwsPDQ5RmXFwcjI2N0bBhQ1Ga3t7eMDAwUBoGUr58eQQGBirlLXddSE1NxdOnT+Hn54dbt24hNTW10HOLi4uDr68vTE1NRfkICAhAdnY2Dhw4AEA+2aempiZ69Ogh7CuVStGnTx81SlDeK0WdYQOFqVmzJnbv3i16de3aFQDw7Nkz7Ny5Ex07dhTit23bFhKJBGvXrlWZnqurKywsLODo6Ihu3brBxcUF27dvF3pAlITMzEwAgLa2ttI2HR0dYTtjjDHGGCtZPBSCfXaePHmCjIwMlWP43d3dkZOTg3///Reenp5CeLly5UTxFN2v846xz+v58+eIjo7GH3/8IUw2qKDqZrI4N9PFcfPmTWhoaCjdRKtj2bJlmDJlCq5cuSKaH6E4ee/atSsmTpyIjRs3omvXrrh69SpOnTqF+fPnFzktALh+/ToAoH79+iq3GxkZAYDQIFShQgWlOK6urqJGkuvXryM1NRWWlpYq08x7XfMrh8OHDyMyMhJHjx5FRkaGaFtqaqqogUOV69ev49y5c7CwsCgwH3fu3IGNjQ0MDAyUzksdRkZGooae4jI3N0dAQIDKbWvWrMHbt29RtWpV3LhxQwivWbMmVq1aJQwNyW39+vUwMjLCkydPMHPmTNy+fVvUWJOZman0mbK2ti5SnhXpvX79Wmnb5zYJJ2OMMcbY54QbFtgXQSqVqgwnogL3Cw4OxpEjRzB48GB4eXnBwMAAOTk5aNy4sdKEewA++RuXlStXIjQ0FEFBQRg8eDAsLS0hlUoRExOj1iR6eXl4eMDb2xsrV65E165dsXLlSshkMgQHBxcrf4oyXbFihcqbyuKsjJGTkwNLS0usWrVK5fa8N/qqruHNmzfRoEEDuLm5YerUqbC3t4dMJsO2bdswbdo0lXVBVT4aNmyIIUOGqNxesWJFNc6mcG5ubkhISMCbN28+2KogirKsU6eOyu23bt0S9SYCgHr16gmrQrRo0QKVK1fGd999h1OnTkFDQwNr1qxBWFiYaJ/CPp952djYAJD3aLG3txdtS0pKKnT1CcYYY4wxVjzcsMA+OxYWFtDT08PVq1eVtl25cgUaGhpKNxXFkZycjL///hvR0dEYPXq0EK54qq6ugoYmFJezszNycnJw6dKlIk24uG7dOjg5OWHDhg2ifBU00WJhunbtip9++glJSUlYvXo1mjVrVuwJ+ZydnQEAlpaW+T4tBwAHBwcAqq9F3nrh7OyMPXv2oE6dOsVu+NmyZQtev36NzZs3i3q/qFpNI7/r7ezsjLS0tALPC5Cf299//420tDRRrwVV9V2VFi1a4OjRo1i/fr1oqEJJuX37No4cOYLevXsLq5go5OTkoEuXLli9enWBK08YGBggMjISYWFhWLt2LTp06IDAwEDs3r37vfKm+CycPHlS1Ijw4MED3Lt3Dz/88MN7pc8YY4wxxlTjORbYZ0cqlaJRo0b4888/hZnlAeDRo0dYvXo16tatK3SZf9/jAMpPTRWz96tLX18fANReLlAdQUFB0NDQwJgxY5Selhf0lFfVOR07dgxHjx4tdl46duwIiUSCfv364datW+jcuXOx0woMDISRkRHGjx+vchlLxRKhNjY28PLywrJly0Td53fv3o1Lly6J9gkODkZ2djbGjh2rlF5WVpZa10VVuaWmpiI2NlYprr6+vso0g4ODcfToUezcuVNpW0pKCrKysgAATZs2RVZWlmgpy+zsbMyaNavQfALyeT5sbGwwcOBAXLt2TWn748eP8csvv6iVliqK3gpDhgxBu3btRK/g4GD4+fnl2zskt++++w5ly5bFxIkTAcivaUBAgOhVVJ6ennBzc8PChQuRnZ0thM+bNw8SieS9V8pgjDHGGGOqcY8F9ln65ZdfsHv3btStWxc9e/aEpqYmFixYgNevX+PXX38tkWMYGRmhXr16+PXXX/H27VvY2dlh165duH37dpHS8fb2BgD07dsXgYGBkEql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du3aHtUjMDCQqKgoj/bxRnBwMMHBwWVebkFBAYGBgV7vX61atTKsjRBCCCGEEJWPDIUQ4joVFRVl+6lWrRqKotge//7774SFhbFq1SratWtHUFAQ33//PQcPHmTgwIFERkYSGhpKhw4d+Pbbb+3KLT0UQlEUPvroIwYPHkxISAiNGzfmyy+/tK0vPRTCOmRhzZo1NGvWjNDQUPr162cXCCksLOSZZ56hevXqRERE8PzzzzN69GinQwpKDoWYO3cukydPZufOnSiKgqIozJ07F4Dz58/z6KOPUrt2bcLDw+nVqxc7d+60lTNp0iRuvvlmPvroIxISEqhSpQoAq1evplu3brY63XnnnRw8eNC2X0JCAgC33HILiqKQlJQEOA6FuHz5Ms888wx16tShSpUqdOvWjS1btji017p162jfvj0hISF06dLFLii0c+dOevbsSVhYGOHh4bRr146tW7cato0QQgghhBDlSQILQtzAXnjhBaZOncqePXto3bo1OTk5DBgwgHXr1vHLL7/Qr18/7rrrLo4cOeK0nMmTJzNs2DB+/fVXBgwYwKhRozh79qzh9nl5ebzxxht8+umnbNy4kSNHjjBhwgTb+tdff53PP/+cjz/+mE2bNpGdnc2yZcvcPq7hw4fz17/+lRYtWpCVlUVWVhbDhw8H4J577uHUqVOsWrWKbdu20bZtW3r37m1X3wMHDrBkyRJSUlJsQylyc3MZP348W7duZd26dfj5+TF48GAsFgsAP//8MwDffvstWVlZpKSk6NbtueeeY8mSJXzyySds376dRo0a0bdvX4f2evHFF3nzzTfZunUr/v7+PPzww7Z1o0aNIiYmhi1btrBt2zZeeOEFAgIC3G4fIYQQQgghypQqhLjuffzxx2q1atVsj9evX68C6rJly1zu26JFC/Xdd9+1Pa5fv7769ttv2x4D6ksvvWR7nJOTowLqqlWr7J7r3LlztroA6oEDB2z7zJ49W42MjLQ9joyMVKdPn257XFhYqMbFxakDBw50+xgnTpyotmnTxm6btLQ0NTw8XM3Pz7db3rBhQ/WDDz6w7RcQEKCeOnXK8LlUVVVPnz6tAuquXbtUVVXV9PR0FVB/+eUXu+1Gjx5tq3dOTo4aEBCgfv7557b1BQUFat26ddVp06apqlrcXt9++61tm5UrV6qAeunSJVVVVTUsLEydO3eu0/oJIYQQQghxtUiPBSFuYO3bt7d7nJOTw4QJE2jWrBnVq1cnNDSUPXv2uOyx0Lp1a9vfVatWJTw8nFOnThluHxISQsOGDW2Po6OjbdtfuHCBkydP0rFjR9t6k8lEu3btPDo2PTt37iQnJ4eIiAhCQ0NtP+np6XbDGurXr++QS2L//v2MHDmSBg0aEB4eTnx8PIDLtinp4MGDXLlyha5du9qWBQQE0LFjR/bs2WO3bck2jY6OBrC10fjx43n00Ufp06cPU6dOtau7EEIIIYQQV5skbxTiBla1alW7xxMmTGDt2rW88cYbNGrUiODgYIYOHUpBQYHTckp3w1cUxTZEwN3t1aswQU1OTg7R0dGkpqY6rCs5a0PpdgG46667qF+/Ph9++CF169bFYrHQsmVLl23jrZJtZJ1Nw9qmkyZN4t5772XlypWsWrWKiRMnsmDBAgYPHlwudRFCCCGEEMIZ6bEghLDZtGkTDz74IIMHD6ZVq1ZERUWRkZFxVetQrVo1IiMj7RIams1mtm/f7lE5gYGBmM1mu2Vt27blxIkT+Pv706hRI7ufWrVqGZZ15swZ9u7dy0svvUTv3r1p1qwZ586dc3g+a12NNGzYkMDAQDZt2mRbduXKFbZs2ULz5s09Or6bbrqJcePG8c0335CcnMzHH3/s0f5CCCGEEEKUFQksCCFsGjdubEtYuHPnTu69916nPQ/Ky9NPP82UKVNYvnw5e/fuZcyYMZw7d852594d8fHxpKens2PHDv744w8uX75Mnz596Ny5M4MGDeKbb74hIyODzZs38+KLLzqdVaFGjRpEREQwZ84cDhw4wHfffcf48ePttqlTpw7BwcGsXr2akydPcuHCBYdyqlatyl/+8heeffZZVq9eze7du/nTn/5EXl4ejzzyiFvHdenSJZ566ilSU1M5fPgwmzZtYsuWLTRr1sztthFCCCGEEKIsSWBBCGHz1ltvUaNGDbp06cJdd91F3759adu27VWvx/PPP8/IkSN54IEH6Ny5M6GhofTt29c29aM7hgwZQr9+/ejZsye1a9dm/vz5KIrC119/Tffu3XnooYe46aabGDFiBIcPHyYyMtKwLD8/PxYsWMC2bdto2bIl48aNY/r06Xbb+Pv788477/DBBx9Qt25dBg4cqFvW1KlTGTJkCPfffz9t27blwIEDrFmzhho1arh1XCaTiTNnzvDAAw9w0003MWzYMPr378/kyZPdbhshhBBCCCHKkqJejYHNQgjhA4vFQrNmzRg2bBj//Oc/K7o6QgghhBBCiBIkeaMQotI5fPgw33zzDT169ODy5cvMmjWL9PR07r333oqumhBCCCGEEKIUGQohhKh0/Pz8mDt3Lh06dKBr167s2rWLb7/9VvIICCGEEEIIUQnJUAghhBBCCCGEEEJ4TXosCCGEEEIIIYQQwmsSWBBCCCGEEEIIIYTXJLAghBBCCCGEEEIIr0lgQQghhBBCCCGEEF6TwIIQQgghhBBCCCG8JoEFIYQQQgghhBBCeE0CC0IIIYQQQgghhPCaBBaEEEIIIYQQQgjhtf8H7JRZoOuwMFAAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for k in results.keys():\n", + " if 'Low' in k:\n", + " line = '--+'\n", + " elif 'Medium' in k:\n", + " line = '-o'\n", + " else:\n", + " line = '--'\n", + "\n", + " if '1' in k:\n", + " colour = 'red'\n", + " print(results[k]['phi'])\n", + " elif '2' in k:\n", + " colour = 'green'\n", + " elif '3' in k:\n", + " colour = 'blue'\n", + " plt.plot(results[k]['phi'], line, color=colour, label=k+' - MSE phi')\n", + " \n", + "plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')\n", + "plt.xlabel('Training iterations')\n", + "plt.ylabel('Normalised MSE')\n", + "plt.title('Normalised MSE of phi parameters during training\\non artificially federated CIFAR-10\\nunder different target heterogeneity conditions\\nand using different numbers of mixture components')\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a1db253c-f175-41f8-852e-988acd0f1445", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "29131b53-2dba-4a5f-a6e9-254314bf4cf8", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "afc1151f-476a-4669-b215-35ae64ff87cd", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e3e76b4c-675e-4a46-b600-36ece1a819e5", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python [conda env:v310] *", + "language": "python", + "name": "conda-env-v310-py" + }, + "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.10.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/publications/mdm/mdm_paper/notebooks/cifar10_visualisations.ipynb b/publications/mdm/mdm_paper/notebooks/cifar10_visualisations.ipynb new file mode 100644 index 0000000..fb04e25 --- /dev/null +++ b/publications/mdm/mdm_paper/notebooks/cifar10_visualisations.ipynb @@ -0,0 +1,241 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "47be4a41-58e1-44e2-bd52-a366cf901fb9", + "metadata": {}, + "source": [ + "This notebook visualizes CIFAR10 users using various methods of generating simulation users." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "77d25f5d-0b22-48fe-999f-74e1f0bc6ddf", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "from sklearn.manifold import TSNE\n", + "import joblib\n", + "\n", + "from ramsay.data.sampling import get_data_sampler\n", + "from polya_mixture.datasets.cifar10_dataset import load_and_preprocess\n", + "from polya_mixture.datasets.sampler import DirichletDataSampler" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "25e2c77a-1a4b-469f-abaf-8ad552f71747", + "metadata": {}, + "outputs": [], + "source": [ + "# Functions to generate users\n", + "\n", + "def generate_mixture_users(num_users, alphas, phi, num_samples_dists, all_labels):\n", + " users = []\n", + " ks = []\n", + " for _ in range(num_users):\n", + " k = np.random.choice(range(len(alphas)), p=phi)\n", + " d = num_samples_dists[k]\n", + " n = np.random.choice(range(len(d)), p=d)\n", + "\n", + " sampler = DirichletDataSampler(alphas[k], all_labels)\n", + " idxs = sampler(n)\n", + " y = np.array(all_labels)[idxs]\n", + " full_y = np.zeros(62)\n", + " vals, count = np.unique(y, return_counts=True)\n", + " full_y[vals] = count\n", + " users.append(full_y)\n", + " return np.array(users)\n", + "\n", + "def generate_single_dirichlet_users(num_users, alpha, user_len_sampler, all_labels):\n", + " sampler = DirichletDataSampler(alpha, all_labels)\n", + " users = []\n", + " for _ in range(num_users):\n", + " n = user_len_sampler()\n", + " idxs = sampler(n)\n", + " y = np.array(all_labels)[idxs]\n", + " full_y = np.zeros(62)\n", + " vals, count = np.unique(y, return_counts=True)\n", + " full_y[vals] = count\n", + " users.append(full_y)\n", + " return np.array(users)\n", + "\n", + "def generate_uniform_users(num_users, user_len_sampler, all_labels):\n", + " sampler = get_data_sampler('random', len(all_labels))\n", + " users = []\n", + " for _ in range(num_users):\n", + " n = user_len_sampler()\n", + " idxs = sampler(n)\n", + " y = np.array(all_labels)[idxs]\n", + " full_y = np.zeros(62)\n", + " vals, count = np.unique(y, return_counts=True)\n", + " full_y[vals] = count\n", + " users.append(full_y)\n", + " return np.array(users)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "d838856d-85f1-4f14-b098-85b158b5d462", + "metadata": {}, + "outputs": [], + "source": [ + "# Load Cifar10 and get all labels\n", + "data_dir = 'data/cifar10'\n", + "_, all_labels, _, _ = load_and_preprocess(os.path.join(data_dir, 'cifar10_train.p'))" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "8034bc9f-c053-48e8-a91f-fe1f8a2b8d90", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "dict_keys(['alphas', 'phi'])\n", + "alpha_mixture [[0.2790543 0.19542773 1.7441087 0.9729872 0.18570527 0.09938517\n", + " 0.09327706 0.10400821 3.144703 1.0748252 ]\n", + " [0.26441148 0.17979808 0.11472267 0.99709547 1.2816628 1.3844566\n", + " 0.98972297 0.4767252 1.1671178 0.0879145 ]]\n", + "phi_mixture [0.9021526 0.09784738]\n", + "num_samples_distribution_mixture (2, 500)\n", + "(2,) (2, 10) (2, 500)\n" + ] + }, + { + "data": { + "image/png": "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hikiIiLSF6XxGgc/EREREZEuMDAlCtHPb/25z+dERESkDPuYEoXod9N/h9iYWI4kJyIiChEDU6IQxcXEofLwWKD2M8D2IDCdlxUREVEw2JRPFA61tc5ppjjJPhERUdAYmBKFg83mnPeUk+wTEREFjdNFEREREZGqOF0UERERERkKA1MiIiIi0gUGpkRERESkCwxMiYiIiEgXGJgSERERkS4wMCUiIiIiXWBgSkRERES6wMCUiIiIiHSBgSkRERER6QIDUyIiIiLSBQamRERERKQLDEyJiIiISBcYmBIRERGRLsRpnYBQCSEAAN3d3RqnhIiIiIjkuOI0V9zmjeED056eHgBAWlqaxikhIiIiIl96enqQlJTk9XWL8Be66pzD4UBnZydGjhwJi8WidXKiXnd3N9LS0nD69GmMGjVK6+RQmDBfzYn5ak7MV/Myct4KIdDT04MJEyYgJsZ7T1LD15jGxMRg4sSJWieDBhk1apThLhryj/lqTsxXc2K+mpdR89ZXTakLBz8RERERkS4wMCUiIiIiXWBgSmGVkJCAqqoqJCQkaJ0UCiPmqzkxX82J+Wpe0ZC3hh/8RERERETmwBpTIiIiItIFBqZEREREpAsMTImIiIhIFxiYEhEREZEuMDClsOvt7cXtt98Oi8WCvXv3Sl7bv38/CgoKkJiYiLS0NKxatUqbRJIiJ06cwIIFCzBp0iQMHz4c2dnZqKqqwpUrVyT7MV+N6ZVXXkFmZiYSExMxbdo0fPjhh1oniQKwcuVK/OAHP8DIkSMxduxYzJkzB0ePHpXs8+2336KsrAzXX389rrvuOjz00EM4f/68RimmYNTW1sJiseDJJ590bzNzvjIwpbB75plnMGHChCHbu7u7UVxcjIyMDOzZswcvvPAC7HY7NmzYoEEqSYkjR47A4XBg/fr1OHToEP74xz+irq4OFRUV7n2Yr8a0ZcsWLFmyBFVVVfj4449x2223Yfbs2bhw4YLWSSOFmpubUVZWht27d6O+vh59fX0oLi7GV1995d7nqaeewrvvvos333wTzc3N6OzsxIMPPqhhqikQH330EdavX4+pU6dKtps6XwVRGL333ntiypQp4tChQwKA+OSTT9yvrV27ViQnJ4ve3l73tvLycpGTk6NBSilYq1atEpMmTXI/Z74a05133inKysrczwcGBsSECRPEypUrNUwVheLChQsCgGhubhZCCHHp0iUxbNgw8eabb7r3OXz4sAAg2tratEomKdTT0yNuuukmUV9fL6ZPny4WL14shDB/vrLGlMLm/PnzePzxx/H6669jxIgRQ15va2vDPffcg/j4ePe22bNn4+jRo7h48WIkk0ohuHz5MlJSUtzPma/Gc+XKFezZswczZ850b4uJicHMmTPR1tamYcooFJcvXwYA9/W5Z88e9PX1SfJ5ypQpSE9PZz4bQFlZGe677z5J/gHmz1cGphQWQgjMnz8fpaWluOOOO2T3OXfuHFJTUyXbXM/PnTunehopdJ9//jlWr16NX/3qV+5tzFfj+eKLLzAwMCCbb8wzY3I4HHjyySdx991347vf/S4A5/UXHx+P0aNHS/ZlPuvf5s2b8fHHH2PlypVDXjN7vjIwJZ9sNhssFovPx5EjR7B69Wr09PTg2Wef1TrJpIDSfPV05swZ3HvvvfjpT3+Kxx9/XKOUE5GcsrIyHDx4EJs3b9Y6KRSi06dPY/Hixdi0aRMSExO1Tk7ExWmdANK3pUuXYv78+T73ycrKQmNjI9ra2oas33vHHXdg3rx5eO211zBu3LghowZdz8eNGxfWdJNvSvPVpbOzE0VFRcjPzx8yqIn5ajw33HADYmNjZfONeWY8ixYtwtatW9HS0oKJEye6t48bNw5XrlzBpUuXJLVrzGd927NnDy5cuIDvf//77m0DAwNoaWnBmjVr8MEHH5g6XxmYkk9jxozBmDFj/O738ssv47nnnnM/7+zsxOzZs7FlyxZMmzYNAJCXl4dly5ahr68Pw4YNAwDU19cjJycHycnJ6nwAkqU0XwFnTWlRURFyc3OxceNGxMRIG1qYr8YTHx+P3NxcbN++HXPmzAHgbArevn07Fi1apG3iSDEhBH7zm9/g7bffRlNTEyZNmiR5PTc3F8OGDcP27dvx0EMPAQCOHj2KU6dOIS8vT4skkwIzZszAgQMHJNt++ctfYsqUKSgvL0daWpq581Xr0VdkTsePHx8yKv/SpUsiNTVVlJSUiIMHD4rNmzeLESNGiPXr12uXUPKpo6NDTJ48WcyYMUN0dHSIs2fPuh8uzFdj2rx5s0hISBCvvvqq+PTTT8XChQvF6NGjxblz57ROGin0xBNPiKSkJNHU1CS5Nr/++mv3PqWlpSI9PV00NjaKf/zjHyIvL0/k5eVpmGoKhueofCHMna8MTEkVcoGpEELs27dPWK1WkZCQIG688UZRW1urTQJJkY0bNwoAsg9PzFdjWr16tUhPTxfx8fHizjvvFLt379Y6SRQAb9fmxo0b3ft888034te//rVITk4WI0aMEHPnzpX8sCRjGByYmjlfLUIIoUVNLRERERGRJ47KJyIiIiJdYGBKRERERLrAwJSIiIiIdIGBKRERERHpAgNTIiIiItIFBqZEREREpAsMTImIiIhIFxiYEhEREZEuMDAlIiIiIl1gYEpEREREusDAlIiIiIh0gYEpEREREenC/wNeOWNioSJVSgAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Load single dirichlet saved params\n", + "mixture = True\n", + "\n", + "if not mixture:\n", + " # load learned parameters\n", + " params = joblib.load(os.path.join('mle_params', 'cifar10_1_mixture', 'polya-mixture.joblib'))\n", + " print(params.keys())\n", + " alpha_one_component = np.array(params['alphas'][0])\n", + " \n", + " num_samples_distribution_one_component = joblib.load(os.path.join('num_samples_distribution', 'cifar10_1_mixture.joblib'))\n", + " num_samples_distribution_one_component = num_samples_distribution_one_component.numpy().reshape(-1,)\n", + " \n", + " len_sampler = lambda: np.random.choice(range(len(num_samples_distribution_one_component)), p=num_samples_distribution_one_component)\n", + "\n", + " # true distribution\n", + " true_alpha = [0.3, 0.2, 0.1, 1, 1.2, 1.3, 0.8, 0.5, 1.2, 0.1]\n", + " true_len_sampler = lambda: 20\n", + "\n", + " # create distributions\n", + " num_users = 500\n", + " true_users = generate_single_dirichlet_users(num_users, true_alpha, true_len_sampler, all_labels)\n", + " simulated_single_dirichlet_users = generate_single_dirichlet_users(num_users, alpha_one_component, len_sampler, all_labels)\n", + " simulated_uniform_users = generate_uniform_users(num_users, len_sampler, all_labels)\n", + "\n", + " # Run TSNE on the label counts of all users\n", + " tsne2 = TSNE(n_components=2)\n", + " X = np.vstack([true_users, simulated_single_dirichlet_users, simulated_uniform_users])\n", + " X = X / X.sum(axis=1, keepdims=True) # This will normalize the counts to proportions to ignore num sample per user effects\n", + " X_2dim = tsne2.fit_transform(X)\n", + "\n", + " N = num_users\n", + " plt.figure(figsize=(8, 5))\n", + " plt.title('TSNE visualisation of user label distributions in CIFAR10 dataset')\n", + " plt.scatter(X_2dim[:N, 0], X_2dim[:N, 1], s=1, color='red', label='true users')\n", + " plt.scatter(X_2dim[N:2*N, 0], X_2dim[N:2*N, 1], s=5, color='green', label='single dirichlet simulation')\n", + " plt.scatter(X_2dim[2*N:3*N, 0], X_2dim[2*N:3*N, 1], s=1, color='blue', label='Simulated users: partitioned uniformly randomly')\n", + " plt.legend(fontsize=10)\n", + "\n", + "\n", + "else:\n", + " # Load two component mixture dirichlet saved params\n", + " params = joblib.load(os.path.join('mle_params', 'cifar10_2_mixture', 'polya-mixture.joblib'))\n", + " print(params.keys())\n", + " alpha_mixture = np.array(params['alphas'])\n", + " print('alpha_mixture', alpha_mixture)\n", + " phi_mixture = np.array(params['phi'])\n", + " phi_mixture /= sum(phi_mixture)\n", + " print('phi_mixture', phi_mixture)\n", + " \n", + " num_samples_distribution_mixture = joblib.load(os.path.join('num_samples_distribution', 'cifar10_2_mixture.joblib'))\n", + " num_samples_distribution_mixture = num_samples_distribution_mixture.numpy()\n", + " print('num_samples_distribution_mixture', num_samples_distribution_mixture.shape)\n", + " print(phi_mixture.shape, alpha_mixture.shape, num_samples_distribution_mixture.shape)\n", + "\n", + " # true distribution\n", + " #true_alpha = [[1.8]*10, [0.2]*10]\n", + " #true_phi = [0.3, 0.7]\n", + " true_alpha = [[0.3, 0.2, 0.1, 1, 1.2, 1.3, 0.8, 0.5, 1.2, 0.1], [0.3, 0.2, 1.8, 1, 0.2, 0.1, 0.1, 0.1, 3.2, 1.1]]\n", + " true_phi = [0.1, 0.9]\n", + "\n", + " # generate users\n", + " num_users = 500\n", + " # TODO change num_samples_distribution_mixture so it's not just tied to learned parameters, but is the actual true distribution\n", + " true_users = generate_mixture_users(num_users, true_alpha, true_phi, num_samples_distribution_mixture, all_labels)\n", + " simulated_dirichlet_mixture_users = generate_mixture_users(num_users, alpha_mixture, phi_mixture, num_samples_distribution_mixture, all_labels)\n", + " len_sampler = lambda: 20\n", + " simulated_uniform_users = generate_uniform_users(num_users, len_sampler, all_labels)\n", + "\n", + " # Run TSNE on the label counts of all users\n", + " tsne2 = TSNE(n_components=2)\n", + " X = np.vstack([true_users, simulated_dirichlet_mixture_users, simulated_uniform_users]) \n", + " X = X / X.sum(axis=1, keepdims=True) # This will normalize the counts to proportions to ignore num sample per user effects\n", + " X_2dim = tsne2.fit_transform(X)\n", + " \n", + " # plot\n", + " N = num_users\n", + " plt.figure(figsize=(8, 5))\n", + " plt.title('TSNE visualisation of user label distributions in CIFAR10 dataset')\n", + " plt.scatter(X_2dim[:N, 0], X_2dim[:N, 1], s=1, color='red', label='true users')\n", + " plt.scatter(X_2dim[N:2*N, 0], X_2dim[N:2*N, 1], s=5, color='green', label='single mixture dirichlet simulation')\n", + " plt.scatter(X_2dim[2*N:3*N, 0], X_2dim[2*N:3*N, 1], s=1, color='blue', label='Simulated users: partitioned uniformly randomly')\n", + " plt.legend(fontsize=10)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "05dc6205-7096-412a-9188-f1086cadbda0", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.10.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/publications/mdm/mdm_paper/notebooks/femnist_visualisations.ipynb b/publications/mdm/mdm_paper/notebooks/femnist_visualisations.ipynb new file mode 100644 index 0000000..5bd9046 --- /dev/null +++ b/publications/mdm/mdm_paper/notebooks/femnist_visualisations.ipynb @@ -0,0 +1,516 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "47be4a41-58e1-44e2-bd52-a366cf901fb9", + "metadata": {}, + "source": [ + "This notebook visualizes CIFAR10 users using various methods of generating simulation users." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "77d25f5d-0b22-48fe-999f-74e1f0bc6ddf", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "from sklearn.manifold import TSNE\n", + "import joblib\n", + "\n", + "from ramsay.data.sampling import get_data_sampler\n", + "from polya_mixture.datasets.femnist_dataset import _load_h5_into_dict\n", + "from polya_mixture.datasets.sampler import DirichletDataSampler" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "59530d17-5a4c-43f2-b2f8-b6e91ab4e2c8", + "metadata": {}, + "outputs": [], + "source": [ + "# Helper functions\n", + "\n", + "def load_femnist_as_dict(data_dir):\n", + " h5_file_path = os.path.join(data_dir, 'fed_emnist_train.h5')\n", + " digits_only = False\n", + " numpy_to_tensor = lambda x: x\n", + " user_id_to_data = _load_h5_into_dict(h5_file_path, digits_only,\n", + " numpy_to_tensor)\n", + " return user_id_to_data\n", + "\n", + "def get_all_labels(user_id_to_data):\n", + " all_labels = []\n", + " for _, y in user_id_to_data.values():\n", + " all_labels.append(y)\n", + " return np.hstack(all_labels)\n", + "\n", + "\n", + "def get_femnist_len_sampler(user_id_to_data):\n", + " histo = np.zeros(500)\n", + " for _, y in user_id_to_data.values():\n", + " num_samples = len(y)\n", + " histo[num_samples] += 1\n", + "\n", + " p = histo / sum(histo) \n", + " len_sampler = lambda p=p: np.random.choice(range(len(p)), p=p)\n", + " return len_sampler" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "25e2c77a-1a4b-469f-abaf-8ad552f71747", + "metadata": {}, + "outputs": [], + "source": [ + "# Functions to generate users\n", + "\n", + "def generate_true_users(user_id_to_data):\n", + " users = []\n", + " for _, y in user_id_to_data.values():\n", + " labels, counts = np.unique(y, return_counts=True)\n", + " full_y = np.zeros(62)\n", + " full_y[labels] = counts\n", + " users.append(full_y)\n", + " return np.array(users)\n", + "\n", + "\n", + "def generate_mixture_users(num_users, alphas, phi, num_samples_dists, all_labels):\n", + " users = []\n", + " ks = []\n", + " for _ in range(num_users):\n", + " k = np.random.choice(range(len(alphas)), p=phi)\n", + " d = num_samples_dists[k]\n", + " n = np.random.choice(range(len(d)), p=d)\n", + "\n", + " sampler = DirichletDataSampler(alphas[k], all_labels)\n", + " idxs = sampler(n)\n", + " y = np.array(all_labels)[idxs]\n", + " full_y = np.zeros(62)\n", + " vals, count = np.unique(y, return_counts=True)\n", + " full_y[vals] = count\n", + " users.append(full_y)\n", + " return np.array(users)\n", + "\n", + "def generate_single_dirichlet_users(num_users, alpha, user_len_sampler, all_labels):\n", + " sampler = DirichletDataSampler(alpha, all_labels)\n", + " users = []\n", + " for _ in range(num_users):\n", + " n = user_len_sampler()\n", + " idxs = sampler(n)\n", + " y = np.array(all_labels)[idxs]\n", + " full_y = np.zeros(62)\n", + " vals, count = np.unique(y, return_counts=True)\n", + " full_y[vals] = count\n", + " users.append(full_y)\n", + " return np.array(users)\n", + "\n", + "def generate_uniform_users(num_users, user_len_sampler, all_labels):\n", + " sampler = get_data_sampler('random', len(all_labels))\n", + " users = []\n", + " for _ in range(num_users):\n", + " n = user_len_sampler()\n", + " idxs = sampler(n)\n", + " y = np.array(all_labels)[idxs]\n", + " full_y = np.zeros(62)\n", + " vals, count = np.unique(y, return_counts=True)\n", + " full_y[vals] = count\n", + " users.append(full_y)\n", + " return np.array(users)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "d838856d-85f1-4f14-b098-85b158b5d462", + "metadata": {}, + "outputs": [], + "source": [ + "# Load femnist and get all labels\n", + "data_dir = 'data/femnist'\n", + "user_id_to_data = load_femnist_as_dict(data_dir)\n", + "all_labels = get_all_labels(user_id_to_data)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "37a3dee8-e3fd-40ce-9577-9f84a544c818", + "metadata": {}, + "outputs": [], + "source": [ + "num_users = len(user_id_to_data.keys())" + ] + }, + { + "cell_type": "markdown", + "id": "92e05e84-3154-4460-afb0-2cba1a665aa0", + "metadata": {}, + "source": [ + "# One mixture component" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "8034bc9f-c053-48e8-a91f-fe1f8a2b8d90", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "dict_keys(['alphas', 'phi'])\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAq4AAAHDCAYAAADlfZgfAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy81sbWrAAAACXBIWXMAAA9hAAAPYQGoP6dpAACmPUlEQVR4nOzde1xT9f8H8NcABRRBUMQrIKappaaWCY6LpXgpK9OsNMPKitKszBRn4cScZLev3zTprnnpm1nW92dqgAqCeKnMS99KUwQ0r3kBb6hj5/fH2GFnO7vBBhu8no8HD912Lp+dnW3vfc778/4oBEEQQERERETk5rzqugFERERERPZg4EpEREREHoGBKxERERF5BAauREREROQRGLgSERERkUdg4EpEREREHoGBKxERERF5BAauREREROQRGLgSERERkUdg4EouN2HCBERGRtZ1M2TboVAooFara70tdbVfR/z000+IiYlB06ZNoVAosGfPnrpuUo3U5DxUKBSYPHmy09pSVFQEhUKBpUuXVmv9pUuXQqFQoKioSLwvISEBCQkJTmmfLabnr1qthkKhwD///FMr+4+MjMSECRNqZV+OcpfPO9Lj61H/MHCtAwqFwq6/nJwcAMCZM2fw4osvomvXrvD390erVq3Qr18/zJgxA5cuXRK3O2HCBCgUCvTs2RNyM/mafvkavjwt/aWnp7v8WNRn69evd/vg1JIbN27goYcewrlz5/Dee+9h+fLliIiIqOtmkZMVFBRArVbjwoULdd0UM+7ctrpw6tQpTJs2DV27dkWTJk3QtGlT9O3bF2+88YbkGCUkJODWW2+VrBsZGWnxc768vFxcrqKiAm3btoVCocCGDRtk22H4kWL4a9SoESIjIzFlyhTZ1yozMxNPPfUUbr31Vnh7e1sNInU6HRYsWICOHTvCz88PPXv2xJdffunQcXImjUaD7777rs72b+z333+HWq2W/FhtqHzqugEN0fLlyyW3v/jiC2RlZZnd361bN5w7dw633347ysrK8OSTT6Jr1644e/Ys9u3bhyVLluC5555DQECAZL39+/fj22+/xahRo+xqz6OPPorhw4eb3d+7d28Hn5m8jz/+GDqdzinbcrarV6/Cx8c1b4P169dj8eLFssGrK/frDIcPH0ZxcTE+/vhjTJw4sa6bQ3bIzMx0eJ2CggLMmTMHEyZMQPPmze1erzbOX2ttO3DgALy83LPfxRWfdz/99BOGDx+OS5cu4bHHHkPfvn0BAD///DPS09OxdetWm6//bbfdhldeecXs/saNG4v/37x5M06cOIHIyEisXLkSw4YNs7i9JUuWICAgAJcvX8amTZvw/vvvY/fu3cjPz5cst2rVKnz11Vfo06cP2rZta7WNs2bNQnp6Op5++mnccccd+P777zF27FgoFAo88sgjVtd1BY1Gg9GjR+OBBx6o9X2b+v333zFnzhwkJCQ0+B5k9/3mrMcee+wxye0dO3YgKyvL7H4AeOutt1BSUoJt27YhJiZG8lhZWZnkQwcA/P390aFDB6SlpeHBBx+EQqGw2Z4+ffrI7ttZGjVq5LJt15Sfn1+D2q+9Tp8+DQAOBTN1TRAElJeXw9/fv66bUidMPwucTafT4fr16/Dz86vz89fX17dO92+Nsz/vLly4gJEjR8Lb2xu//vorunbtKnl83rx5+Pjjj21up127djY/51esWIE+ffogKSkJKpUKly9fRtOmTWWXHT16NFq2bAkAePbZZ/HII4/gq6++wq5du9CvXz9xOY1Gg48//hiNGjXCvffei99++012e3///TfeeecdTJo0CYsWLQIATJw4EfHx8Xj11Vfx0EMPwdvb2+bzpPrPPX+ykujw4cPw9vZG//79zR4LDAw0+wLx8vLCa6+9hn379mHt2rUua9fbb78NhUKB4uJis8dmzpyJxo0b4/z58wDkc4z+85//oG/fvmjWrBkCAwPRo0cPLFy4UHzccDnKlFxu3/fff4977rkHbdu2ha+vLzp16oS5c+eioqLC5vMwzdW7ePEiXnrpJURGRsLX1xetWrXC4MGDsXv3bnGZvLw8PPTQQwgPD4evry86dOiAl19+GVevXhWXmTBhAhYvXizuw/Bnab8A8Ouvv2LYsGEIDAxEQEAA7r77buzYsUP2+W/btg1Tp05FaGgomjZtipEjR+LMmTM2ny+g71WJjY1F06ZN0bx5c9x///34448/JG2Pj48HADz00ENQKBRWcycdea1+/vlnDBkyBC1btoS/vz86duyIJ598UrKeTqfDv/71L9xyyy3w8/NDWFgYnn32WfF8MoiMjMS9996LH3/8Ebfffjv8/f3x4Ycf2nUMDN5++23ExMSgRYsW8Pf3R9++fbFmzRqLy69cuRI333wz/Pz8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Wq1du1YAIPz0008Wt5WXlycAEFauXCm5f+PGjWb3R0RECACEjRs32myjIMi//qav5fXr14Vbb71VuOuuuyT3G94TP//8s3hfcXGx4OfnJ4wcOVK876mnnhLatGkj/PPPP5L1H3nkESEoKEjcn+G99/nnn1tt80svvSQAEHbu3Cned/r0aSEoKMjsfRAfHy/Ex8eLt++//37hlltusbr9t956y2w7xs/Zy8tL+N///if7mPH5azgH7rvvPslyzz//vABA2Lt3ryAI1p+36TattS0iIkJISkoSbxuOU15ennjfxYsXhY4dOwqRkZFCRUWFIAhV53W3bt2Ea9euicsuXLhQACDs379fEARB+PXXX+0+/02ZnmeG59yiRQvh3Llz4v3ff/+9AED4v//7P6vbCw4OFnr16mX3/uPj481ed8N7xfTP+Hjfe++9woABA8TbH330keDj4yOcPn1asi3Da33gwAHhzJkzQlFRkfDZZ58J/v7+QmhoqHD58mWLbbvnnnvM3oPGj0VFRZndf/nyZQGAkJKSYvV533bbbUKbNm0kn4GZmZkCgGq/75s2bSo5zyytLwiCsH37drPvvl69egn33HOP1XbffffdQo8ePSTfVTqdToiJiRE6d+4s3vf1118LAIQtW7ZY3V5DwFQBNxcWFoa9e/ciOTkZ58+fR0ZGBsaOHYtWrVph7ty5stUDAGDcuHHo3Lkz0tLSLC5j8MwzzyArK8vsr3v37lbXe/jhh/HLL79ILg199dVX8PX1xf33329xvebNm+Py5ctml0uqy7j36eLFi/jnn38QGxuLK1eu4M8//3RoW82bN8fOnTtx/Phxu/Z3+fJl/PPPP4iJiYEgCPj1118dbn9FRQUyMzPxwAMPICoqSry/TZs2GDt2LPLz81FWViZZ55lnnpH0pMfGxqKiokI2dcPgxIkT2LNnDyZMmICQkBDx/p49e2Lw4MFYv369w213hCFfdt26dbhx44bsMl9//TWCgoIwePBg/PPPP+Jf3759ERAQgC1btkiW79ixI4YMGVLtNhm/lufPn0dpaSliY2MlqSEG0dHR4qAYAAgPD8f999+PH3/8ERUVFRAEAd988w1GjBgBQRAk7R8yZAhKS0tlt2vN+vXr0b9/f0nOYGhoKMaNG2dz3ebNm+PYsWN2XY62JD4+3ubngLFJkyZJbr/wwgsA4PJz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srKyoFQq8fzzz8PHxwcffvghrl27hgULFjj8XCx56623MGzYMERHR+Opp54Sy2EFBQVVe3pae1+rZcuW4YMPPsDIkSPRqVMnXLx4ER9//DECAwPFoDk+Ph7PPvss5s+fjz179iAxMRGNGjXCX3/9ha+//hoLFy6scVkgg3vuuQfvvvsuhg4dirFjx+L06dNYvHgxbrrpJkkemsGtt96KIUOGSMphAZD8KExPT8eWLVtw55134umnn0b37t1x7tw57N69G9nZ2Th37pxDbZw+fTqWL1+OoUOH4sUXXxTLYUVERMi20VhiYiJat26NAQMGICwsDH/88QcWLVqEe+65RxzsYzhHZ82ahUceeQSNGjXCiBEjqtXzDuh77+677z4MHToU27dvx4oVKzB27Fj06tVLXGbixIlIT0/HxIkTcfvtt2Pr1q2yAZkjbUtJScGXX36JYcOGYcqUKQgJCcGyZctw5MgRfPPNNw5fut68eTMmT56Mhx56CF26dIFWq8Xy5cvFHye1KTg4GGvXrsXw4cNx2223SWbO2r17N7788kubn9PWrFy5ErfddpvFqzr33XcfXnjhBezevVssCSinUaNGePHFF/Hqq69i48aNGDp0KABg3759Yk3SQ4cOobS0VAy0e/XqJV6ha9++PV566SW89dZbuHHjBu644w589913yMvLw8qVK21OPjB//nzcc889UCqVePLJJ3Hu3DmxjrHx1OiOvO/79u2L7OxsvPvuu2jbti06duyIO++8E/feey+WL1+OoKAgdO/eHdu3b0d2djZatGghWb979+5ISEhA3759ERISgp9//lkst2iwePFiKJVK9OjRA08//TSioqJw6tQpbN++HceOHcPevXsB6H/ke3t7480330RpaSl8fX1x1113oVWrVlaPS71Uy1UMSIa1skn79u0TXn31VaFPnz5CSEiI4OPjI7Rp00Z46KGHhN27d0uWNS6HZezGjRtCp06dHC6HJVcGRM7HH38sABCaNWsmXL161exx0/Iwa9asERITE4VWrVoJjRs3FsLDw4Vnn31WOHHihGS9X375RbjzzjvFZd59913Zcljbtm0T+vfvL/j7+wtt27YVpk+fLvz4449mpUNslcO6du2a8Oqrrwq9evUSmjVrJjRt2lTo1auX8MEHH0jW+f3334VBgwYJAQEBQsuWLYWnn35a2Lt3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2CM+Ph5xcXEYNWoUsrKycOTIEWzYsKHa227WrBmmTZuGl19+GcuWLcPhw4exe/duvP/++1i2bBkAICIiAgqFAuvWrcOZM2fEXlpTL730En788UccOXIEu3fvxpYtW6r9Olly1113YdGiRfj111/x888/Izk52ayX01jnzp3x888/48cff8TBgwfx+uuvm/1QiYyMxL59+3DgwAH8888/sj24zz//PI4ePYoXXngBf/75J77//nvMnj0bU6dOFfNb3ZH7toyIiKiW+Hj5IDU+FZnjM5Ean+qygVkAEBgYiK1bt2L48OHo0qULXnvtNbzzzjsYNmxYtbbn7e2N7777DpcuXcIdd9yBiRMnYtasWQAAPz8/2XXatm2Lbdu2oaKiAomJiejRowdeeuklNG/e3GLQ0r9/f3z88cdYuHAhevXqhczMTDFArqlvvvkGd9xxBx599FF0794d06dPt6s31JK5c+fi9ddfx/z589GtWzcMHToUP/zwAzp27AgAaNeuHebMmYOUlBSEhYVh8uTJstupqKjApEmTxG106dIFH3zwQbXbJeedd95Bhw4dEBsbi7Fjx2LatGlo0qSJxeWfffZZPPjgg3j44Ydx55134uzZs3j++eclyzz99NO4+eabcfvttyM0NBTbtm0z2067du2wfv167Nq1C7169UJycjKeeuopp72mrqIQPHV6jkplZWUICgpCaWkpAgMD67o5RERUS8rLy3HkyBF07NjRYoDWUG3btg1KpRKHDh2SDBYiciVr70lnxWusKkBEROTh1q5di4CAAHTu3BmHDh3Ciy++iAEDBjBopXqHgSsREZGHu3jxImbMmIGSkhK0bNkSgwYNwjvvvFPXzSJyOgauREREHu7xxx/H448/XtfNIHI5Ds4iIiIiIo/AwJWIiIiIPAIDVyIi8mh1OYsPEVWpjfcic1yJiMgjNW7cGF5eXjh+/DhCQ0PRuHFjiwX3ich1BEHA9evXcebMGXh5eYkzk7kCA1ciIvJIXl5e6NixI06cOIHjx4/XdXOIGrwmTZogPDzcpTNvMXAlIiKP1bhxY4SHh0Or1dZopiUiqhlvb2/4+Pi4/KoHA1ciIvJoCoUCjRo1sjq/OxHVDxycRUREREQegYErEREREXkEBq5ERERE5BEYuBIRERGRR2DgSkREREQegYErEREREXkEBq5ERERE5BEYuBIRERGRR2DgSkREREQegYErEREREXkEBq5ERERE5BEYuBIRERGRR2DgSkREREQegYErEREREXkEBq5ERERE5BEYuBIRERGRR2DgSkREREQegYErEREREXkEBq5ERERE5BEYuBIRERGRR3Bp4Dp//nzccccdaNasGVq1aoUHHngABw4ckCxTXl6OSZMmoUWLFggICMCoUaNw6tQpVzaLiIiIiDyQSwPX3NxcTJo0CTt27EBWVhZu3LiBxMREXL58WVzm5Zdfxv/93//h66+/Rm5uLo4fP44HH3zQlc0iIiIiIg+kEARBqK2dnTlzBq1atUJubi7i4uJQWlqK0NBQrFq1CqNHjwYA/Pnnn+jWrRu2b9+O/v3729xmWVkZgoKCUFpaisDAQFc/BSIiIiJykLPitVrNcS0tLQUAhISEAAB++eUX3LhxA4MGDRKX6dq1K8LDw7F9+3bZbVy7dg1lZWWSPyIiIiKq/2otcNXpdHjppZcwYMAA3HrrrQCAkydPonHjxmjevLlk2bCwMJw8eVJ2O/Pnz0dQUJD416FDB1c3nYiIiIjcQK0FrpMmTcJvv/2G//znPzXazsyZM1FaWir+HT161EktJCIiIiJ35lMbO5k8eTLWrVuHrVu3on379uL9rVu3xvXr13HhwgVJr+upU6fQunVr2W35+vrC19fX1U0mIiIiIjfj0h5XQRAwefJkrF27Fps3b0bHjh0lj/ft2xeNGjXCpk2bxPsOHDiAkpISREdHu7JpRERERORhXNrjOmnSJKxatQrff/89mjVrJuatBgUFwd/fH0FBQXjqqacwdepUhISEIDAwEC+88AKio6PtqihARERERA2HS8thKRQK2fs///xzTJgwAYB+AoJXXnkFX375Ja5du4YhQ4bggw8+sJgqYIrlsIiIiIjcm7PitVqt4+oKDFyJiIiI3JtH1nElIiIiIqouBq5ERERE5BEYuBIRERGRR2DgSkREREQegYErEREREXkEBq5ERERE5BEYuBIRERGRR2DgSkREREQegYErEREREXkEBq5ERERE5BEYuBIRERGRR2DgSkREREQegYErEREREXkEBq5ERERE5BEYuBIRERGRR2DgSkREREQegYErEREREXkEBq5ERERE5BEYuBIRERGRR2DgSkREREQegYErEREREXkEBq5ERERE5BEYuBIRERGRR2Dg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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Load single dirichlet saved params\n", + "\n", + "# load learned parameters\n", + "params = joblib.load(os.path.join('mle_params', 'femnist_learn_dirichlet_1_mixture', 'polya-mixture.joblib'))\n", + "print(params.keys())\n", + "alpha_one_component = np.array(params['alphas'][0])\n", + "\n", + "num_samples_distribution_one_component = joblib.load(os.path.join('num_samples_distribution', 'femnist_learn_dirichlet_1_mixture.joblib'))\n", + "num_samples_distribution_one_component = num_samples_distribution_one_component.numpy().reshape(-1,)\n", + "\n", + "len_sampler = lambda: np.random.choice(range(len(num_samples_distribution_one_component)), p=num_samples_distribution_one_component)\n", + "\n", + "# create distributions\n", + "true_users = generate_true_users(user_id_to_data)\n", + "simulated_single_dirichlet_users = generate_single_dirichlet_users(len(true_users), alpha_one_component, len_sampler, all_labels)\n", + "simulated_uniform_users = generate_uniform_users(len(true_users), len_sampler, all_labels)\n", + "\n", + "# Run TSNE on the label counts of all users\n", + "tsne2 = TSNE(n_components=2)\n", + "X = np.vstack([true_users, simulated_single_dirichlet_users])#, simulated_uniform_users])\n", + "X = X / X.sum(axis=1, keepdims=True) # This will normalize the counts to proportions to ignore num sample per user effects\n", + "X_2dim = tsne2.fit_transform(X)\n", + "\n", + "N = num_users\n", + "plt.figure(figsize=(8, 5))\n", + "plt.title('TSNE visualisation of user label distributions in CIFAR10 dataset')\n", + "plt.scatter(X_2dim[:N, 0], X_2dim[:N, 1], s=1, color='red', label='true users')\n", + "plt.scatter(X_2dim[N:2*N, 0], X_2dim[N:2*N, 1], s=5, color='green', label='single dirichlet simulation')\n", + "#plt.scatter(X_2dim[2*N:3*N, 0], X_2dim[2*N:3*N, 1], s=1, color='blue', label='Simulated users: partitioned uniformly randomly')\n", + "plt.legend(fontsize=10)" + ] + }, + { + "cell_type": "markdown", + "id": "69f2e996-8985-45f7-adb0-1ad56ded1d8c", + "metadata": {}, + "source": [ + "# Two mixture components" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "eeae50e6-b4e4-409e-b8b1-f45d27f2ed70", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "dict_keys(['alphas', 'phi'])\n", + "alpha_mixture [[12.486713 13.534921 11.7629795 12.550145 11.480532 10.293059\n", + " 11.921352 12.587899 11.840125 11.941666 3.9614604 2.2822833\n", + " 7.3454185 2.6096861 2.1497195 6.5782847 1.219504 1.6149502\n", + " 8.219717 2.2317927 1.2118896 2.750498 6.845294 5.16876\n", + " 20.386126 6.246426 1.2428675 2.2957945 16.824781 6.5312443\n", + " 9.8076315 2.787484 3.030136 1.3144614 2.9685311 1.3412713\n", + " 6.926577 3.528872 1.3654627 7.718317 19.724745 1.1862212\n", + " 2.2440865 6.1563945 1.3286887 1.0327483 1.2686301 9.836655\n", + " 1.2492453 7.9961534 1.320585 1.1531479 1.781072 10.346889\n", + " 1.3283604 14.271842 1.3694632 1.4000323 1.3433177 1.3627586\n", + " 1.2021077 1.3795127]\n", + " [44.51527 50.686996 45.006035 45.453217 44.310375 41.812286\n", + " 45.320396 47.128685 44.48823 44.521595 3.9697187 3.7719092\n", + " 4.3950214 3.7158391 3.4485605 3.7217412 3.4760392 3.436453\n", + " 5.725511 3.7413826 3.4088106 4.3864307 3.7450933 4.0867777\n", + " 4.2136483 4.049439 3.738219 3.8356507 3.954183 3.9112475\n", + " 3.938368 4.162987 3.984091 3.9271889 3.6723745 4.0041394\n", + " 3.9384997 3.9038906 3.8839767 3.7883527 3.8080533 3.7992022\n", + " 3.401485 4.051268 3.5428376 2.285073 3.3482904 5.7865825\n", + " 3.7956715 3.8241901 3.8699336 3.475093 2.9511976 3.8318043\n", + " 3.9740224 3.9577084 3.8802054 4.14223 3.9508624 4.002048\n", + " 3.295877 3.841521 ]]\n", + "phi_mixture [0.39602438 0.60397565]\n", + "num_samples_distribution_mixture (2, 500)\n", + "(2,) (2, 62) (2, 500)\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Load two component mixture dirichlet saved params\n", + "params = joblib.load(os.path.join('mle_params', 'femnist_2_mixture', 'polya-mixture.joblib'))\n", + "print(params.keys())\n", + "alpha_mixture = np.array(params['alphas'])\n", + "print('alpha_mixture', alpha_mixture)\n", + "phi_mixture = np.array(params['phi'])\n", + "phi_mixture /= sum(phi_mixture)\n", + "print('phi_mixture', phi_mixture)\n", + "\n", + "num_samples_distribution_mixture = joblib.load(os.path.join('num_samples_distribution', 'femnist_2_mixture.joblib'))\n", + "num_samples_distribution_mixture = num_samples_distribution_mixture.numpy()\n", + "print('num_samples_distribution_mixture', num_samples_distribution_mixture.shape)\n", + "print(phi_mixture.shape, alpha_mixture.shape, num_samples_distribution_mixture.shape)\n", + "\n", + "# generate users\n", + "num_users = 500\n", + "true_users = generate_true_users(user_id_to_data)\n", + "simulated_dirichlet_mixture_users = generate_mixture_users(len(true_users), alpha_mixture, phi_mixture, num_samples_distribution_mixture, all_labels)\n", + "len_sampler = get_femnist_len_sampler(user_id_to_data)\n", + "simulated_uniform_users = generate_uniform_users(len(true_users), len_sampler, all_labels)\n", + "\n", + "# Run TSNE on the label counts of all users\n", + "tsne2 = TSNE(n_components=2)\n", + "X = np.vstack([true_users, simulated_dirichlet_mixture_users, simulated_uniform_users]) \n", + "X = X / X.sum(axis=1, keepdims=True) # This will normalize the counts to proportions to ignore num sample per user effects\n", + "X_2dim = tsne2.fit_transform(X)\n", + "\n", + "# plot\n", + "N = num_users\n", + "plt.figure(figsize=(8, 5))\n", + "plt.title('TSNE visualisation of user label distributions in CIFAR10 dataset')\n", + "plt.scatter(X_2dim[:N, 0], X_2dim[:N, 1], s=1, color='red', label='true users')\n", + "plt.scatter(X_2dim[N:2*N, 0], X_2dim[N:2*N, 1], s=5, color='green', label='single mixture dirichlet simulation')\n", + "plt.scatter(X_2dim[2*N:3*N, 0], X_2dim[2*N:3*N, 1], s=1, color='blue', label='Simulated users: partitioned uniformly randomly')\n", + "plt.legend(fontsize=10)" + ] + }, + { + "cell_type": "markdown", + "id": "54127757-97f1-4619-912a-ddc91f085e32", + "metadata": {}, + "source": [ + "# Three mixture components" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "05dc6205-7096-412a-9188-f1086cadbda0", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "dict_keys(['alphas', 'phi'])\n", + "alpha_mixture [[ 7.331553 7.954057 6.9863634 7.491554 6.840809 6.176658\n", + " 7.037211 7.3866696 7.0418634 7.0186877 1.7180551 1.3936192\n", + " 4.336823 1.3972884 1.021399 3.9414258 0.8377679 0.8865488\n", + " 4.666944 1.3927824 0.82493305 1.5903513 4.075701 2.323618\n", + " 11.663883 3.662332 0.8683789 0.9965437 9.724308 3.1967835\n", + " 5.7382493 1.7378958 1.9411799 0.8642131 1.9035438 0.8644596\n", + " 4.9368877 2.3315918 0.90976584 5.0233307 12.5443945 0.7650201\n", + " 1.4112251 4.09973 0.91791886 0.70593554 0.8813811 5.6781783\n", + " 0.82670665 5.477468 0.91935456 0.7856333 1.1689324 7.026988\n", + " 0.83059084 9.19348 0.8955782 0.8933723 0.8802291 0.93215483\n", + " 0.79196453 0.9271174 ]\n", + " [18.83051 21.391619 19.192364 19.395418 18.862967 18.080807\n", + " 19.338434 20.053724 18.768417 19.05818 1.8996079 1.8278965\n", + " 2.0523577 1.8387978 1.6229041 1.7828559 1.7393044 1.6851878\n", + " 2.5363393 1.7556136 1.6119165 1.9750109 1.85119 1.9215419\n", + " 1.9163609 1.8660287 1.758909 1.8497199 1.8336132 1.8163389\n", + " 1.8787143 1.8776171 1.9155294 1.9301225 1.710874 1.9480428\n", + " 1.8938534 1.7851719 1.9563513 1.8582665 1.8689779 1.7700071\n", + " 1.6418803 1.9925227 1.6899055 1.1193209 1.7580124 2.5709739\n", + " 1.841688 1.8507614 1.861241 1.6949676 1.3854067 1.8211398\n", + " 1.7923293 1.8661227 1.8890306 1.8883762 1.8973581 1.8782278\n", + " 1.5289938 1.8693763 ]\n", + " [ 7.890613 8.639257 7.737538 8.249985 7.3764997 6.5286493\n", + " 7.720129 8.291615 7.935243 7.8369765 6.848669 2.595738\n", + " 4.581804 3.8827293 4.726481 4.3145986 0.87768173 2.2444005\n", + " 4.7095323 1.4775896 0.93684626 3.5841136 4.011161 7.8069186\n", + " 12.993805 4.214646 0.95914626 3.931263 9.673255 8.524542\n", + " 6.182734 1.9064779 1.9609798 1.0343878 2.0815775 1.0086254\n", + " 1.1224002 1.3733677 1.0175576 2.079446 2.4763615 1.0114193\n", + " 1.0507283 1.8728429 0.81286395 0.9262054 1.1011454 3.7723496\n", + " 0.9499362 1.327955 0.9742082 0.79845166 1.0648375 1.2909755\n", + " 1.0237517 2.5326338 1.0434972 1.0078688 0.9999532 1.0237565\n", + " 0.9694846 1.0330129 ]]\n", + "phi_mixture [0.32083896 0.60536647 0.07379463]\n", + "num_samples_distribution_mixture (3, 500)\n", + "(3,) (3, 62) (3, 500)\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAqYAAAHDCAYAAAD2qtjrAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy81sbWrAAAACXBIWXMAAA9hAAAPYQGoP6dpAADNHElEQVR4nOydeVgTVxeHfyHsIKuIuADibou7dUPFBdyr1q3aulYr1qXaTy1FhYAKqNXWqgW1rbvWvbaugIqKe93rrizairugKChJ7vdHzJgJSUggIQmc93l4dGbu3Hvmzsydk3PPOVfAGGMgCIIgCIIgCCNjYWwBCIIgCIIgCAIgxZQgCIIgCIIwEUgxJQiCIAiCIEwCUkwJgiAIgiAIk4AUU4IgCIIgCMIkIMWUIAiCIAiCMAlIMSUIgiAIgiBMAlJMCYIgCIIgCJOAFFOCIAiCIAjCJCDFlDA4w4cPh6+vr7HFUCmHQCCASCQqcVmM1a4unDlzBq1atYKDgwMEAgEuXLhgbJGKRXGeQ4FAgPHjx+tNlvT0dAgEAqxatapI569atQoCgQDp6encvsDAQAQGBupFvsJQfn5FIhEEAgGePHlSIu37+vpi+PDhJdKWrpjKeEfIoPthfpBiagQEAoFWf8nJyQCAx48f4+uvv0adOnVgZ2eHChUq4KOPPsK3336LnJwcrt7hw4dDIBCgfv36ULXSrPLHVf5xVPcXGxtr8L4ozezZs8fklU915Ofno3///nj27Bl++OEHrF27Fj4+PsYWi9Azx48fh0gkQlZWlrFFKYApy2YMHj58iClTpqBOnTqwt7eHg4MDmjRpgtmzZ/P6KDAwEB9++CHvXF9fX7XjfF5eHldOIpGgUqVKEAgE2Lt3r0o55D9C5H9WVlbw9fXFxIkTVd6rhIQEfPHFF/jwww8hFAo1KolSqRTz5s1DtWrVYGtri/r162Pjxo069ZM+iY6Oxh9//GG09hW5evUqRCIR78doacXS2AKURdauXcvbXrNmDRITEwvsr1u3Lp49e4amTZvixYsXGDlyJOrUqYOnT5/i0qVLiIuLw9ixY+Ho6Mg77/Lly9i+fTv69u2rlTyDBg1Ct27dCuxv1KiRjlemmhUrVkAqleqlLn2Tm5sLS0vDvAZ79uzB0qVLVSqnhmxXH9y5cwcZGRlYsWIFRo0aZWxxCC1ISEjQ+Zzjx48jMjISw4cPh4uLi9bnlcTzq0m2GzduwMLCNO0qhhjvzpw5g27duiEnJweff/45mjRpAgD4+++/ERsbiyNHjhR6/xs2bIj//e9/BfZbW1tz/z948CAyMzPh6+uL9evXo2vXrmrri4uLg6OjI169eoUDBw5g8eLFOHfuHFJSUnjlNmzYgE2bNqFx48aoVKmSRhmnT5+O2NhYjB49Gs2aNcPOnTsxePBgCAQCfPrppxrPNQTR0dHo168fevfuXeJtK3P16lVERkYiMDCw1FuATffLWIr5/PPPedsnT55EYmJigf0AMH/+fNy9exfHjh1Dq1ateMdevHjBG1QAwM7ODlWrVkVUVBQ++eQTCASCQuVp3Lixyrb1hZWVlcHqLi62trZlql1tefToEQDopKwYG8YY8vLyYGdnZ2xRjILyWKBvpFIp3r59C1tbW6M/vzY2NkZtXxP6Hu+ysrLQp08fCIVCnD9/HnXq1OEdnzNnDlasWFFoPZUrVy50nF+3bh0aN26MYcOGISwsDK9evYKDg4PKsv369UP58uUBAGPGjMGnn36KTZs24fTp0/joo4+4ctHR0VixYgWsrKzQo0cP/PPPPyrr+++//7BgwQKMGzcOS5YsAQCMGjUK7dq1w9SpU9G/f38IhcJCr5Mwf0zzJyfBcefOHQiFQrRo0aLAMScnpwIfCAsLC8yYMQOXLl3Cjh07DCbX999/D4FAgIyMjALHvvvuO1hbW+P58+cAVPv4/P7772jSpAnKlSsHJycn+Pv7Y9GiRdxx+XSRMqp863bu3Inu3bujUqVKsLGxQfXq1TFr1ixIJJJCr0PZV+7ly5eYNGkSfH19YWNjgwoVKiAoKAjnzp3jyhw9ehT9+/eHt7c3bGxsULVqVUyePBm5ublcmeHDh2Pp0qVcG/I/de0CwPnz59G1a1c4OTnB0dERHTt2xMmTJ1Ve/7Fjx/DNN9/Aw8MDDg4O6NOnDx4/flzo9QIyq0ibNm3g4OAAFxcX9OrVC9euXePJ3q5dOwBA//79IRAINPou6nKv/v77b3Tu3Bnly5eHnZ0dqlWrhpEjR/LOk0ql+PHHH/HBBx/A1tYWnp6eGDNmDPc8yfH19UWPHj2wf/9+NG3aFHZ2dli2bJlWfSDn+++/R6tWreDu7g47Ozs0adIEW7duVVt+/fr1qF27NmxtbdGkSRMcOXKkQJn//vsPI0eOhKenJ2xsbPDBBx/gt99+00kuRa5cuYIOHTrAzs4OVapUwezZs1Va5FT5mC5evBgffPAB7O3t4erqiqZNm2LDhg0AZPdt6tSpAIBq1apxz6j8fsldf9avX48PPvgANjY22LdvH3dM1UzAkydPMGDAADg5OcHd3R1ff/01b6pYk2+tYp2FyabKxzQ1NRX9+/eHm5sb7O3t0aJFC+zevZtXJjk5GQKBAJs3b8acOXNQpUoV2NraomPHjrh9+zav7K1bt9C3b19UrFgRtra2qFKlCj799FNkZ2cXkF0R5fFOfs3ff/89li9fjurVq8PGxgbNmjXDmTNnNNYFAMuWLcN///2HhQsXFlBKAcDT0xMzZswotJ7CyM3NxY4dO/Dpp59iwIAByM3Nxc6dO7U+v02bNgBk3yxFKlWqpJWyvnPnTuTn5+Orr77i9gkEAowdOxb//vsvTpw4UWgdf/zxBz788EPY2triww8/VPsN1Oa9FwgEePXqFVavXs09f/JnLiMjA1999RVq164NOzs7uLu7o3///gWm2fPz8xEZGYmaNWvC1tYW7u7uCAgIQGJiIq/c9evX0a9fP7i5ucHW1hZNmzbFn3/+yR1ftWoV+vfvDwBo3759AXe/0gZZTE0cHx8fSCQSrF27FsOGDdPqnMGDB2PWrFmIiopCnz59CrWavn79WmXQgouLi9rpugEDBmDatGnYvHkz9wGRs3nzZgQHB8PV1VXluYmJiRg0aBA6duyIuXPnAgCuXbuGY8eO4euvv9bmEnmsWrUKjo6O+Oabb+Do6IiDBw8iPDwcL168wPz583WqKyQkBFu3bsX48eNRr149PH36FCkpKbh27RoaN24MANiyZQtev36NsWPHwt3dHadPn8bixYvx77//YsuWLQBkFoT79++rdNFQxZUrV9CmTRs4OTlh2rRpsLKywrJlyxAYGIjDhw+jefPmvPITJkyAq6srIiIikJ6ejh9//BHjx4/Hpk2bNLaTlJSErl27ws/PDyKRCLm5uVi8eDFat26Nc+fOwdfXF2PGjEHlypURHR2NiRMnolmzZvD09NSpH1Xx6NEjBAcHw8PDA6GhoXBxcUF6ejq2b9/OKzdmzBisWrUKI0aMwMSJE5GWloYlS5bg/PnzOHbsGO8jd+PGDQwaNAhjxozB6NGjUbt2bZ1kWrRoET7++GN89tlnePv2LX7//Xf0798fu3btQvfu3XllDx8+jE2bNmHixImwsbHBzz//jC5duuD06dOcT9/Dhw/RokULTqnz8PDA3r178cUXX+DFixeYNGmSTvI9ePAA7du3h1gsRmhoKBwcHLB8+XKtrMIrVqzAxIkT0a9fP05BvHTpEk6dOoXBgwfjk08+wc2bN7Fx40b88MMPnPXLw8ODq+PgwYPYvHkzxo8fj/Llyxc6hThgwAD4+voiJiYGJ0+exE8//YTnz59jzZo1Ol23NrIp8vDhQ7Rq1QqvX7/GxIkT4e7ujtWrV+Pjjz/G1q1b0adPH1752NhYWFhYYMqUKcjOzsa8efPw2Wef4dSpUwCAt2/fonPnznjz5g0mTJiAihUr4r///sOuXbuQlZUFZ2dnna4HkE1pv3z5EmPGjIFAIMC8efPwySefIDU1VaPi9ueff8LOzg79+vXTuU1F8vPzC4zz9vb2sLe359rJycnBp59+iooVKyIwMBDr16/H4MGDtapfrpSpG/cL4/z583BwcEDdunV5++XW1/PnzyMgIEDt+QkJCejbty/q1auHmJgYPH36FCNGjECVKlUKlNXmvV+7di1GjRqFjz76CF9++SUAoHr16gBkrhXHjx/Hp59+iipVqiA9PR1xcXEIDAzE1atXuT4ViUSIiYnh6nnx4gX+/vtvnDt3DkFBQQBkY3/r1q1RuXJl7h3fvHkzevfujW3btqFPnz5o27YtJk6ciJ9++glhYWFcHyn3VamBEUZn3LhxTN2tePDgAfPw8GAAWJ06dVhISAjbsGEDy8rKKlB22LBhzMHBgTHG2OrVqxkAtn37du44ADZu3DhuOy0tjQFQ+3fixAmNcrds2ZI1adKEt+/06dMMAFuzZg1PLh8fH27766+/Zk5OTkwsFqutOyIiQmWfrFy5kgFgaWlp3L7Xr18XKDdmzBhmb2/P8vLy1MrBmKxPIiIiuG1nZ2deH6lCVXsxMTFMIBCwjIwMbp+m+6rcbu/evZm1tTW7c+cOt+/+/fusXLlyrG3bttw++fV36tSJSaVSbv/kyZOZUChU+Vwo0rBhQ1ahQgX29OlTbt/FixeZhYUFGzp0KLfv0KFDDADbsmWLxvoY0/5e7dixgwFgZ86cUVvX0aNHGQC2fv163v59+/YV2O/j48MAsH379hUqI2Oq77/yvXz79i378MMPWYcOHXj75e/E33//ze3LyMhgtra2rE+fPty+L774gnl5ebEnT57wzv/000+Zs7Mz15783Vu5cqVGmSdNmsQAsFOnTnH7Hj16xJydnQu8B+3atWPt2rXjtnv16sU++OADjfXPnz+/QD2K12xhYcGuXLmi8pji8yt/Bj7++GNeua+++ooBYBcvXmSMab5u5To1yebj48OGDRvGbcv76ejRo9y+ly9fsmrVqjFfX18mkUgYY++f67p167I3b95wZRctWsQAsMuXLzPGGDt//rzWz78yys+Z/Jrd3d3Zs2fPuP07d+5kANhff/2lsT5XV1fWoEEDrdtv165dgfsuf1eU/xT7u0ePHqx169bc9vLly5mlpSV79OgRry75vb5x4wZ7/PgxS09PZ7/99huzs7NjHh4e7NWrV2pl6969e4F3UPGYn59fgf2vXr1iAFhoaKjG627YsCHz8vLijYEJCQkMQJHfewcHB95zpu58xhg7ceJEgW9fgwYNWPfu3TXK3bFjR+bv78/7VkmlUtaqVStWs2ZNbt+WLVsYAHbo0CGN9ZUGaCrfxPH09MTFixcREhKC58+fIz4+HoMHD0aFChUwa9YsldH3APDZZ5+hZs2aiIqKUltGzpdffonExMQCf/Xq1dN43sCBA3H27Fne1M2mTZtgY2ODXr16qT3PxcUFr169KjCdUVQUrUcvX77EkydP0KZNG7x+/RrXr1/XqS4XFxecOnUK9+/f16q9V69e4cmTJ2jVqhUYYzh//rzO8kskEiQkJKB3797w8/Pj9nt5eWHw4MFISUnBixcveOd8+eWXPEt4mzZtIJFIVLpWyMnMzMSFCxcwfPhwuLm5cfvr16+PoKAg7NmzR2fZdUHur7pr1y7k5+erLLNlyxY4OzsjKCgIT5484f6aNGkCR0dHHDp0iFe+WrVq6Ny5c5FlUryXz58/R3Z2Ntq0acNz3ZDTsmVLLugEALy9vdGrVy/s378fEokEjDFs27YNPXv2BGOMJ3/nzp2RnZ2tsl5N7NmzBy1atOD57Hl4eOCzzz4r9FwXFxf8+++/Wk0Xq6Ndu3aFjgOKjBs3jrc9YcIEADD4s7Vnzx589NFHPIuao6MjvvzyS6Snp+Pq1au88iNGjOD55MqnoVNTUwGAs4ju378fr1+/1ouMAwcO5FkTldtUx4sXL1CuXLlit9+8efMCY/zQoUMBAE+fPsX+/fsxaNAgrnzfvn05twdV1K5dGx4eHvD19cXIkSNRo0YN7N27l7MW6kpubq5K32G5u5qiq5Qy8rFt2LBhPGt2UFCQyudXl/deFYrn5+fn4+nTp6hRowZcXFx4dbi4uODKlSu4deuWynqePXuGgwcPYsCAAdy368mTJ3j69Ck6d+6MW7du4b///tNKptIEKaZmgJeXF+Li4pCZmYkbN27gp59+goeHB8LDw/Hrr7+qPEcoFGLGjBm4cOFCoekuatasiU6dOhX4c3Jy0nhe//79YWFhwU0fM8awZcsWzk9SHV999RVq1aqFrl27okqVKhg5ciTnu1YUrly5gj59+sDZ2RlOTk7w8PDgnPwL8wdTZt68efjnn39QtWpVfPTRRxCJRAU+HHfv3uWUO0dHR3h4eHA+mbq2B8jSgb1+/VrlNHTdunUhlUpx79493n5vb2/etvyDp+yHqYhcaVXXzpMnT/Dq1Sud5deWdu3aoW/fvoiMjET58uXRq1cvrFy5Em/evOHK3Lp1C9nZ2ahQoQI8PDx4fzk5OVxQlpxq1aoVS6Zdu3ahRYsWsLW1hZubGzw8PBAXF6fyPtasWbPAvlq1auH169d4/PgxHj9+jKysLCxfvryA7CNGjACAAvIXRkZGhsp2tXFZ+Pbbb+Ho6IiPPvoINWvWxLhx43Ds2DGd2te1f5VlrV69OiwsLAye4iYjI0Ptcy0/rkhh70+1atXwzTff4JdffkH58uXRuXNnLF26tEjvt7ZtqsPJyQkvX74scrtyypcvX2CMl/8Q3rRpE/Lz89GoUSPcvn0bt2/fxrNnz9C8eXOsX79eZX3btm1DYmIiNmzYgBYtWuDRo0fFCjy0s7PjjQVy5D7KmuqW319t3xVd3ntV5ObmIjw8HFWrVoWNjQ3Kly8PDw8PZGVl8eqIiopCVlYWatWqBX9/f0ydOhWXLl3ijt++fRuMMcycObPAmBEREQFA9zGjNEA+pmaEQCBArVq1UKtWLXTv3h01a9bE+vXr1abz+eyzzzhfU0Oku6hUqRLatGmDzZs3IywsDCdPnsTdu3c5v1F1VKhQARcuXMD+/fuxd+9e7N27FytXrsTQoUOxevVqAFDrF6sc0JSVlYV27drByckJUVFRqF69OmxtbXHu3Dl8++23OqdtGTBgANq0aYMdO3YgISEB8+fPx9y5c7F9+3Z07doVEokEQUFBePbsGb799lvUqVMHDg4O+O+//zB8+PASS4ulLjq1MOu4IdD2XgkEAmzduhUnT57EX3/9hf3792PkyJFYsGABTp48CUdHR0ilUlSoUEHtx1DZx7A4H8KjR4/i448/Rtu2bfHzzz/Dy8sLVlZWWLlyJRcgpAvye//555+r9QevX79+keXVlbp16+LGjRvYtWsX9u3bh23btuHnn39GeHg4IiMjtaqjuBkOlJ8NbZ8VQ6PN+7NgwQIMHz4cO3fuREJCAiZOnMj5zqryW9RHm6qoU6cOLly4gLdv3xos84L8fWvdurXK46mpqbzZHABo27Yt5/vbs2dP+Pv747PPPsPZs2eLlMrLy8sLhw4dAmOM95xkZmYCQKGpprRFH+/9hAkTsHLlSkyaNAktW7aEs7Mzl9JK8RvQtm1b3Llzh3uGfvnlF/zwww+Ij4/HqFGjuLJTpkxRO/NTo0aN4l+0mUGKqZni5+cHV1dX7qVVhdxqKh9cDcHAgQPx1Vdf4caNG9i0aRPs7e3Rs2fPQs+ztrZGz5490bNnT0ilUnz11VdYtmwZZs6ciRo1anDWhKysLF7KImXLR3JyMp4+fYrt27ejbdu23P60tLQiX5OXlxe++uorfPXVV3j06BEaN26MOXPmoGvXrrh8+TJu3ryJ1atXc9NgAFS6JWiTqguQKVv29va4ceNGgWPXr1+HhYUFqlatWuTrkSNPkK+unfLly6tNDaMJbe+VnBYtWqBFixaYM2cONmzYgM8++wy///47Ro0aherVqyMpKQmtW7c2eNqnbdu2wdbWFvv37+dNIa5cuVJleVXTcTdv3oS9vT2nMJcrVw4SiQSdOnXSi4w+Pj4q21V1D1Xh4OCAgQMHYuDAgXj79i0++eQTzJkzB9999x1sbW21fka15datWzwr6+3btyGVSrmgKcVnRRFVz4ousvn4+Kh9ruXHi4K/vz/8/f0xY8YMHD9+HK1bt0Z8fDxmz55dpPqKQs+ePXHixAls27aNN9WuL9LS0nD8+HGMHz+em/mRI5VKMWTIEGzYsEFj5L+joyMiIiIwYsQIbN68uUg5Rxs2bIhffvkF165d402/ywPSGjZsqPZc+f3V5l3R5b1X9wxu3boVw4YNw4IFC7h9eXl5KhcYcHNzw4gRIzBixAjk5OSgbdu2EIlEGDVqFKfsW1lZFTpm6PtdNWVoKt/EOXXqlMrp1dOnT+Pp06eFTul9/vnnqFGjhtYWEl3p27cvhEIhNm7ciC1btqBHjx6FKjdPnz7lbVtYWHCWJPlUjjz6UTEdjzx1hyJyK4Si1eHt27f4+eefdb4WiURSYCqnQoUKqFSpEieXqvYYY7xUV3Lk/VDYyjVCoRDBwcHYuXMnb8rz4cOH2LBhAwICAgp1q9AGLy8vNGzYEKtXr+bJ9M8//yAhIUHlIgvaoO29ev78eQHrkPxjI+/fAQMGQCKRYNasWQXaEYvFel0FSCgUQiAQ8Kx16enpal1fTpw4wfMfu3fvHnbu3Ing4GAIhUIIhUL07dsX27ZtU5mrUdt0Xop069YNJ0+exOnTp3n1qLMoK6L8nllbW6NevXpgjHE+vto+o9oiT5EmZ/HixQDAJWp3cnJC+fLlC6TZUvW+6iJbt27dcPr0aV5KoVevXmH58uXw9fXVyU8WkPl1isVi3j5/f39YWFionG42JCEhIfDy8sL//vc/3Lx5s8DxR48eFUtRlj9L06ZNQ79+/Xh/AwYMQLt27bR63j777DNUqVKl0BkzdfTq1QtWVla8Z4Exhvj4eFSuXLlAHm9FFMc2xTE8MTGxgH+xLu+9g4ODyudPKBQWGMsWL15cwPKv/A46OjqiRo0a3DNUoUIFBAYGYtmyZSqNTIpjhr7fVVOGLKYmztq1a7F+/Xr06dMHTZo0gbW1Na5du4bffvsNtra2CAsL03i+UCjE9OnTOR83VZw7dw7r1q0rsL969epo2bKlxvorVKiA9u3bY+HChXj58iUGDhxY6DWNGjUKz549Q4cOHVClShVkZGRg8eLFaNiwIecTFhwcDG9vb3zxxReYOnUqhEIhfvvtN3h4eODu3btcXa1atYKrqyuGDRuGiRMnQiAQYO3atUWa0n758iWqVKmCfv36oUGDBnB0dERSUhLOnDnD/TKuU6cOqlevjilTpuC///6Dk5MTtm3bptJPTB4oM3HiRHTu3BlCoVCtJWH27NlITExEQEAAvvrqK1haWmLZsmV48+YN5s2bp/O1qGP+/Pno2rUrWrZsiS+++IJLF+Xs7Fzk5VO1vVerV6/Gzz//jD59+qB69ep4+fIlVqxYAScnJ04pbteuHcaMGYOYmBhcuHABwcHBsLKywq1bt7BlyxYsWrSo2Glz5HTv3h0LFy5Ely5dMHjwYDx69AhLly5FjRo1eH5gcj788EN07tyZly4KAO9HX2xsLA4dOoTmzZtj9OjRqFevHp49e4Zz584hKSkJz54900nGadOmYe3atejSpQu+/vprLl2Uj4+PShkVCQ4ORsWKFdG6dWt4enri2rVrWLJkCbp3784F08if0enTp+PTTz+FlZUVevbsWSTLOSCzvn388cfo0qULTpw4gXXr1mHw4MFo0KABV2bUqFGIjY3FqFGj0LRpUxw5ckSlwqWLbKGhodi4cSO6du2KiRMnws3NDatXr0ZaWhq2bdum89TywYMHMX78ePTv3x+1atWCWCzG2rVruR8fJYmrqyt27NiBbt26oWHDhryVn86dO4eNGzcWOk5rYv369WjYsKHaWZmPP/4YEyZMwLlz57iUeaqwsrLC119/jalTp2Lfvn3o0qULAODSpUtcTs7bt28jOzubU6QbNGjAzbBVqVIFkyZNwvz585Gfn49mzZrhjz/+wNGjR7F+/fpCk+vHxMSge/fuCAgIwMiRI/Hs2TMuj6/i0t26vPdNmjRBUlISFi5ciEqVKqFatWpo3rw5evTogbVr18LZ2Rn16tXDiRMnkJSUBHd3d9759erVQ2BgIJo0aQI3Nzf8/fffXDpCOUuXLkVAQAD8/f0xevRo+Pn54eHDhzhx4gT+/fdfXLx4EYDsR7xQKMTcuXORnZ0NGxsbdOjQARUqVNDYL2ZJCWcBIFSgKa3QpUuX2NSpU1njxo2Zm5sbs7S0ZF5eXqx///7s3LlzvLKK6aIUyc/PZ9WrV9c5XZSqNBmqWLFiBQPAypUrx3JzcwscV06fsnXrVhYcHMwqVKjArK2tmbe3NxszZgzLzMzknXf27FnWvHlzrszChQtVpos6duwYa9GiBbOzs2OVKlVi06ZNY/v37y+QWqOwdFFv3rxhU6dOZQ0aNGDlypVjDg4OrEGDBuznn3/mnXP16lXWqVMn5ujoyMqXL89Gjx7NLl68WCANjlgsZhMmTGAeHh5MIBDw7jGUUrUwxti5c+dY586dmaOjI7O3t2ft27dnx48f55WRX79yyiV5GhxtUokkJSWx1q1bMzs7O+bk5MR69uzJrl69qrI+bdPlaHOvzp07xwYNGsS8vb2ZjY0Nq1ChAuvRowcvBZOc5cuXsyZNmjA7OztWrlw55u/vz6ZNm8bu37/PlfHx8Sk0FYsiqu7/r7/+ymrWrMlsbGxYnTp12MqVK1Wmv5K/O+vWrePKN2rUSGV/P3z4kI0bN45VrVqVWVlZsYoVK7KOHTuy5cuXc2W0TRfFmGwMaNeuHbO1tWWVK1dms2bNYr/++muh6aKWLVvG2rZty9zd3ZmNjQ2rXr06mzp1KsvOzubVP2vWLFa5cmVmYWHBq1N5vFDuD1Xpoq5evcr69evHypUrx1xdXdn48eMLjAmvX79mX3zxBXN2dmblypVjAwYMYI8ePVL5TqiTTTldFGOM3blzh/Xr14+5uLgwW1tb9tFHH7Fdu3bxyqh7rpXvR2pqKhs5ciSrXr06s7W1ZW5ubqx9+/YsKSlJZX8ooi5d1Pz58wvtR03cv3+fTZ48mdWqVYvZ2toye3t71qRJEzZnzhzePVWXLkrVu3L27FkGgM2cOVNtu+np6QwAmzx5MmPs/b1+/PhxgbLZ2dnM2dmZ9xzKxwFtvjESiYRFR0czHx8fZm1tzT744AO2bt06bbqHMcbYtm3bWN26dZmNjQ2rV68e2759e7He++vXr7O2bdsyOzs7nrzPnz9nI0aMYOXLl2eOjo6sc+fO7Pr16wWey9mzZ7OPPvqIubi4MDs7O1anTh02Z84c9vbtW147d+7cYUOHDmUVK1ZkVlZWrHLlyqxHjx5s69atvHIrVqxgfn5+TCgUlurUUQLGjBAtQRAEQRAEQRBKkI8pQRAEQRAEYRKQYkoQBEEQBEGYBKSYEgRBEARBECYBKaYEQRAEQRCESUCKKUEQBEEQBGESkGJKEARBEARBmARmn2BfKpXi/v37KFeuXJlasosgCIIgCMJcYIzh5cuXqFSpksZFL8xeMb1//75e1hEnCIIgCIIgDMu9e/dQpUoVtcfNXjGVL6137949vawnThAEQRAEQeiXFy9eoGrVqpzepg6zV0zl0/dOTk6kmBIEQRAEQZgwhbldUvATQRAEQRAEYRKQYkoQBEEQBEGYBKSYEgRBEARBECaB2fuYaotEIkF+fr6xxSAIgiCMgLW1tcYUNQRBmAalXjFljOHBgwfIysoytigEQRCEkbCwsEC1atVgbW1tbFEIgtBAqVdM5UpphQoVYG9vT0n4CYIgyhjyhVgyMzPh7e1N3wGCMGFKtWIqkUg4pdTd3d3Y4hAEQRBGwsPDA/fv34dYLIaVlZWxxSEIQg2l2uFG7lNqb29vZEkIgiAIYyKfwpdIJEaWhCAITZRqxVQOTdsQBEGUbeg7QBDmQZlQTAmCIAiCIAjThxRTgiAIgiAIwiQgxdQECQwMxKRJk4wtBkEQBEEQRIlCiqmZwhiDWCw2thh64+3bt8YWgSAIgiAII0OKqYkxfPhwHD58GIsWLYJAIIBAIEB6ejqSk5MhEAiwd+9eNGnSBDY2NkhJScHw4cPRu3dvXh2TJk1CYGAgty2VShETE4Nq1arBzs4ODRo0wNatWzXKIRAI8Mcff/D2ubi4YNWqVQBkiuT48ePh5eUFW1tb+Pj4ICYmhiublZWFUaNGwcPDA05OTujQoQMuXrzIHReJRGjYsCF++eUXVKtWDba2tgCArVu3wt/fH3Z2dnB3d0enTp3w6tUr3TuSIAiijCKWihF1OArBa4MRdTgKYmnpMWIQpZ9SncfUHFm0aBFu3ryJDz/8EFFRUQBk+ffS09MBAKGhofj+++/h5+cHV1dXreqMiYnBunXrEB8fj5o1a+LIkSP4/PPP4eHhgXbt2hVJzp9++gl//vknNm/eDG9vb9y7dw/37t3jjvfv3x92dnbYu3cvnJ2dsWzZMnTs2BE3b96Em5sbAOD27dvYtm0btm/fDqFQiMzMTAwaNAjz5s1Dnz598PLlSxw9ehSMsSLJSBAEURaZfWQ2Ig9HAgASUxMhZVKIAkXGFYogtIQUUxPD2dkZ1tbWsLe3R8WKFQscj4qKQlBQkNb1vXnzBtHR0UhKSkLLli0BAH5+fkhJScGyZcuKrJjevXsXNWvWREBAAAQCAXx8fLhjKSkpOH36NB49egQbGxsAwPfff48//vgDW7duxZdffglAZnVds2YNPDw8AADnzp2DWCzGJ598wtXn7+9fJPkIgiDKKmsvrS2wTYopYS7QVL62xMcDvr6yf41I06ZNdSp/+/ZtvH79GkFBQXB0dOT+1qxZgzt37hRZjuHDh+PChQuoXbs2Jk6ciISEBO7YxYsXkZOTA3d3d16baWlpvDZ9fHw4pRQAGjRogI4dO8Lf3x/9+/fHihUr8Pz58yLLSBAEQRCEeUEWU22JjQUyMmT/hoQYTQwHBwfetoWFRYGpbvmKVwCQk5MDANi9ezcqV67MKye3ZqpCIBBorLdx48ZIS0vD3r17kZSUhAEDBqBTp07YunUrcnJy4OXlheTk5AL1uri4qL0WoVCIxMREHD9+HAkJCVi8eDGmT5+OU6dOoVq1amplJQiCIN7zuf/niDoSxdsmCHOBFFNtCQ2VKaWhoQZvytraWutl8zw8PPDPP//w9l24cIFbC7pevXqwsbHB3bt3dZq29/DwQGZmJrd969YtvH79mlfGyckJAwcOxMCBA9GvXz906dIFz549Q+PGjfHgwQNYWlrC19dX6zYBmULcunVrtG7dGuHh4fDx8cGOHTvwzTff6FQPQRBEWWVmu5kQWgiRcjcFAd4BCGsTZmyRCEJrSDHVlpCQErOU+vr64tSpU0hPT4ejoyMXLKSKDh06YP78+VizZg1atmyJdevW4Z9//kGjRo0AAOXKlcOUKVMwefJkSKVSBAQEIDs7G8eOHYOTkxOGDRumtt4lS5agZcuWkEgk+PbbbzllFwAWLlwILy8vNGrUCBYWFtiyZQsqVqwIFxcXdOrUCS1btkTv3r0xb9481KpVC/fv38fu3bvRp08fte4Ip06dwoEDBxAcHIwKFSrg1KlTePz4MerWrVuM3iQIgihbWFpYIrxduLHFIIgiQT6mJsiUKVMgFApRr149eHh44O7du2rLdu7cGTNnzsS0adPQrFkzvHz5EkOHDuWVmTVrFmbOnImYmBjUrVsXXbp0we7duzVOjy9YsABVq1ZFmzZtMHjwYEyZMgX29vbc8XLlymHevHlo2rQpmjVrhvT0dOzZswcWFhYQCATYs2cP2rZtixEjRqBWrVr49NNPkZGRAU9PT7VtOjk54ciRI+jWrRtq1aqFGTNmYMGCBejatasOvUcQBEFoIudtDqotqgarWVaotqgact7mGFskguAQMDPPxfPixQs4OzsjOzsbTk5OvGN5eXlIS0vj5ckkCIIgyh70PXhPtUXVkJ6Vzm37uvgi7es04wlElAk06WuKkMWUIAiCIMoQ/774V+M2QRgTUkwJgiAIwszRZbWnKk5VNG4ThDGh4CeCIAiCMHOij0ZDlCwCA0NSahIAIKxNGKKPRvOi8y0tLHF57GX4x/nj3xf/oopTFVwee9nI0hPEe0gxJQiCIAgzJ+VuChhkISMMDCl3U1Qqq+HtwuFo7Ug+pYTJQoopQRAEQZghYqmYs4iKpWIIIAADgwACBHgHIOX4xgLKKkGYOqSYEgRBEIQZomgRBYD2vu0hFAghYRIcyTgCaXoaBF4AEwACAAFbTwOv4o26eiFBFAYppgRBEARhhihO3wOyxPotH1gh6tUemSbqBfi8sECN8jXR9tQDhO3KBi4ad1ltgigMisonCIIgCDMkwDsAAggAAAII0PKBFX568k4ple1EhpMUAa0+RbhDN1gKhECrVsYTmCC0gCymBEEQBGGGhLUJAwAu6l78wwJkNVQqJADWXloL0XEJIJEAx4+XuJwEoQtkMTUzhg8fjt69e+u1zvT0dAgEAly4cEGv9WqDr68vfvzxxxJvV58o919ycjIEAgGysrI0nqfLvdTmHq1atQouLi5a1adPBAIB/vjjD4O3o69npTQ8cwQByKbuw9uFI2FIAsLbhWN9U+v31lJFXryQWUqFChbT+HjA11f2L0GYEGQxNTMWLVoEM19FlseZM2fg4OCgdfnAwEA0bNjQpBWLVq1aITMzE87OzhrLmcK9FAgE2LFjR7F+7GRmZsLV1VV/QumJVatWYdKkSQV+IOj6zBGEqcFF4x/fiICTmQjrMgeWY8cBTk7A8yf8wgwYfOwlkLhZZjHduBHYtg0QiwGpFIgln1PCtCCLqZnh7OxsFKuYofDw8IC9vX2Jt/v27VuD1W1tbY2KFStCIFBlugAkEgmkUmmpuZcVK1aEjY2NscXQGmM9cwShL+TR+Ilvr0PUKBvR+6YDAIbUHwIuFkrhN68QAplSKuftW5lSKhQCoaElJzhBaAEppibI1q1b4e/vDzs7O7i7u6NTp0549eoVgILTv4GBgZg4cSKmTZsGNzc3VKxYESKRiFff9evXERAQAFtbW9SrVw9JSUmFTr/+888/6Nq1KxwdHeHp6YkhQ4bgyZMnasvLp5F37dqF2rVrw97eHv369cPr16+xevVq+Pr6wtXVFRMnToREYYBUnFZNTk6GtbU1jh49yh2fN28eKlSogIcPH2L48OE4fPgwFi1aBIFAAIFAgPT0dJVT2H/88QdPMRSJRGjYsCF++eUXVKtWDba2tgCArKwsjBo1Ch4eHnByckKHDh1w8eJFtdcJAKdPn0ajRo1ga2uLpk2b4vz587zjylP5cvn+/PNP1KtXDzY2Nrh7926BeymVSjFv3jzUqFEDNjY28Pb2xpw5c3h1p6amon379rC3t0eDBg1w4sQJjbLu3LkTjRs3hq2tLfz8/BAZGQmxWMz1PQD06dMHAoGA21bm7du3GD9+PLy8vGBrawsfHx/ExMRwxxWfJbnLwebNm9GmTRvY2dmhWbNmuHnzJs6cOYOmTZvC0dERXbt2xePHj7k6AgMDMWnSJF67vXv3xvDhw9Ve28KFC+Hv7w8HBwdUrVoVX331FXJycgDI7sGIESOQnZ3NPSvy90J5Kv/u3bvo1asXHB0d4eTkhAEDBuDhw4fccfmzs3btWvj6+sLZ2RmffvopXr58qaHnCcJw8JLpC4AU15eAuztmXPNA5Ck7uL0GLwDqeCUVy5NaWABLlpC1lDA5SDE1MTIzMzFo0CCMHDkS165dQ3JyMj755BONU76rV6+Gg4MDTp06hXnz5iEqKgqJiYkAZNa53r17w97eHqdOncLy5csxffp0jTJkZWWhQ4cOaNSoEf7++2/s27cPDx8+xIABAzSe9/r1a/z000/4/fffsW/fPiQnJ6NPnz7Ys2cP9uzZg7Vr12LZsmXYunWryvPlysmQIUOQnZ2N8+fPY+bMmfjll1/g6emJRYsWoWXLlhg9ejQyMzORmZmJqlWrFtKj77l9+za2bduG7du3c76a/fv3x6NHj7B3716cPXsWjRs3RseOHfHs2TOVdeTk5KBHjx6oV68ezp49C5FIhClTphTa9uvXrzF37lz88ssvuHLlCipUqFCgzHfffYfY2FjMnDkTV69exYYNG+Dp6ckrM336dEyZMgUXLlxArVq1MGjQIE7RVObo0aMYOnQovv76a1y9ehXLli3DqlWrOGX3zJkzAICVK1ciMzOT21bmp59+wp9//onNmzfjxo0bWL9+vVolVk5ERARmzJiBc+fOwdLSEoMHD8a0adOwaNEiHD16FLdv30Z4eHhh3aYRCwsL/PTTT7hy5QpWr16NgwcPYtq0aQBk7hQ//vgjnJycuGdF1X2SSqXo1asXnj17hsOHDyMxMRGpqakYOHAgr9ydO3fwxx9/YNeuXdi1axcOHz6M2NjYYslPEEWFF43PgIB0KfDsGSznzkd4r4X4+rrze72UAQF3xIC9vcxC2rQp4OMDLF1KSilhmjAzJzs7mwFg2dnZBY7l5uayq1evstzc3GK1kS/JZ5HJkSxoTRCLTI5k+ZL8YtWnibNnzzIALD09XeXxYcOGsV69enHb7dq1YwEBAbwyzZo1Y99++y1jjLG9e/cyS0tLlpmZyR1PTExkANiOHTsYY4ylpaUxAOz8+fOMMcZmzZrFgoODeXXeu3ePAWA3btxQKdfKlSsZAHb79m1u35gxY5i9vT17+fIlt69z585szJgx3LaPjw/74YcfuO03b96whg0bsgEDBrB69eqx0aNH89pp164d+/rrrwu07ezszNu3Y8cOpvh4R0REMCsrK/bo0SNu39GjR5mTkxPLy8vjnVu9enW2bNkylde5bNky5u7uznum4uLieP136NAhBoA9f/6c1zcXLlzg1aV4L1+8eMFsbGzYihUrVLYrv0e//PILt+/KlSsMALt27ZrKfujYsSOLjo7m1bN27Vrm5eXFbSs+B+qYMGEC69ChA5NKpSqPq3qWFOXcuHEjA8AOHDjA7YuJiWG1a9fmtlXd1169erFhw4Zx28rPijJbtmxh7u7u3Laq50K5noSEBCYUCtndu3e54/J+PX36NGNM9uzY29uzFy9ecGWmTp3KmjdvrlYWwvTQ1/fAFJB/kzqs6sB8o9yZ67dg7UZYsJldbFhQdB0WfjCcRRyKkH2z5vdg+b7ejMXFGVtsooyjSV9ThIKftEDdesOGoEGDBujYsSP8/f3RuXNnBAcHo1+/fhqDS+rXr8/b9vLywqNHjwAAN27cQNWqVVGxYkXu+EcffaRRhosXL+LQoUNwdHQscOzOnTuoVauWyvPs7e1RvXp1btvT0xO+vr68ejw9PTnZVGFtbY3169ejfv368PHxwQ8//KBRVl3w8fGBh4cHt33x4kXk5OTA3d2dVy43Nxd37txRWce1a9dQv359zhUAAFq2bFlo29bW1gXuk3K9b968QceOHTXWo1iHl5cXAODRo0eoU6dOgbIXL17EsWPHeO4AEokEeXl5eP36tdZ+lsOHD0dQUBBq166NLl26oEePHggODtZaTrnV19/fn7dP03OgDUlJSYiJicH169fx4sULiMVina/t2rVrqFq1Ks/yXq9ePbi4uODatWto1qwZANn0f7ly5bgyiu8YQZQ08mj8DukdkC59CtgBh72lOOz9Bnh7HUlHZkEUKELCkATZCY7xsiAngKykhMlDiqkW8Px5DLzesFAoRGJiIo4fP46EhAQsXrwY06dPx6lTp1CtWjWV51hZWfG2BQIBpFJpkWXIyclBz549MXfu3ALH5MqQtnIURbbj7/LsPXv2DM+ePSs0gtrCwqKAq0N+fn6Bcsr15OTkwMvLC8nJyQXK6jsoyc7OTm0wlPy4Nij2p7w+df2Zk5ODyMhIfPLJJwWOKSrWhdG4cWOkpaVh7969SEpKwoABA9CpUye1Lhnq5FTepyi3tvdQTnp6Onr06IGxY8dizpw5cHNzQ0pKCr744gu8fftW78FN+n7HCEIfXHyo4A+vMLzwvlPx8cD48bLgJ8UI/Ph3ympoKCmrhElhUB/TuLg41K9fH05OTnByckLLli2xd+9e7nheXh7GjRsHd3d3ODo6om/fvrygA1NBeXWNAO8Ag7YnEAjQunVrREZG4vz587C2tsaOHTuKVFft2rVx7949Xr+q8yWU07hxY1y5cgW+vr6oUaMG78/QaXbu3LmDyZMnY8WKFWjevDmGDRvGUwCsra15wVOALMr65cuXXIAYAK1ysjZu3BgPHjyApaVlgessX768ynPq1q2LS5cuIS8vj9t38uRJHa+yIDVr1oSdnR0OHDhQ7LrkNG7cGDdu3ChwbTVq1ICFhezVt7KyKtCfqnBycsLAgQOxYsUKbNq0Cdu2bVPrh1sUPDw8kJmZyW1LJBL8888/asufPXsWUqkUCxYsQIsWLVCrVi3cv3+fV0bVs6JM3bp1ce/ePdy7d4/bd/XqVWRlZaFevXpFvBqCKByxVIyow1EIXhuMqMNREEtV+4prOt/JxknlMe47paiUWlgAL1/K9sn3Z2TIlFPKaUqYEAZVTKtUqYLY2FicPXsWf//9Nzp06IBevXrhypUrAIDJkyfjr7/+wpYtW3D48GHcv39fpXXH2IS1CYMoUIQgvyCIAkXcahuG4NSpU4iOjsbff/+Nu3fvYvv27Xj8+DHq1q1bpPqCgoJQvXp1DBs2DJcuXcKxY8cwY8YMAFBrwRs3bhyePXuGQYMG4cyZM7hz5w7279+PESNGaKXEFBWJRILPP/8cnTt3xogRI7By5UpcunQJCxYs4Mr4+vri1KlTSE9Px5MnTyCVStG8eXPY29sjLCwMd+7cwYYNG7Bq1apC2+vUqRNatmyJ3r17IyEhAenp6Th+/DimT5+Ov//+W+U5gwcPhkAgwOjRo3H16lXs2bMH33//fbGv3dbWFt9++y2mTZuGNWvW4M6dOzh58iR+/fXXItcZHh6ONWvWIDIyEleuXMG1a9fw+++/c/cfkPXngQMH8ODBAzx//lxlPQsXLsTGjRtx/fp13Lx5E1u2bEHFihX1alXu0KEDdu/ejd27d+P69esYO3asxgUKatSogfz8fCxevBipqalYu3Yt4pU+qr6+vsjJycGBAwfw5MkTvH79ukA9nTp1gr+/Pz777DOcO3cOp0+fxtChQ9GuXTs0bdpUb9dHEMpwKZ9SEyFKFiH6aLTO52dkZRTY72bn9v47FRsrU0qFQsDFBXj2TLZPcX+rVnwllSCMjEEV0549e6Jbt26oWbMmatWqhTlz5sDR0REnT55EdnY2fv31VyxcuBAdOnRAkyZNsHLlShw/flwvFih9ory6hqWF4TwgnJyccOTIEXTr1g21atXCjBkzsGDBAnTt2rVI9QmFQvzxxx/IyclBs2bNMGrUKC4qX910bqVKlXDs2DFIJBIEBwfD398fkyZNgouLC2dpMwRz5sxBRkYGli1bBkDmNrB8+XLMmDGDS+E0ZcoUCIVC1KtXDx4eHrh79y7c3Nywbt067NmzB/7+/ti4cWOBlFmqEAgE2LNnD9q2bYsRI0agVq1a+PTTT5GRkVEgGl6Oo6Mj/vrrL1y+fBmNGjXC9OnTVbo8FIWZM2fif//7H8LDw1G3bl0MHDiwWH6MnTt3xq5du5CQkIBmzZqhRYsW+OGHH+Dj48OVWbBgARITE1G1alU0atRIZT3lypXDvHnz0LRpUzRr1gzp6enYs2ePXp+FkSNHYtiwYZxS6Ofnh/bt26st36BBAyxcuBBz587Fhx9+iPXr1/NSWAGyyPyQkBAMHDgQHh4emDdvXoF6BAIBdu7cCVdXV7Rt2xadOnWCn58fNm3apLdrIwhVFNdFTPF8OQII8HXzr99/p+SrPQ0YAMyZI4vGDw3l7z9+/H2OU/mqUARhRARM2bHLQEgkEmzZsgXDhg3D+fPn8eDBA3Ts2BHPnz/nWV58fHwwadIkTJ48WWU9b968wZs3b7jtFy9eoGrVqsjOzoaTE39aIy8vD2lpaby8lQRw7NgxBAQE4Pbt27xgJYIgiNKKqX0Pog5HcUG1AgggChRpHVQrlooRvDYYh9IPcfv8XP0wrMEwhLUJkymlitP4Pj4Qp96WrRZ1NwUBW08jbFc2LAXvlNPNm7lySE830BUTZZ0XL17A2dlZpb6miMGDny5fvoyWLVsiLy8Pjo6O2LFjB+rVq4cLFy7A2tq6wHSgp6cnHjx4oLa+mJgYREZGGljq0sWOHTvg6OiImjVr4vbt2/j666/RunVrUkoJgiCMhNwlLOVuCgK8A3RyEYs+Gs1TStv7tkfCkAT+bJ7idH1o6DvXgQgwAEmNALwQIDxZIrOYLlnyPhCKIIyMwRPs165dGxcuXMCpU6cwduxYDBs2DFevXi1yfd999x2ys7O5P8WgBUI1L1++xLhx41CnTh0MHz4czZo1w86dO40tFkEQRJmlOC5iRzKO8LYtBBYFzw8NBdzcAGdnAPKpfxlMAKQE134/tR8SIrOUhoTILK3u7rI/CoYijIDBFVNra2vUqFEDTZo0QUxMDBo0aIBFixahYsWKePv2bYEAh4cPH/JybipjY2PDRfnL/wjNDB06FDdv3kReXh7+/fdfrFq1qkDuToIgCMI8kDKp+m15hD0AlCvHBTwFeAdA8E4zFTAgwKqGTCmVR+XLmT5ddo48UIogSpgSX5JUKpXizZs3aNKkCaysrHjpcW7cuIG7d+9qlbCcIAiCIMoiQoGQt33xwcX3KadiY99H2IeGclbRsDZhEDn2QNAdQJQMhC29xC+rjEBAU/uEUTCoj+l3332Hrl27wtvbGy9fvsSGDRuQnJyM/fv3w9nZGV988QW++eYbuLm5wcnJCRMmTEDLli3RokULQ4pFEARBEGZLG582OJB2gIvKf5b3DKJkEaRMCovx/ki5+RABtfwR9uUoWL5Lnm8JIHzKXzLr6JF3Sqs8k4ViDPScOZR4nzAqBlVMHz16hKFDhyIzMxPOzs6oX78+9u/fj6CgIADADz/8AAsLC/Tt2xdv3rxB586d8fPPPxtSJIIgCIIwa+SBUotOLcKzXNlCFwwMay+tRdqrNLDKDEmvdgNHowtG+oeEvFc4x46V/Xv3Ln8lKIrMJ4xIiaWLMhSa0g+YWnoQgiAIwjiUxu9B1Pc9IcrZBSaQ5TCt5loNqc9TueNBfkFIGJKgvoJmzYC//waaNgVSU2V+pW5uwNOnJSA9UdbQNl1UifuYEkRp5dEj4NIl2b8EQRD6QNPSpWFLL0GUDAT9ZwtRoAif+3+u2/LZZ87IpvG/+AJQs/IbQZQ0Bs9jShBlhQcPgLdvZf9WqGBsaQiCMHeUE+knpiYiOT2Zy1lq+e13CI+NBT4NBdqFQCwVQ2gh1D03amysTEEVCmU+pgRhRMhiaqYIBAL88ccfBm/H19cXP/74o8HbUcWqVav0uh67oalYEbC2lv1raqSnp0MgEODChQsaywUGBmLSpEklIpMmtJW3uKh6xpYvX46qVavCwsLCKM9+Sb3b+qKk3lORSISGDRsavB1TQjmRPgAcSj+E6KPRso2QEF7KpyLnRpVH7y9ZQgFPhNEhxdQEefz4McaOHQtvb2/Y2NigYsWK6Ny5M44dO8aVyczMRNeuXY0opWrMTZnUJxUqAPXrG99aOnz4cPTu3Zu3r2rVqsjMzMSHH34IAEhOToZAICiQR3j79u2YNWtWCUlqfAYOHIibN29y2y9evMD48ePx7bff4r///sOXX35pROmIsk7K3ZTC9yumfJLnMNUlMX58vCx36cuXxROWIPQETeWbIH379sXbt2+xevVq+Pn54eHDhzhw4ACeKjika1qEgDAcb9++hbW1tbHFUIlEIoFAIFB5TCgUavXMuLm56Vssk8bOzg52dnbc9t27d5Gfn4/u3bvDy8uryPXm5+fDyspKHyIWG1N+Zgn1iKVinj+pIjzf0dBQiOfGIHqcP1LOTUaAbx7C5sZwaaIKJTZWFvQEAOPHy/4lqylhRMhiamJkZWXh6NGjmDt3Ltq3bw8fHx989NFH+O677/Dxxx9z5RSn++TTnps3b0abNm1gZ2eHZs2a4ebNmzhz5gyaNm0KR0dHdO3aFY8fP+bqUDVt27t3bwwfPlytfAsXLoS/vz8cHBxQtWpVfPXVV8jJyQEgs8KNGDEC2dnZEAgEEAgEEIlEAIA3b95gypQpqFy5MhwcHNC8eXMkJyfz6l61ahW8vb1hb2+PPn368BRxVaiy+l24cAECgQDp79KdZGRkoGfPnnB1dYWDgwM++OAD7Nmzhyv/zz//oGvXrnB0dISnpyeGDBmCJ0+e8Ppo/PjxmDRpEsqXL4/OnTuDMQaRSMRZtCtVqoSJEydqlFUZX19fzJo1C4MGDYKDgwMqV66MpUuXat3X8v5ycXHBn3/+iXr16sHGxgYjR47E6tWrsXPnTu4eJCcn86bG09PT0b59ewCAq6srBAIBd8+Vn4nnz59j6NChcHV1hb29Pbp27Ypbt24VkGH//v2oW7cuHB0d0aVLF2RmZvKu5ZdffkHdunVha2uLOnXqFEgLd/r0aTRq1Ai2trZo2rQpzp8/X2gfqprydnFxwapVqwC8fy+2b9+O9u3bw97eHg0aNMCJEycKyC//v7+/PwDAz8+P9xzFxcWhevXqsLa2Ru3atbF27doCssTFxeHjjz+Gg4MD5syZw009//bbb/D29oajoyO++uorSCQSzJs3DxUrVkSFChUwR4NPX4cOHTBeriy84/Hjx7C2tuYtTqKIvN1ffvmFF4G+b98+BAQEwMXFBe7u7ujRowfu3LnDnadNf8n7qbD3VJv+WrZsGXr06AF7e3vUrVsXJ06cwO3btxEYGAgHBwe0atWKJ58iR44cgZWVFR48eMDbP2nSJLRp00ZNb5oX0UejkZyezG37OPvAz8UPfq5+kDLpe6U1JATRq76A6NVuJFbOgygQiB5XX/uG5EuXCgSAREKrPRHGh5k52dnZDADLzs4ucCw3N5ddvXqV5ebmGkGyopGfn88cHR3ZpEmTWF5entpyANiOHTsYY4ylpaUxAKxOnTps37597OrVq6xFixasSZMmLDAwkKWkpLBz586xGjVqsJCQEK6Odu3asa+//ppXb69evdiwYcO4bR8fH/bDDz9w2z/88AM7ePAgS0tLYwcOHGC1a9dmY8eOZYwx9ubNG/bjjz8yJycnlpmZyTIzM9nLly8ZY4yNGjWKtWrVih05coTdvn2bzZ8/n9nY2LCbN28yxhg7efIks7CwYHPnzmU3btxgixYtYi4uLszZ2VltHxw6dIgBYM+fP+f2nT9/ngFgaWlpjDHGunfvzoKCgtilS5fYnTt32F9//cUOHz7MGGPs+fPnzMPDg3333Xfs2rVr7Ny5cywoKIi1b9+e10eOjo5s6tSp7Pr16+z69etsy5YtzMnJie3Zs4dlZGSwU6dOseXLl3PnREREMB8fH7Vyy/u1XLlyLCYmht24cYP99NNPTCgUsoSEBK36mjHGVq5cyaysrFirVq3YsWPH2PXr11l2djYbMGAA69KlC3cP3rx5wz0j58+fZ2KxmG3bto0BYDdu3GCZmZksKyuLu17FZ+Ljjz9mdevWZUeOHGEXLlxgnTt3ZjVq1GBv377lydCpUyd25swZdvbsWVa3bl02ePBgro5169YxLy8vtm3bNpaamsq2bdvG3Nzc2KpVqxhjjL18+ZJ5eHiwwYMHs3/++Yf99ddfzM/Pj5NXHYrvgBxnZ2e2cuVKxhj/vdi1axe7ceMG69evH/Px8WH5+fmc/PJn7PXr1ywpKYkBYKdPn2aZmZlMLBaz7du3MysrK7Z06VJ248YNtmDBAiYUCtnBgwd5slSoUIH99ttv7M6dOywjI4NFREQwR0dH1q9fP3blyhX2559/Mmtra9a5c2c2YcIEdv36dfbbb78xAOzkyZMqr2v9+vXM1dWVNxYsXLiQ+fr6MqlUqrJfIiIimIODA+vSpQs7d+4cu3jxImOMsa1bt7Jt27axW7dusfPnz7OePXsyf39/JpFItO4vbd5TbfurcuXKbNOmTezGjRusd+/ezNfXl3Xo0IE3hnXp0oV3XQ0aNOC2a9WqxebNm8dtv337lpUvX5799ttvKvvFZL4HcXGM+fjI/tWwP2hNEIMI3J/fIj8mEAkYRGACkYBFJkdypyqXDYquoz+5CEJPaNLXFCHF1ATZunUrc3V1Zba2tqxVq1bsu+++4z4uclQppr/88gt3fOPGjQwAO3DgALcvJiaG1a5dm9suimKqzJYtW5i7uzu3rfihl5ORkcGEQiH777//ePs7duzIvvvuO8YYY4MGDWLdunXjHR84cGCxFVN/f38mEolUnj9r1iwWHBzM23fv3j1OYWNM1keNGjXilVmwYAGrVasWp5wps3jxYtahQwe1cjMm61fFjy5jsuvt2rWr2nNU9TUAduHCBV65YcOGsV69evH2KSqmjKnuO8b4z8TNmzcZAHbs2DHu+JMnT5idnR3bvHkzT4bbt29zZZYuXco8PT257erVq7MNGzbw2pk1axZr2bIlY4yxZcuWMXd3d957GhcXpzfFVPG9uHLlCgPArl27xsmv+IwpPz+MMdaqVSs2evRoXjv9+/fnPa8A2KRJk3hlIiIimL29PXvx4gW3r3PnzszX15dTBhljrHbt2iwmJkbldeXm5jJXV1e2adMm7nj9+vXVPtPydq2srNijR4/UlmGMscePHzMA7PLly4wx7fpLm/dU2/6aMWMGt33ixAkGgP3666/cvo0bNzJbW1vedSkqpnPnzmV169bltrdt28YcHR1ZTk6Oyus1he9BXBxjPsJ7LA5jZEqgIj4+jAHc/sjkSJ4i6hdVnq98rgniTuWVjQCL/Ni5pC6JILRGW8WUpvK1pCg+5UWlb9++uH//Pv7880906dIFycnJaNy4MTdFqY769d9P33h6egIANzUp3/eomEk2k5KS0LFjR1SuXBnlypXDkCFD8PTpU7x+/VrtOZcvX4ZEIkGtWrXg6OjI/R0+fJibqrt27RqaN2/OO69ly5bFkhUAJk6ciNmzZ6N169aIiIjApUuXuGMXL17EoUOHeDLVqVMHAHhTiE2aNOHV2b9/f+Tm5sLPzw+jR4/Gjh07IBa/9wUbP3682mlWRZSvr2XLlrh27Rq3rU1fW1tb8+67Prl27RosLS1598Xd3R21a9fmyWlvb4/q1atz215eXtxz9urVK9y5cwdffPEFr59nz57Nu/f169fnJT3Xx72Xo9g/cr9RXd6Da9euoXXr1rx9rVu35vUBADRt2rTAub6+vihXrhy37enpiXr16sHCwoK3T508tra2GDJkCH777TcAwLlz5/DPP/9odLcBAB8fH3h4ePD23bp1C4MGDYKfnx+cnJzg6+sLQOZXq4im/tLmPdW2v7QZr/Ly8vDixQuV1zh8+HDcvn0bJ0+eBCBzMRgwYAAcHBxUljcm8u/H9OlAhqQKxmMJ4lut4RdSWNcekK3uJAoUIcgvCKJAEYaczYfg3XI4yjlKubLWdSA674ywLjL3EE05UAnCVKHgJy1RDHwsCb9wW1tbBAUFISgoCDNnzsSoUaMQERGh8YOkGGwhD4JR3ieVSrltCwsLMKWFv/Lz89XWn56ejh49emDs2LGYM2cO3NzckJKSgi+++AJv376Fvb29yvNycnIgFApx9uxZCIVC3jFHR0e17RWG/OOueA3K8o8aNQqdO3fG7t27kZCQgJiYGCxYsAATJkxATk4Oevbsiblz5xaoWzHwRflDV7VqVdy4cQNJSUlITEzEV199hfnz5+Pw4cN6C3jRtq/t7OzUBjyVFMrXLBAIuHsi94ldsWJFAYVG+VnQFcV25Kh6flW9F4rvgb5QpRCp6htV+zTJM2rUKDRs2BD//vsvVq5ciQ4dOsDHx0dnWXr27AkfHx+sWLEClSpVglQqxYcffoi3b9+qldmQ/aXNeKWp7QoVKqBnz55YuXIlqlWrhr179xbwWzcV5N8PgQCwsAAkUkvEHm8LTZ8SeeonOeKr7rDYNx0pLbwQ0GoQL0cpV1Zp+dHoo9EQJYvAwJCUmgQABZcoJQgTgyymWqL0Y7bEqVevHl69eqXXOj08PHhBKhKJBP/884/a8mfPnoVUKsWCBQvQokUL1KpVC/fv3+eVsba2hkQi4e1r1KgRJBIJHj16hBo1avD+5JHidevWxalTp3jnyS0hmuQHwLsGVXkvq1atipCQEGzfvh3/+9//sGLFCgBA48aNceXKFfj6+haQqzCri52dHXr27ImffvoJycnJOHHiBC5fvqzxHGWUr+/kyZOoW7cuAO36Wh2q7oGqMgA0lqtbty7EYjHvvjx9+hQ3btxAvXr1tJLF09MTlSpVQmpqaoE+rlatGtfOpUuXkJeXx51X2L0HCj6/t27d0mi5Lyp169blpWoDgGPHjmndB8XF398fTZs2xYoVK7BhwwaMHDlS5zrk923GjBno2LEj6tati+dFWOlHm/e0JPtr1KhR2LRpE5YvX47q1asXsNSaCqGhMqWUMQCWuYDdM2TcfwU7p9dY+vO7d1DR+qECy7HjEL4zCwnfXdM6R2nK3RQwyH68MTC16acIwpQgxVRLQkKA9HTDW0ufPn2KDh06YN26dbh06RLS0tKwZcsWzJs3D7169dJrWx06dMDu3buxe/duXL9+HWPHji2Q11KRGjVqID8/H4sXL0ZqairWrl2LeCXfBl9fX+Tk5ODAgQN48uQJXr9+jVq1auGzzz7D0KFDsX37dqSlpeH06dOIiYnB7t27Acim3Pft24fvv/8et27dwpIlS7Bv3z6N8teoUQNVq1aFSCTCrVu3sHv3bixYsIBXZtKkSdi/fz/S0tJw7tw5HDp0iFP+xo0bh2fPnmHQoEE4c+YM7ty5g/3792PEiBEaFbZVq1bh119/xT///IPU1FSsW7cOdnZ2nBVryZIl6Nixo0bZAdnHet68ebh58yaWLl2KLVu24Ouvv9a6r9Xh6+uLS5cu4caNG3jy5IlKK6KPjw8EAgF27dqFx48f86L95dSsWRO9evXC6NGjkZKSgosXL+Lzzz9H5cqVdXoWIyMjERMTg59++gk3b97E5cuXsXLlSixcuBAAMHjwYAgEAowePRpXr17Fnj178P333xdab4cOHbBkyRKcP38ef//9N0JCQgySomnq1KlYtWoV4uLicOvWLSxcuBDbt2/HlClT9N6WOkaNGoXY2FgwxtCnTx+dz3d1dYW7uzuWL1+O27dv4+DBg/jmm290rkeb97Qk+6tz585wcnLC7NmzMWLECL3XX1SUXb9CQgBXV9n/pUwC5DkB+Q7Ie2mP6VHv8ofqaP3QZpo+wDtAtyVKCcIUMLy7q2EpbcFPeXl5LDQ0lDVu3Jg5Ozsze3t7Vrt2bTZjxgz2+vVrrhxUBD8pBoqoCm5RDvR4+/YtGzt2LHNzc2MVKlRgMTExhQY/LVy4kHl5eTE7OzvWuXNntmbNmgLthISEMHd3dwaARUREcG2Fh4czX19fZmVlxby8vFifPn3YpUuXuPN+/fVXVqVKFWZnZ8d69uzJvv/+e43BT4wxlpKSwvz9/ZmtrS1r06YN27JlCy94Zfz48ax69erMxsaGeXh4sCFDhrAnT55w59+8eZP16dOHubi4MDs7O1anTh02adIkLuJZVYDYjh07WPPmzZmTkxNzcHBgLVq0YElJSdxxbaPyIyMjWf/+/Zm9vT2rWLEiW7RoEa9MYX2tKtCMMcYePXrEgoKCmKOjIwPADh06pPIZiYqKYhUrVmQCgYC758rX++zZMzZkyBDm7OzMySHPpKBOhh07djDloWX9+vWsYcOGzNramrm6urK2bduy7du3c8dPnDjBGjRowKytrVnDhg25rAGagp/+++8/FhwczBwcHFjNmjXZnj17VAY/Kdbx/Plzrk9Uya8q+Ikxxn7++Wfm5+fHrKysWK1atdiaNWt4xxXfRznKwTqMqQ5MU+5zVXW9fPmS2dvbs6+++kptf2hqlzHGEhMTWd26dZmNjQ2rX78+S05OLnQcUe4vxrR7T3XtL23GMHXXNXPmTCYUCtn9+/c19ktJfg+U4pgYY7LAJwuXDAa7J0xmO5UyWL1kdYb/WKQ2ZAFPeBccBV6Uvpx8ST6LTI5kQWuCWGRyJMuX5BftgghCD2gb/CRgTMlJy8x48eIFnJ2dkZ2dDScnJ96xvLw8pKWl8XL5EYQp4Ovri0mTJpnE8p+E6ZOeno7q1avjzJkzaNy4sbHFMSm++OILPH78GH/++afGciX5PYiPl83Ih4bKrKXx8UBMDMOT8n/i9eWOQL4DAAHgnI7InWuK5PcZvDYYiamJ3HaQXxAShiTo8SoIQr9o0tcUoal8giAIEyU/Px8PHjzAjBkz0KJFC1JKFcjOzkZKSgo2bNiACRMmGFscHiEhQHpoPEJifYH4eMTGAnfvCvD6fHcg3xGAAIAEXUZchEQqKVLUvGyaXoYAoGl6otRAiilBEISJcuzYMXh5eeHMmTNa+xiXFXr16oXg4GCEhIQgKCjI2OIURCGYKTQUsHV/CHywCYDMf93S4RVa9r6IWUdmITE1EaJkEaKPRmusUtGvVCKVINyhO4L+s4XIoQcvSp8gzBlKF0UQRkC+1CVBaCIwMLBASixChqmmhuIIDeXm80NCgEd1l8lSN/kcBVJC0WXkFZ2j5nnpn+4kQnTKDgn78gCfy8AU+pwTpQN6kgmCIAhC34SE8NK4yC2aKX4pCJi6BmFtwhB99CySUpPAwLSKmj+SceS9IisAjlR6a9w8hgRhAMqEYkoWB4IgiLKNMb8D8fHA9OmWAMIxZw4Q0k62n1NW76YgwDug0Ol4KVNYbIAB0urVgV9vqG5QMfqKIMyIUh2VL5FIcPPmTVSoUAHu7u5GkpAgCIIwNtnZ2bh//z5q1KhhkHy3mnB3B549k/3fx0eWE1tn4uMRdG4ykiq/X4iiU7VOSByaWLCsr6/Mv7XIjRGE/tE2Kr9UW0yFQiFcXFy4dZ7t7e2NvnyjOfP0KfDkCVC+vGygJQiCMAekUikeP34Me3t7WFqW3GdPnibqeZYUgBAAw9Rp8v/rSGws2vjm4UAl2TS+AEAbnzaqyyr4txKEuVGqLaaAbPrmwYMHGlc0IrTj338BiQQQCoEqVYwtDUEQhPZYWFigWrVq3HK8hkIsFSP6aDRS7qbg9NTNyH7oAoBBpkoy1Br6I66snKDVkqI84uMhnhuD6HH1keL5hpv617kegjAS2lpMS71iKkcikahcmpHQnt9/B1asAEaPBj791NjSlAxl8ZoJojRibW0NCwvDZ0iMOhzFRc7jTAgsj0+H2O4+cL8ZiptUnyDMGVJMCUIPkKsWQRC6oLwik5+rH1KfpwJnxgApoUBALIIGptIqTUSZg1Z+Igg9EBpK2VgIgtAe2YpM72IZzoTgafRZ1EpdCDRbBkyuBkGz5bRKE0FogCymBEEQBFFM5L6lRzKOQMqkEAqESBm/E3kv7WHp8AJtlvaGhcACbX3akm8oUSYhiylBEARBlBCzj8xGRHIEDqQdwKH0Q2jt3Zpby14szUdyejLa+rRFeLvwklVK4+NlPkm0pC1hJpBiShAEQRBFRL5+/bxj83j7115aC5++KwDndKDDdK2WHDUIsbEyR/nY2JJvmyCKAM0lEARBEEQRUVy/XpEXKYOQf2QYUHWPLOgJAgQEepW8gJTTlDAzyMeUKBXQCnwEQRgD5Sh8Oc5xz5H90AUCCymY1ALOnll4ct+RfEuJMgv5mBJlCpqtIgjCGPCi8AHYWtrCz8UPAYNT4O3N8OlAC/j4ALEiF1JKCUILSDElSgWU1okgiJJE7lt6NOMofFx8uP154jykZqVij/PH+GLNLGzYIMuBTDM5BKEdpJgSpYKQEBr8CYIoOaKPRiNifiaSJq5AemJn2c4zY4Af0oAzY4wX7EQQZg4ppgRBEAShIyl3U4ADs4FsX+DAHNnOg3Nk2wdl25RInyB0hxRTgiAIgtCRAO8AcK6lAsDXxRdcYD4D2vu2R1ibMCNJVxC560Hw2mBEHY6CWCo2tkgEoRLyxCYIgiAIHXG/Mh1WUgnyBVL4t7yPCq7Vkd5xuiw1VEAsLC0sTSrYadbhWYg6EgUASLyTiPxTJ2DVvCVS7qYgwDuAVqMiTAZ6CgmCIAhCR8JnCpH/RggAeHHHH/182uJgMxFYs2UQQIAAb5FxBVRi3eV17zcEwNLnCchK3g8GhqTUJABAeLtwI0lHEO8hxZQgCIIgtEAxX7IcCwvZ9qh30/aKFsjiIpaKEX002iBWzTxbIRjyAYACtQiTgnxMiVILLRFNEIS+iI8Hxo9/ny95zhxZirqlS2XZQH5ZbonfhoXjk1cJCG8XrhcFUr6qVGJqIkTJIkQfjS5yXUPqD+FtN/dpzeVflVl4KVCLMA1o5Sei1OLrK/uI+PjIUkkRBEEUBblSKpEAQiGwZEnB1HSGGG+UV5UK8gtCwpCEItWVJ85Dt/XdcPHhRTTwbIA/B/2JhScWko8pUWJoq6/RU0iUWmiJaIIg9EFsrGalFDDMeBPgHYCk1CQwsGJbNecdm4fk9GQwMCSnJ2PhiYXkU0qYJKSYEqWWkBBKuE8QRPFRVDrVjSmGGG/C9Oi3mnI3BexdPivyKSVMGVJMCYIgCEIDxvqRa2lhqTerpj6trwRhSEgxJQgTRDH6l6y+BEEUF31aXwnCkFDwE0GYIBS4RRAEQZQmtNXXKF0UQZggoaEypZQCtwiCIIiyhEEV05iYGDRr1gzlypVDhQoV0Lt3b9y4cYNXJi8vD+PGjYO7uzscHR3Rt29fPHz40JBiEYTJExIis5TSND5BEARRljCoYnr48GGMGzcOJ0+eRGJiIvLz8xEcHIxXr15xZSZPnoy//voLW7ZsweHDh3H//n188sknhhSLIIoEJewnCIIgCMNSoj6mjx8/RoUKFXD48GG0bdsW2dnZ8PDwwIYNG9CvXz8AwPXr11G3bl2cOHECLVq0KLRO8jElDIVyABL5fRIEQRBE0TBJH9Ps7GwAgJubGwDg7NmzyM/PR6dOnbgyderUgbe3N06cOFGSohFEAWJj3y8/CBjX75OstQRB6IpYKkbU4SgErw1G1OEoiKViY4tU4lAfmB8lli5KKpVi0qRJaN26NT788EMAwIMHD2BtbQ0XFxdeWU9PTzx48EBlPW/evMGbN2+47RcvXhhMZqJso7ySizET9isqyeR3ShBEYcTHA6GiHGQ3zQSaJSIpNQkAytxqT9FHoyFKFoGBldk+MDdKzGI6btw4/PPPP/j999+LVU9MTAycnZ25v6pVq+pJQoLgU5IBSIVZRClKnyAIXYiNBbIfugAp3wIou6s90YpX5keJKKbjx4/Hrl27cOjQIVSpUoXbX7FiRbx9+xZZWVm88g8fPkTFihVV1vXdd98hOzub+7t3754hRSeIIqNO2YyPB9zdZX/yY8puA8pQlD5BELoQGgo4e2YBAXMBoMyu9hTgHQABBLINBojvZdC0volj0OAnxhgmTJiAHTt2IDk5GTVr1uQdlwc/bdy4EX379gUA3LhxA3Xq1KHgJ8LsURcsJd8PvD9GKz0RBKFvxFIxoo9G81Z7srQoWws+yvvgyPpo3LF/g3QXAAKZoi4KFNG0fgliEsFP48aNw7p167BhwwaUK1cODx48wIMHD5CbmwsAcHZ2xhdffIFvvvkGhw4dwtmzZzFixAi0bNlSK6WUIPSBoQKL1E2/h4YCbm6yP0X/VbKIEgShTywtLBHeLhwJQxIQ3i68zCmlwPs+aFWzA6eUAjStb8oY1GIqEAhU7l+5ciWGDx8OQJZg/3//+x82btyIN2/eoHPnzvj555/VTuUrQxZTorhQGiiCIIjSi1gqRrlZdsgDf+o+MjCSLKYliElYTBljKv/kSikA2NraYunSpXj27BlevXqF7du3a62UEoQ+MLfAIkodRRBEmaSIg1/00WjkMb5SaiGwQFibMD0KR+iLEs1jSpg/pVEpMrdp9MICpQiCIEobYqkYUXtDEdw2A1F7Q3UKXEq5m8JN4ctxsnYqk64N5gAppoROkFJkfMzNwksQBFFcohf2gahRNhKrA6LG2Yg+Gq31uQWyETBgQvMJepaQ0BekmBI6QUqR8TE3Cy9QOi3tBEGUHCk3k8DeZ31SG7jErfQUUxdRvVwgjluKsDZhiGgXAT9XP/i5+iG8XTj5lpowBg1+Kgko+IkgTB91AWaUzoYgCG2I+r4nRDm7wASAgAGi9qoDl6IOR0GUHAGGd+XOOyN8Z1aJy0sURFt9jb4ABEEYHOXlXeXQcoEEQWhD2Dc7gIV9kHIzCQG1OqkNXEo5vhFyaxsTACktvEpOSEIvkGJKEITBCQlR7XpAywUSBKENlhaWCJ/yF2+fqhmXgJOZSGokU0oFAAJaDTKOwESRIR9TgiCMhuJygWV1yUSibMH5QNKymEVDwWFdPuOSmJoIUbII0UejEdZlDkTnnRFkXQeiwEi1llWxVIyZB2fCNdYVwo/HwcL1LrpP/pPuhwlAiilhdCgwpuz2QVibMIgCRQjyC4IoUER5BYlSj0yZininTEXoFF1ealE3AKraP326zGF9+nSVMy6WY8chfGcWEr67pnG1q+ij0Zh9dDay1i+B9K8lYFne2LOyPt0PE4AUU8LolMUUVMrjbWF9EB8PuLvL/kqT8kpLJhJlDZkyJUNTdLnZoI9f1eoGQPn+6dNlbQweDGRlQWwBRH2UizvP73BFdZ1x4fr9ykDIJv0ZEBBr/vejFECKKWF0yloKqvh4YPx4/jhcWB/ExgLPnsn+ypICT2hHWbW4myMy9xUZAqjIsWkG8J43fVgW3g2A4m+n8t0cvp0qGxgBWRu//w5IpYhuA4ha5CL1eSoAwM/VT+cZF67fP9gECMTAhxuAZsvM8n6UNihdFEGUMPLUSUIhsGSJdvlI4+NlRgMAmDPHvHKYEoanKM8UYRzkATtHM45CwiSwEFigrU9bs0qVxkv/Fhr/PuWGFg+eqoAlAJh1eBYWn16M53nPubLcWvbx79p4/Bh4/RrBIy2R6P3eFzTILwgJQxJ0ugaxVIzI5EgsOboAOZJclLO0x/g2/6OZGwOirb5GiimhNfG6jT+EEvL+a9UKOH6c+pHQH3IrvERSMFcsYVrIFbPVF1cjNSEISAkFAuYicqqX2aRKK+q3IE+ch7pL6yL9eTo3ex751B/o1w8RyREFynes1hFJ+ypAvGUTovtXRIrdIwTct4KkRnXMcv/nXeS9AKJAUdH7Tl2SZULvaKuv0VS+mWHMKTttZmxoSlE98v47ftz8Vm4iTJuQEJmltCy5xJgrsw7PQkRyhGwaOiUUyPYFUr41K99G5dXn4gcfga/lv4gffETjed3Wd0N6VjoUfRlSsi+rvXYpkwKbNyO6tRSiWveR6C2GqHkuBPfuQZQMdPzPBoFWNXF0fQyivu+pW0S9/GPVqpXsxWnVij5eJgIppmaGMQOFtPEFLYuBTNpS1nxpiZLFHJeqLYusu7zu/UZALOCcDgTMNWvfxtjNfsiQVEHsJl+Nyt3Fhxf5OxgQ4Oyv9tqFAiEwYABSvPF+OVIBcLy5F8LTfdC2VhCS395EUuU8iHJ26RZRr2wpOH6cPl4mAimmZoYxlRttPnykfKmHFAeCIHg0Wwa7qfUQOdXLrFOlTe1/G852d2HXYi6ifDMgnhujslwDzwa8bV9XX4QtOoewNmEIbxsOV1tX7pgAArTxaQNs2ICALyK5fMcAIK7kBXHqbaR4vuEprEczjmqfI1b5Y0UfL5OBfEwJgiAIooQQJYsQeTiS245oFwFRoMh4AukB2fr0sqWFBQwQOfYosEoTIPMx7ba+Gy4+vIgGng2w57M9sLW05Y4rBkbZnP8al7Z1w3ffCTDqSzGC1wbjUPohrmxkYCSkTMrry0CfQBzOOCzLbcoAF4kVcqwZqjhVweWxl+Fo7WjYjiA0Qj6mhF4h31HjQX1PEKWHGW1nIDIwEkF+QYgMjMSMtjOMLVKx4SW6FwAp+bdVlrO1tMXBYQfxdNpTHBx2kKeUAsAvyy3x27BwfLJ3Bi7/1AB37woQGwtYLv8FlsdO8Mquvrha5oOqQEZ2BicHBEDW+ZEQL7iF9MTO8I/z19PVEoaGLKaEVlDgovGgvicIwtQQS8WYfWQ21l5ci/s595EnzgMAmcX0vDPCd2bpXCc31gn/RahkNmKFMxC6pApCYn0R5ZuBiEBAYUYffq5+XC5TAHC1dX2fbooB+DFNFlzmnA7L/9VE/sz8Il4toQ/IYkroFXK/MR7U9wRBmBJiqWxqPfJwJFKzUjmlFADaPbBBWJc5RaqXG+sGpCLEZx/Sl+yS+eSHhmLa3apwzSt4jqLvqWIOVFsrW4XgslhUcapSJJmIkocspkSJQrlQCYIgzJuow1GImH8fODBHZsGsvg+41xoIiIVdyzUIDQjV34IB7z4aUeP9EbH6U9kSoh9sAvp9jvC24RBaCJFyNwV3nt/hWU8DfQORnpWOf7PuosoLAS77zYfjuMnFl4coMmQxJUwSU0onRb6bBEEQupNyN0WWgzXPHch1lymL2b5ASihyxbkQJYt0S92kidhYxGd0QUzkEuCfTwFmCVwZCDsxIBAIENYmDAlDEjCswTDOeiqAAO192yPt6zTkr6yKtIUSOM5fpB95CINDiilRJIqq1JnStLQpKclydOlXUqwJgjAGAd4BQMBcwDIHgATwOsdNmQMAA9PfggGhoYgVzkBejg9gmStb1/6DTci1lFlu5QpwWJswiAJFCPILgihQ9D79lil9dAitoKl8okhoE5Bj6tP2piifLoFOFBRFEIQxkKd1mtV9EsSvnGBb7jUqzfbnptKLvUyoEvHxQEwMQ/2+e3C84lA8y33GHfNz9cON8TcMur69KX4rzBGayicMSmlYBcoUE97r8uOeDAEEQRgDSwtLhLcLh5ONTLmwt7LHjfE3uDRYPIulHggJATIyBPhrYXd83fxr2c4zY4Af0pCaEFRktwGxVKwxIb/8+OQZD5GRIVOOiRKAmTnZ2dkMAMvOzja2KKWWuDjGfHxk/xb3vKLWRRAEQZgWxhjP8yX5zG+RH4NzGgMYg3MaC1oTpHM9ufm5zK1/GIPtEwa7JwzdQ1hkciSvTGRyJBOIBAzdxzA4p7Eek3fp6zLKJNrqazSVTxSKPqeMafqZIAiCKA5Rh6MQMb4GcGUA8MFmRC65rbPbQIfVHXDo699kQVsA4JyOoMVfImFIAlcmeG0wElMTuW1XW1fc/9/9AgsDENpBU/mE3tDnlHFZmH4uTlDS4MGApaXsX4IgCKIgYW3C4Py4myxC/9/WOJh2kJdLVRsuPrwoC9ayfQrYPQUCYhHw0IY3eAd4B/DOeZ73HN3Wd9PXZRBqIMWUKBR9+mIWtS5jRaAXpd3i+NZu3gxIJLJ/CYIgiIJYWljCs/NKmUKZ54jDW+vorDA28GwANFsGhJYHvi0P36D9cI/xh29GMgb/zws+PgyndzaGhZKadPHBRX1eCqECUkwJs8BYgVRFabc4VuEBAwChUPYvQRBEaSE+HvB1f4l49+l6sTA8+WA2YP1Slks1JVRmAdWBPZ/tQXvf9nCzc0N73/a4Nu4a5uM7ZMAXm/N64u5dAXb/9iGkkMqWNwUABrwWv1YZKEXoD1JMCbPAWC4ARWm3OBbmDRsAsVj2L0EQRGkhNhbIeFYOsc9G68XC0MCzAW/J0fJXZvBmt+IHH4Gv5b+IH3xE5fm2lrY4OOwgnk57ioPDDsLW0hahc8rBxwcYMNACtu4Pubys3KqnAiBPnKffBQSIAlDwE2EQSkPet9JwDQRBEKZAfDwQO/0lQhGLkDlViz2o5onz0G19N1x8eBENPBvgTvgB3L0r4AJrfS3/RYakCnyE/yJdXEXn+qMOR0GULAIDk1lMBfzjnap1QuLQRJXnEqqh4CfCqJh6DlNtKOlroJWcCIIorYSEAOlPyyHk6Ry9/NJXtHgOyD2InBwB3Nzez26FDkiFj/BfhA5ILTRfqSrkK0l1qtYJ7a1rweU1eFP6EiYp9jUQqiHFlDAIpSH6Xpdr0IdSWRqUeYIgCIOiYrCNjQWePQPKlXuv84ZsaIt0cRWEbGiL6KPRECWLkJiaiIjkCNReUrtQBVW+iEDi0EQcDLuBJs61eVP6FgJSnwwF9SxhEExxVSVd0eUa9KFUlgZlniCIMkpJTfmoGGwLGztT7qbIpuTfkZoQhIheQ/HBiMUFrKjqrKttWw9W1EvR1qetIa6OACmmBKEX9KFUalKEaZqfIAiTpqSmfFQMtoUZEQK8AyBQdBJNCQWyfXFzZx8kpibygpkUrauK+8OuuiP8vDP8LMqjmqsfJFIJReYbCFJMCUIPGNpCTNP8BEGYNK1ayXLdtWpl2HaKMNjK/UX9XP1kOxSi+QGAgSHlbgoAvnVVcb/l3PmwyMpGmuQJUp+nYtaRWRSZbyBIMSUILTGm1ZKm+QmCMGmOH5etDnL8uLElKYDcX/TG+BuIDIxE0MBUtF80UpZgH4AAAryVvEX1n6rj7/t/c+cJIHi/+lNoKFJq2YK9M7wqKq2EfqF0UQShJb6+MqulPB0JQRAE8Y74eIjnxiB6XH2keL5BgHcAwtqEwdLC0tiSqUQsFSP6aDRS7qZALBXjUPoh3nE/Vz8Me1sPYUsvwfLb74CQEF4KKQEEEAWKEN4u3EhXYH5oq6+Z5hNDECZIaOj7vKYEQRCEAiEhiK77CKLkCLBUIClVluPTVBU3uRUVAILXBhc4Xt21OsJnXgYy7soG/pAQhLUJAyCb7pcr3oT+oal8osyj7RR9acg0QBDmRFHyTxLGI+X4RsVUn2Yz1d2ySssC+wK8Awr4UFku/wXhw35DwqtPEN4uvHBrMEWtFglSTIkyj6bAIl3GFV3HIBqzCEIz6iKkCdMk4GQmBO80UwHw3j+zhFA5phYy0MbHA4sGTQbOjOH2tfNpJ7OGKlsjdI1CpajVIkGKKaEVpVmJ0hRYpMu4Ii8bE8O0svLQmEUQmlEXIU3oj+JapcVxSxHVywXBMXUhCWiN8FO2CLprCZFDjxKf6p4+XTamTp+usLOQgTY2Fsh+6CJLIfWOey/uqbaG6hqFSlGrRYIUU0IrTEGJMpRyrGmKXt24okoWedn6ffdoZeVRrLs0K/4EUVQU80/yIqQJvRF1OAoRyRHcqkhRh6N0Oj9633SIGmUj8e11zHq9FxbWNkj4TYzwJZdNI/CpEOUwNBSwdP2XSx2FM2NwV3RY9Visqz8X+X8VCYrKJ7QiPv594I+x3jFTiorXJEvw2mAkvnP8B4AgvyAkDEnQuj7FICsazwiTxsADg2LktKlHeZsrrnNdkZWXxW272Lrg+bfPtT4/OKYuEt9e57b9hOVR/W4OAmp1Qtg3O0rsfomlYvSZsh9Ja5qi09C/seP7zlq3HXEoAlFH3inkP6QB2b4m8Z0pbWirr5HFlNAKbX/4GdLyZ0qzIppkKYqVR7E+Q1inySJLGAQDT6XII6cThiRoF2xC6EzO2xyN24UR0GoQb1WlVMkTJFbOg+jVrhL1CY4+Go3dzj2RN6Eidjv3LNh2fDzE1XwQ9X3PAm4LM9vNlOU39QtCj5FX4O3NTOI7U1Yhi2kpwRQsmoBpWTWNRXGtPIa4l3RfCINgKgMPUWRcY12R9SaL23bJBZ77xml9PxXHuzvP7yD1eSp3TJvZIn1R6EyVry+ifDMgCgSYADrlITWVx9zcZxDIYlrGMAUfUMC0rJrGorhWHkO4JRV2X4xlUSVLrplDPnRmz4TmE95vMKD+A0A8N0br8xXHu2ENhnG2UwEDAjaklNjLXehMVTFWbjKV72tZyVJhUMX0yJEj6NmzJypVqgSBQIA//viDd5wxhvDwcHh5ecHOzg6dOnXCrVu3DClSqcVUFMKy+J0yB+WqsPtirIHXVAZ8giirhLcLR3vf9rINAXDEF4geV79IdcnWpI9E0H+2ECUDYQm5JfZyy9oWIcgvCKJAUcGMACEhCPjsO57y2qpqK60yEpjK97WsZKkwqGL66tUrNGjQAEuXLlV5fN68efjpp58QHx+PU6dOwcHBAZ07d0ZeXp4hxSqVlEWF0FQoDcqVsQZeUxnwCaKsYmlhyZ/VEQApnm8KPU9VminOetr4B4RfdoOli1uJvdyWFpYIaxOGAO8ApNxNQfTR6AKKprLyyhjTygJpKt9XlVZhc7CM6AorIQCwHTt2cNtSqZRVrFiRzZ8/n9uXlZXFbGxs2MaNG7WuNzs7mwFg2dnZ+hSXILQmLo4xHx/Zv2WxfYIgzJvI5EgmEAkYRGACkYBFJkdqLJ8vyWftV7VnEIH7K+yckoB3HRFgkfN7aCwftCaIdw1Ba4JKSNKikS/JZ5HJkSxoTRCLTI5k+ZJ82eAPMObmZvIfAm31NaP5mKalpeHBgwfo1KkTt8/Z2RnNmzfHiRMn1J735s0bvHjxgvdHFJ/S+KOrpK7J2L+mS4PFliAI41HoNLgS0UejcSj9EG9fiU0rDx4MWFrK/n2HfKzfuMoZ7MyXwA9pYH+PQcrNJI1VmVueXOX4BQCIapWP4CFAVIMsiO+Vjg+B0RTTBw8eAAA8PT15+z09PbljqoiJiYGzszP3V7VqVYPKaQ7oQwEzNeWmNF6ToaDpcIIgioOuAZuqlFBDK3Wc64DlRkQFSCDesok7Jh/rM/cOk63glO0LpIQioFYn9RVCvUKu7Kaw9GeJSRpuoo9GQ1TrPhKrA6K2UkT3cC4VHwKzi8r/7rvvkJ2dzf3du3fP2CIZHX0oYKam3JTGazIUxrbYEgRRtlC0NAJAe9/2ui0/qsLqWRhcRHp1QBQIRId8wB2Tj/Vzwsuhx8grsHV/iB4jryDsmx0a61SnkCtHv0+PelmyRg4tLTMpd1PeZxkQACn9PioVHwKjKaYVK1YEADx8+JC3/+HDh9wxVdjY2MDJyYn3V9bRhwJmaspNabwmgiCI0oCipTEyMBIJQxJ0S4u3eTMgkcj+1RJeRLoASPmoImfZ3O4QjJGrozAmhOGvhd2R+8QTfy3sXuQcn8rR715dV5eskUNLy4yyK4JYKi40w4A5YLTMrNWqVUPFihVx4MABNGzYEIAs+eqpU6cwduxYY4llloSElD7lqzReE0EQRGlAbmksMgMGyJTSAQO0PiXAOwBJqUlgYJw/qNyyycCQlCrzJy2WXGraGjQ8G+Eri12t9iiuS60BuZU65W4KxFIx5/eb9G6hAX30hTEwqGKak5OD27dvc9tpaWm4cOEC3Nzc4O3tjUmTJmH27NmoWbMmqlWrhpkzZ6JSpUro3bu3IcUiCIIgCMJYbNgg+9MBRSVMvupRt7n+BsnrqaqtEkVLy4ziD4TgtcHcfoYSDEYzAAZVTP/++2+0b9+e2/7mm28AAMOGDcOqVaswbdo0vHr1Cl9++SWysrIQEBCAffv2wdbW1pBiEaUEU1kmjiAIgjAsqqy0ASczkdTo/RKj+grAKrZF2AgEeAcg6U6irC+Y4YPRDImAMcaMLURx0HbtVaLkKCmFkdZ/JwiCAPLEeei2vhsuPryIBp4NsOezPbC1LP0GHnHcUkTvm46UFl4IaDXIpNeON/Q692KpGNEL+yDlZhICanVC2Dc7TK4vtNXXSDEltEIXZbM4CqMu7ZDFlCgLGPqDRpg/HVZ34OUVbe/bHgeHHTSiRAoMHvzen1TL6fvS+MxHHY7i/GEFEEAUKDI7q2xx0VZfM7t0UYRx0CV9U3Ei6gtrRzGLhjGj7uPjAXd32Z+p5bYjShfKqWvULZtIlF0uPrwo+8+ZMcAPaTi1s5FxBVKkCBH4sw7PQkRyBBJTExGRHIFZh2cZUMCSoaysc68PSDEltEIXZVNRYdQ1UX5h7ZhK0vzYWODZM9mfsWUhSjf0QSMKo4FnA9l/3iWXf5M82ehpg7gk9d94ICpQAPGAflqfu+7yOo3b5ojBV5kqRcs3kmJaRtH1GS6qdVJXRbKwdkwhaX58PPDyJWBvD7i5FV2WUjSOEAbE3JZNJEqePZ/tQXvf9rDvsBhC138haTVbZwu78mpHxVVoOUu/wwNZQvwx9YpVn7mj9bKvRf0wmIrVRg+Qj2kZpSh+oEXx6dR0jrn6iLq7yyyl9vaAh0fR5afgLUIbSqO/HWE4gtcGI/FdHksACPILQsKQhELPEyWLEHk4ktuOaBcBUaCoROTgBe7Y1IT4XgZmNXwB+eJSxZXFrCjqh8EMPqjkY0popCiWx6L8INNkATX3H3i5ucWT3xSsv4Tpo+s65kTZpqgW9rWX1mrcNqQc0UejIcrZhcTKeRC5X4Yg+wUizztzK0vNaDuj8AZLyxRUUT8MpWipQ7KYElqj7x9kZvADTyVyuVu1Ao4fNz/5CYIovRTVwl79p+pIfZ7Kbfu5+uHOxDslIkcB6+p/ttjT6HtE13uKoxlHIWESWAgs0Nanrfp6dLU0musHSBMmfk2ULoogCIIgCK2IOBSBqCNR3HZ423BEto/klSmS0quFsqQqlRIAbh8YgHdJ9NWmWdJVKSvClLnB8qYqy15UBdPE/cNIMSUIgjBzTNwAQpQitFE6i5SLUwtlSVXb3dZ341lR5WjrM1soRXi5onq5QNQom1tpSm+5SOV9JBQCS5a893Mrjp8pYHKDB/mYEmWC0uJWZAiob8wfc/fDJswHbXyZi5S6TAufSVVtK/qovmtSva9qUQY7VT6ZhdST0sILjBNJj6nbQkNlSqlE8l6ZLK6fqRkPHqSYEmaNGb97Bof6xvyhADnClChSYFURg3Lk6ZU6VeuE9tXao2O1jurTLMkHu/Hji/dLvJBBM6DVoKKnbtOk9IaEyCyl8pe9CEpzAcx58GBmTnZ2NgPAsrOzjS1KqScujjE3N9lfXJyxpZERF8eYj4/pyGNKUN8QxYYeIkKBfEk+i0yOZEFrglhkciTLl+TrdNxgxMUxJhQyBsie16IyaJCsnkGDVB4u1vX5+BRPPnXnm9E7qq2+RoopoTXy96K47z6hHn2MMWY0TpUaSm2fF/djSpQpIpMjmUAkYBCBCUQCFpkcWbCQoV4WDfVqrVAa8nkv7nWrO9/NTSazm1txJTQ4pJgSPPSl8JiaxbS0oY9xsSh1lFrFqoQotfobPRiEDgStCWIQgfsLWhNUsJAOL4u+LLCR83swQYRMJkEEWOT8HqoLmuPzbm8v6097e2NLUija6mvkY1pG0Ie/YUgI8PSp7M9EgvxKHfpwCyqpxROI95izO5dGSlHSbsKwiKXiAsuYqvTBVPeyqPCh5JY11XF5Vbk88iVWV2fufR+0JABSbiapPskcn3db2/f/lpKIV0oXVUYoatoZSldTNjDX+0zLdRKEERg8GNi8GRgwANiwAQA/lRQAtPdtj4QhCQXexwLv7FV3WM6dD3HOC0R/+BxHvAFpnVoQVvFGalYqL+m/LqmilOXhcqEyQOTYA+FT/ip+P5gCioN3UdNMlRCUx5TQCyaer5co4xQpryJBEMXD0lKW2kgoBMQyS2ntJbW1UiJl72yEXF2E3wshhp2VQGJni1nN82SWzXdKJAC+Qtk+Uuv3W3k1KT9XP1R3ra75B6yp/kJXl58UAKZPB3JygPx8oEkT4PFjlfKbwo94ymNK6AVtpyhLyQxCiUB9pT+KlFeRIAiNFDpGDRggU0oHDAAgm3JXVEpxZgxOj/kF8YOPFDhV9s6+J9VJAlEgsK61IzfdzimlAOwEVvB7YYmZDt1Up4pSg3Jqq2ENhmnM0QrAdH2aFOVS/v+zZ8Dbt7K45PPnVbsixMcjuk95iJIjiuQWUdKQYkpoRFuXG329z2VBadOmr8pCP+iDIuVVJAiC54MZdTiK5x9a6Bi1YQMgFnPT+Mo/CC2PfIfsXG/EbvYrcKrsneXDBACcnN4n1FcgF/lIdRJD0KwZflluWfi4+G7wDLvqDlGgCEF+Qerznypjqs7iinIp/9/NDbC2BgQC7ocCAP5HJDYWKc7Z3A8Ck/8RXwKBWAalLEXlm3JUvL6CGUttdLMC2vRVWegHfaDvvInmGJRLEEVBVWon+ftU++NwZuOYzup8HKHVe6VcV49PljAf4T0WN+hwgbK5+bms/ar2zG62HRe9LxAJWMQhWVsdV3eUHRdZ8iL8/Rb5aTcuGmLwNMeBQbEf4uJY5MfOTKDQ3ypTeRkYShdVCikLeUS1ef/NMdenru2Z4zhYGqAfBERpRflHXKfVnQqkdlJUMBGhQolRMzDJ65YrlZ1Wd1Kr0PLaEIHZzbZj7Ve1Z7n5ubxyft8UVEy1GhcLK6R4XNuB1hgDQ3E/AoMGyWQWCBgbNMh4ix8oQIppKcQULabGUKD0MUaUdE5iUnjMA/pBQJgrckuk21w3lYqeslWz/ar2BSymynlIC+QjLWQg05RgX64Yuc11K1C/Kgte+LxunHKMCDD3DiHM2eUBW7JUXKx+yvf1ZpHtwIJG27LIj51ZvgVkqz0Z2hqiK/paKUr+ZwKDGuUxLYWYYh5RfS1RrAum6gakCXOUuSxijmkMCQIAuq3vhkPph/As9xkOpR9Ct/XdeMeVAwUtBBYFfDAVfbbl8Hy3CxnICgQjHt/IHZPnJH2W+6zAeap8Hmf+byciLjjD9bVs++nZb5Gd5YnpUS81+scWRvS4+hAFAomV8yBqnI3otgJZhgENTv/iL0chavVIBDts17m9IlPYR6OwQITQUMDe/v22qQV0aYAU01JOYc+u8nFdg25CQ2XBmYW81zrJVBj6UB7mzJG983PmFL0OXSCFhyDKHsVRoHQhPh44PGkVcGYMt+/iw4u8MrxAQQa0fWSH8HbhvEj1sDZhCG8Xjmou1eBq6wo/Fz+EtwuXBQ5pkUpJuY2Ak5ncMUWlFQDsLO24/6sKXLS0sIRFQBs8t4MsSj8gFrB9ilc5FugzZT8/8f7CPu8DgJo109hXKZ5v3ifbB5ASXLtQq0GREv0b+kNXWIRaSAjw6hUQF8e/PjOIrCXFtJRT2LOrfFzX6PqQEGDJEt2sgfI2pk833vtBiiJBqMYMvltmQ/TRaES8S9ETkRyB4LXBBlFOY2MBaZY3kPJ+EG7g2YBXJqxNGESBInT6zxaB6cCRm4kFlGVLC0tYCCyQnpWO53nPkZaVBguBhSy9khYfB3kbQdZ1IDrvjLAu73/5B3gHQPBOLxUwYFrraYgMjNQYNZ/i+eZ96qhmywCblxC/ckLSmqZ8y+zNJFkeTwD4+2+NfVUgk0erQYV+DIqUlk7Lj6nOP14GD5blkfXw0O7Dq/yxM9WUWAqQYlrKKWw2QPl4UaacdVXy5G0AJv9+6AX60BPmhBl8t8wGToE5Mwb4IQ2HttQySP7I0FDA25uhVq8dcLNzQ3vf9tjz2R5eGUsLS4S3C0ebWp2Q7AscqPxGpfVPrRL2buCOb7VG7Xj2y3JL/DYsHJ+4XkP4zixYjh3HHQtrEwaRYw8E/WcLkWMPzGg7o4DFVhllK6pb8ArYuj+Ed/cN3D4BBAio1QmwsgIAiJs10ajoccqzDmmkipSWTsuPqU7W2Ph4YONG2RTluXPaf3jlH6HBg4GXL2UppkzZr6yEfF4NRlkKfjJX1PmNG9qf3FQCWSjwiTAnTOW9KQ1EJkfKgnec02QxKM5p7wOJ5JRwhysHOCnLoymAiTHN45m+xzrFSHLlYK32q9qzoOg6sgCmn5eolb/H5F0qu5fLJDCnNmv/pQ3rNKeO2mj1YkW0a7q/cXEsaLStxvvBQzGgyd5eexnk5wmFRv0YUVQ+YTIYSzEzFYWQPvQEUTbJl+Sz9qvaM3QfI1NOu49hkfN78AuV8EBVmOJZmBKmydAgyxojZT0m79J7WqKg6DoFFTilvsuX5DO/RX68crbumTJdzkLMekzexclTaGosfaHu/sbFMSYUssh2YAJt25d3sr29bul55DetaVOZcjpoUBEvpnhQVD5hMhgrIt1UIuHJn5UwVcjNxLBYWlgiYUgCIqdWQtCAuojMWYawpZf4hUp4oFKcyu6e/Rd+HToTPb/ZzU19A9A4xa5uPJOvjimxysZu5556X/oy4GTmex9V+XS6Ut8VWBoVgHf3jYBADEiF2PXbB5w8vGAsLhhK9xWRCvURla/O9PIl/0WLjQUkEoSlCCA6ZSfzyy3MtUCemsfDQ9bZuvrbpKbK3ACOH9ftvJKmhBRlg0EWU9NFX5ZCsjiaF3S/zAdTmVUozXDvw6DDjPn4sPyfl5RIonNtpp+5mWHntPcWu/k9ivQCy6+zzvAftZ+a1uV6fl7CIj92lk3fq7keZTcFv0V+soUEFCzWcnlUWkwjwCK72Ol07YVZoBljql80eYfJk2rr8hIWNsgOGsS3jMrbsLc36uBMU/klBH2E1aOvj15Z/Hia83NVFu+XuWLOz5m5oPw+aKXI6AFt2omLY8zW/YFMcZMrc99YsqAhYJEfO7Pc/FwWcSiC+S3yY36L/Fj4wXCdlyc1yPWpeXBVta1OngI+psMtWGQ7yBLu6zB4Feazq0letceK+2LKfUmFQtl2Sa8oowZSTEsI+gjLMMS7pe96zIV3rkdm+1yVtftl6pjCUoRlmbg4xry93/tdKvtA+i3y0+s90dVyqbxE6PvVmCDzj1XaX5iiWSLPm5oPr6q2VcqjapCyt3+/hKfOFtP3faYXRby4ioWyxVT5euXbgwaV6GBNimkJQR9hGaSg6w/5j1vAaD7qRCmix+Rd3DSmIS10hHrUKX/aKnu6IB+LnT2fa2W5VFTclJVm+x4TuGdH31PzmuTQpNDmS/JZ5PwesiVF5/dQWa6w7zJvWVJ5W25uLN8CLKKLbeEWYoUG8iX5MheDd1ZmvSjiihfw7v9xgw5rr2uoOJ93ovwjY2FRoh9uUkxLEFJOqQ/0iaJiSoo+UVxs3R/w/AgNpVgQ6lGe7rWbbWcQP0zG3o/FS5aKdbZcKk972zim854dvLOiGsIaqq0LgDblCjOURM7vUTASPi6OhXex5fxNNf5oUG5AwwdQJwuysqVToS0f4T3tvwmK8vn4sHwLmdLMyeDu+t46rEt0fzGhqPwShBJSl57Ic1OIUp4zRxbEaeo5kAnzoNPQvwHndCAgVvvk4IReUU7Q3qJKC90TtmuJfCwe95Ww0AT2ysgj9mun/QDrxfdhWe39swMAPs4+SE5P1j7iXocBVdvVlbQpV1iiA/6ypO/qCAnBunri9ytNvWPRqUUFo+3VRdqrQKcE+ps3y6LmN2/mtSX29YZ/r52wdX8I/092y2RR1bfNmsmWZWXsfQeEhiK6hzNEjbPfyxDaGmKhAFFtGYJ7v0BU3UcGWy63KJBiqgdMJS2RvjEFJa2kUfyRYazrl2cEefrU/BV9wvjs+L4zIneuQdDAVK1XuiH0i/JqQ3s+26Pz6kMlgXx1qAf7huPN04p49U8vmVLabBkA4OXbl7otzTl9+vv1pwtB29WVtCnHM5SoGMjV1uHiUqCuZ7nPVCuU2dnvUzZpsE7ptJxpo0b8f98RXT8bu+uPR96Eitjt3FMmi6q1veXLsd69K1Oa5TJ4vpEnxpLJ4PkG0UG2EAUCid5iiJIjDLIiWVERMMZY4cVMlxcvXsDZ2RnZ2dlwcnIytjilCl9f2XPv4yN7yUuK+HjZOxcaWvKKmWLb8ve+pK+fIAjCmHgMmIEnW0UAs5RZTCdXAwD4uvgiIysDDAwCCCAKFCG8Xbj6itzdZcqbm5vsl7YKxFIxoo9G42jGUUiYBBYCC7T1aYuwNmEqrbzy8il3UxDgHaC2HIeKD5m6OkTJIkQejlRZTZBfEBKGJPDrFAqBJUtk+9R8tKIOR0GULNKuz1R9dH19Edw2A4nVlWR59YmszZcvZX0sFAKVK8uUUjnv1v4WVctAZDtw1uCIdhE4fmITEt9eV319BkJbfY0spoRaSsoSrPyD1piuEYq/tEurJZwgCEITTgEbgW7jAbunwJtywJkxAID0rHS09WmrvaV3zhzZIDpnjtoi8qnupLQkJKcno61PW42uB3KrrtYuCioGcsvlvyB82G9IePUJr44ZbWcgMjASQX5BaO/bnitfwDIrr3PJEtnHQoMvm7K1XGOfqfrohIYiINuZ8zDgZJF/pADAwkLmAiAQAHFxsh8C9vYypbVVKzAnJ56LAmMMAa0GKdQJ03LxKQmHV0NiCsFPjFHwjzK69IdyijXqS4IgygJajXVGGBDDD4bLgn9sn8iCnyxfctH5fov89NqWVnlA9Y0WaWQKC1oqyTRsatuSX4eFBT+ISSHnYL6lBfObVb5AHxsjjRxF5ZcwlC6Jjy79YSK5fwmCIEoEuVIgz5jg7S1VX9gIH5d8Sb4sh6ndO8UUUi463zXWVa/KjMoIeUOjRtnX5TeApuwAGpU+ff7QGDSIn8JFeTUpgEW2g3aZBkoAisovYWjal48u/aHFbI9RKIvBXwRBGJ7oo9GImJ+JvFeWgN1T1O+7R2W5+HjA9+VlxLuFlejHxdLCEglDElCr/xrZOvMQyP4NiMXzvOfaR+WrQXF9ecnRIwg/DAT9Z8tNdSseFyWLEHEoQv1a9GrQOH6rmXov4EamoRJNQU0aI/H16asmX/PewkI2bS8PNsvLk/mcensjxRu8aXw/Vz+TCbZTSwkpygbDVCympQGaQudDVnCCIAxB0Jog2dT4Oyukuunrkh6DlL8B+ZJ81q3PYmZZLp2V7/k/Vu3HanqZdudbG2U5NhU/POpXoxJwFsjCpqHV9Z2mcwt8AzXcAE0WU43uCfr80CpbSO3tZblJBQJuSdLIdnhvkY4o2NclCVlMCZ2hfKx8yApOEIQhCPAOAALmvssROldt4Imhx6DCAk8tLSyx+9z3yH/pi8eXtmJ4w+F6yb/KtzYCKf0+4lkvFY8rIrdMapMbVF3faTq3gCFVsRKlzgq76g7ROSd0sqqDQN9AHMk4wll0Naa00mfSb3ld8mlHQD6xL/u/VIqwv+0geuovs0gfs0LYrmyt0ncZE1JM9Yw5T/+SIsantCwaQBCEaRHWJgyRU70QtPhLRE71Uju1augxSFkRVfkNUNipTYS54jS8uqn3wnKRKh5XRF5Wm9yg6vpOp7yiipUodZbl3PkI/zMbbU5lIjk9GQfSDnCKrnI/TWs9TXWfaKswqCsn3w8A6ekQCxii2gHBQ4CodoBYwGD5KhfhG/5Dwoo8hB8Qw1KquSlTgPKY6hlj5f4kCIIgCFWoyw1tiJzR2uTtLCwXqeLxVlVbgTGGE/+e4MrKrZ5a51PVUT5ViOOWInrfdKS08EJAq0EIu+oOy7nzETzGjpcP1M7SDl7lvDCk/hBMaTUFH2/8GCf/PYlccS4A8NvUVmFQV04pT2xUV3uImueCCQABA0TJQPhhyFJHvXkjS9z/+LFxkoRDe32t8DXKCJ2QJ2Ynq6P5UpIJ/nVOFk0QhEbonSqIorFPcUyTp+BUpCj9p3jOned3CrVIynORqkPV8fh4IHYYUCEUCPtSZqlVlFFb5GVT7qYg4KENwob/CnxbodDBPrreU4gevQB7m42kZBEQKEJ4ejoCDkch6Z2iCwC54lykPk9F5OFIzE2ZizxJHq8eXp9oozDEx8sCm9zcgFatZMooUDBaOD6ev9SqAEjpXAdIz5Wd//o1cP78+9yrpkxJOLwWxpIlS5iPjw+zsbFhH330ETt16pTW55Z08FNx/JbNLbjI3OTVFyUZcKDJgZ4gCN0xxXfKGDkjFdFXGqRCz+k+hst3qi6wSRFd+sUg47IOlaoLaJJfg9tctwLBWhBBRZ/o+Ewqyij/P8Dy3V1ZeBdb5jfJgvlFlWcRXWxZRKBCoJNiWiiFvKbGjOY1m+CnTZs24ZtvvkFERATOnTuHBg0aoHPnznj06JGxRVNJcQKEzC24yNzk1QZtXHpK0tdWJ38ngiAKxRTfKXl6qMQJyxExP7PE1yXXxVe1KP3HnZMSCmT7wvL4DJl/5TlnWbCNmo+INkFMclq1kmVAatWq8GtQhUrf13eDfXyrNQW/C0ofC3V+sZYWlgi/VgFfH5OobvhdnyAlVLbsqRYrZvFkHe8Psa+3TNbQUJnl1M0N0c3yENU8D6kuUqRKnyCyeR4YANFhAYKs60AUGClrRz4FOGCA2QSRGF0xXbhwIUaPHo0RI0agXr16iI+Ph729PX777Tdji6YSudLSqpXuQU6mHlykrLSZurxFQRtluySDngoLAiAIQjdM8Z1KuZsCpHz7TkH51iSUZXXo0n/yb4bN+a9l5wTEAs7p6DL8omzJ0K6xsKyq/iOiixJ8/Lhs1c1jx1ihwVWqUKkEvxvsY4+3LfhdUPpYaAz8io1F2K5shJ9zgp+rH1xtXd8fe9cnCIjFdwHfabWMap8p+xHRaygSN/lBlLML0ePqv/e7ePoUePoUKW19ePlJIQBO1LRFuNenSFiWi/BrFWTtyK/j+HHzieYtIQuuSt68ecOEQiHbsWMHb//QoUPZxx9/rFUdxspjWhpXKyoLeTtNzT3B2FN8BFHaMMV3KjI5kqF7yLsp3RCTcC9gTPV4WJTpdW9vaZH6XJd+kcvaY/IunV0N4uKYbJWtd9PpEIH5LfLj5F2yVFzwu6DLx0KprLwPO67uyNqvas86re6ksV+U+1y+Ihic02RuA6NtC5wTmRzJX9EpAixyfg/Z8qQmusa3WSxJ+t9//zEA7Pjx47z9U6dOZR999JHKc/Ly8lh2djb3d+/ePVJM9URcnOx6FJfcNZYciu+RCb1XBsEQ+ZZLa18RhDliisoyY8U3RhR3vMmX5DNnz+cMYMy23Cvm7S0ttC6NyevVCOjj9oKn6KlK2m9MlP16aw1dyPmlCuQKpxL5knwWPq+bzMd0kgWLmN+d5ft6v1+i1ASVk1KrmEZERDDIcvLy/kpaMS2tCoApWE2VZTAFmQyJPq+vtPcVQRD6wyjfMaVGlRcvKmzs0iU4K84tjPkgjQ2y/4N5e0tZj8m7WNCaIOa3yK+Acqv840GlFdVAKCvbHVd3LNoPGVOxLqnBLBTTokzlm4rFtLRiCgo3WUxNoy6Cj6lavQjTxcT1BOOg5teztmOXpvdQ+Zi3W7asKbcXvDpUKbfK++SW3AKKsgEGWU3KtvI15ebnmu04pK1iavQE+82bN8dHH32ExYsXAwCkUim8vb0xfvx4hGoRdWNqCfYJgiidFDUxN1F2kedFB4q+6EpJ5GUtbhs65X42YKJo5Xe0e/ZfuLy9e4GmVF1vt/XdkJiayJWpnfYDHuwbDq+uqzFoePb7PtHnKjrv+kL87VRE13uqsv+VrynQNxDJ6clmOQ5pq68ZPSr/m2++wYoVK7B69Wpcu3YNY8eOxatXrzBixAhji0YQBMFhimmICONS2PKbCtl9ipzdRJeUSkWluG3olFowJATxoenwjQ1Rm9WmqEt7K7+jbxotUhmILk/gv+ezPQCAbuu78e6dAAK8abQI2WNdcd13Er9P1KSr0WYp1gK86zjLCV8j/FoFWSYDpah95Wu6mHGKt7364mrVbZnx+uhGV0wHDhyI77//HuHh4WjYsCEuXLiAffv2wdPT09iiEVqg67NvqHfFjN9BwkwwtTRE9MwbH2WFbtbhWTzlZNSXYnl2nyIbB0viB1Fx21DW1QpT0gpTZIuaQ1vXd1Tx/iWnJ8PH2Qe2QlsILYRIz0rnyjEwpBzfKNtQk0+wMOVebR5VoVCWB0vNxSpfU4P/JIDCPHfq81TMPjK7YN1mnIjcJNZpGz9+PMaPH29sMYgioG6pO32V14b4eGD8+PfvtjmkaSPMD95Shjoug2gIDPEuGYKSXOK3pFFW6NZdXoe052lgYEhKTQKAYk+zBngHICk1iZu6LUzZKkp/69qGMspLmyquZa+qHwpbibOoS3vr+o4q37+M7AzVBRkQcDJTbT1iqRirL67WqNzPPjIbkYcjAQCJqYmQMilEISLZQQ0Xq3xN06644IM73yDV6X1C/7WX1iLteSoYgKR37gjhZrw+utEtpoR5o2sSfkMk7Y+NlSmlQqHpvINkzSp9yKf/VE23GQNzWQDDjA03hdKySkveNmNM79ZNjYndVVCU/tamDcUxrbDxrTALbGGLmBR1kRNLC0tUuBaOmzMTUOFa4e+oojVSE+0zbRDWhb82vdwCWnfEIjhWeILUhKACdSuy9tJa1duFXKyy28HH5XbBp35bnhUVeG9EZXi3oENJrhSjZ4we/FRcKPhJf+jTslGSVpKitmVIGfXpH08Q5kxptpiKkkWcFQwAAn0CcTjjsFEDU+T9PXWaBE8/mKO3oCluTBP+Czg7I+NZObi5AeXKFby3XMDOmS+BlFD0GHkFfy3sXvyL00VOLcZexSAosVSMQ+mHCpRxsXXBvcn3YGtpywuYkkglmHVkFtgPqbIVvZzTgcnVAAB+rn64Mf4Gr7+r/1Qdqc9TuW0/Vz/cmXin0OuRy7j64mre+e1928PSwlJBligwyBaDEgVGmmRAlNb6muETBBgWY638VBjmmLZHXzkw4+IYEwpNP5+mIXN+FmPREIIgzATl/JPyFX50TeVjiDFAl3yf2hAXx5iP8B6LwxhZflAf9blH5SmO5CsYCYWFJ87XF3FxsvRQcW5hOnXokqVi5uz5nLn3n84soyx5Kyq1n1OL9Zi8633Se5HgfS7U7mO4/ZrSPVX7sRqvznaza2q1MpTifVS3sIC5pLIzm3RRxcVULabmaDHTl2VDfu1CIbBkielaSUzFkmOOzwpBEPpLIWaIMSB4bTAv/VGQXxAShiQUr1KlQbOwMVTR/1/f45vGFFdF6FDFU15+5Y5nuc+4Y255ArxekYm8p56cZdTP1Y/zJ5ancbK8n4mAk5kI6zIHlmPHAeA/IwDg98ISPk/FSPYFmACQmznVPT/BMXWR+PY6b58AgOicM8K7mriDuRJmky6qtGIu/l+K6MslRX7tpqyUAqbjgmOOzwpBELr7f6rDEGOAQbJIKA2a2viKLllimPFNUxR8fKs18BXeQ3yrNdw+RZ9Ql4pZWPqzLHhI7i/bqtV7ORt4NnjfEAMalKuJTkP/limlAbEQQIAh9Yfw7n3CkAQkLMtF2K5sRO+bjuC1wej5zW7E9B0jc2mQV+fsjJNV3imlAOQurup8kgNOZkKgYD70c/WD6JwzwnZl8x2JS1FgA1lMCYIgCKKUURKJ+Y2JJouwKoMpZ7l85xPq7JmFrAcuXFlvb4Yv1sxCyt0UfPTAAusyE/CfI0MViQMu/+4K2ymhapPgc8THI2pvKESNs2X20R/SCvifFoCzmAIihx4IX3KZl3C/1UNrSFOOYn0Ta8DZCZ/fssfMuCuwtLEDFix4/6vADKbeyGJK6IQp/tgyRZm0xZxlJ1RTpATaRIlC7917TC2LhL7RZBFWZYHmMgUExALO6fDquppXtn7fPZwFds6r/chwYhCfG4P0pf9gkLA7LOfOL7w/Q0KQ0u+j92lGA2Jh6/4APUZeQZBfEPxc/QqcYisBXF8DgWnAtLkpQEYGovdN52SJerUHKX2aIE36FKnPUzHL/R9EBzDgzRu+qboUTb2RxZQAoP7HlqH8MLWp1wx+AKrFnGUnVENLkpo+9N6VHXS1CBf2/ipbYAFwFk9bxwzkzt+r1UdQUztRh6MQkRyh+kQGtE8HLIWWuOPr8v/27jy+qSrvH/gnaaAtS9OyFVC6ueGMqCioQAuttkXFWdTHeR51ADegWmdkeYBQtE3r0EZAHQa1wVkA0Uf9Oeo4AiploIUKKiiyjehoacvWItCmVWlpkvP7I81t9iZt0tykn/frlRckuU3OPbnL9557zvegynxGeisuKg4NLQ3S86zvgC3Ge4H/+79OyyMnbDEln7i72ApUDkJvPrezC8CutI70VItKGF28UjtOSSp/3O96D19bhD31Bzaaja7vgLS3rmbOOuR1y4z1e0ZX/xExpecw+PBSu/fyJ+cjLirO+Q8VwPYkoCzBaBeUAoA6St3ROiyA1KvvcA5Kw+h2AVtM/UQuI7z9LZgtpp0t25XWEbaohLdA9quTY4tpuPcjpBBlc9A2zn5E9tuoY0vmlMQpmJI4BbuP7+5ymT2da1y2znqQnpgOhUKB/fX7cU38Ndh8/2ZEqaK8/0KZ8DZeY2DqJyGwTYQsf3YzCNcLCLIIZPAoxyBQjsFyuJHj7y57NjkDC0qmouinzdJb+ZPzUZhR2OVjsT9/D2sZojNW4UjSXOn1lLgUXBJ3idvP96YMej1QUiJw9d2b0Tp2ld1yTimk4lKQqE5E+dHtHSmkAGnEfpQqCi3GlvaX3OznIXByY2Daw0JgmwhZrFvyVkByN8pYb1tff/D1eGIXROzJgXpvCXTa2KDdQQoJNglML5mvQlVMx23ylLgULOz7XZfzm/rzYswaP6vjG9H06CApULRSQIFphvdx8J1pdr+Nt2UoqihCwYpTQOViIPUZFC4cgfyvhsH4TAmKc6/GzmEtMAkTlAolJo2aBMWf/4xdqlO46TjwyoT+qOn7o8tyZ6Vk4a4ft4TcNsM+pj1MLjkxw5Gc6jaMuvGEpYDkbpSx3ra+/uBrv3nbvsWoXAxDfax/+tzbHEwC1Zffn3zKSmGbwDQ21ultnc4SlEZE+N4fuNt9vW3q3doneVn+QGjTtchMzrT0/9wzB3j+KMSe2dj6yjin38ZjGWw+v3LX65ag1JAEVC5G5WslwIIFUFXXIr9kF9IS01B+dDv+dfRfeLqiCMqTp7BlA6AyAzV9XAel1v08FLaZrmJgSuSDcD4YhAN/JTwPFb1tff3B1wFStsE/Up+BOr6x+4OrrC2K7QeTnhy01dWLa08J7V1qb1GYnpZr93JCTAKiM1ZBHd+IVX8yeWxwcBUMd/tizOYgbm30yH0sAvlT8pGWmGYZ/V6paQ8mNcicsdfpt3Esw4SLJ3SU8wMNjMcsn5/6ySlpABVSdYgsn4mknw5DjzkA2gNca4J9BVCZYPl/ZQKk2/i24qLikByXDNNnn2Jhcx4SBjVhzF2bwi6FHTvKEPlAo+m45UbyYx2p21t0tr6h2D8y0Le1c3J8+1xrsF9ZW4nU9BHISxsAVXebdByaDK1lsgaNgVp3o9kIjfYHGOpjodE24pHZA7zeHrraUvnk5CehVChRWVsJo9mI8upyiKRyKB6dh7M/1wJwv/1ag2EBga1VWwE4/B7t27RPPBzEpXVK1QGVGgzJ/gveXamF6rmOZYxmI8zCjGTlYKCxEb8dng2FQtFRzusAQI382zRYZL6A8v2LsH/+BlzzwwAc2PQpapEEXcSTyFl2LVITTmPrd2UQivbR9t9HA/0USP1eoCzlvCU4FZYUUv379EdDSwMaWhrwtKiCdsxmPKx+CVp1E0RVR/2Ew/GPLabUq/naeiCnbgVEnfG5lUsG5HZXIiCJ6t3M2xzIddfrgSEjf4Bh6GZAXQ3DuCU+bQ9dbam0rT+VUuVTcOsqGO727+HhIC6t4/g1UMxLwe9y+zp9fvHOYhRVFKHKfAZHBxoRUfkxdh3bZVNOoPK/boBx9iO4vf8/sH1kK86Jn1De7zSuvkyHRGUtNC9cDOTkWO54nB2DrO8A7TcjkXdkKAAgb8t5FFRYEu8DlmDY0GqQyiAUQOXlUai8aYTX9RlKE4QwMKVeTW4nwWBjH9rwEoq5V3tFLlI3wVGg1t3ac8BQHwscm2iZHnO83qftwR/dRnwNbrtz274rxzJ362gb1K3fv75jn1IAlTeNcFnO4p3F2F69XfpsoQBab1qD6tix0s+uUqqQv/oAtrwikL+rD1TVtdD/NB2Xmo/i87rH0BANl7f0ASD1/iVInXiv3fdG7nvC7TqH0kWqvO/pEAWYRgMsXQo0N1t25t7eEmobqPf2uggHqQmp2Fq1VRo9HLDBUX68/+7rrfaeFsjuEYFad2vPAYXSDJH6DADfAz1/dJPx9Ta89f3X16lx6oOZGDx0IDDFebkXXzJhaVEzRty2Hvc+YEBeWh50OpXPxzJ362jbpcCWAgqkTrzX5XqNefhF4N2jlm4B49cAAFINamDZMpffbVy8EMX/73co2aNBy49JqK/LAxQvuVz28qrn8Ne/zcWixWZo0zu+968zbkdtLTDvyXqcvnINFk1ahJKdJdhQ+SKOtZ2FiLD8vdwvUpkuinq9UM5B6+/+eGGXtqaX67E+pqG8E/nIMVWQq3RCcmPdrxcuMuHsz5eFVJ9joPPNK3Z4o6U1WF0NxbwUaNO1GPZVvt+OZY5p2TrLc+pYJsxLRkZSBjbfvxnL/3gPKr/ZisizK3Fg72NYskSBnJz27Wp7AcTeOUClBpf/6l18kzLf6XMzkjLwXf6/UFursKuPF18yYe6iH2E0tQG3LAXGr4FKoYJRuL5lX5he2OP9UZkuqhfj7VjfhPKtQ393RWAf2vASkP6RroTyTuQDvR4ouXsOxJ7ZACwtT67SCcmN4+jzgG8PftbZ5hWV/AWgMAKjPrZrDRRCYNM33o9ad3fudLxVP/Oambjrxy3428x8/OVl13W4LH8g1PGNGH3neyiYUoC0hDT8/KWfo+CHjSi7qAUb/zUNtbUKabuRRuiPXwPMS8b3I+cjSTnY6XNVShWWLFFI9WHtZjD3yVMw/hgDRDZLLbTugtKUuBRZZ/BgYBqG2G/SN90NxoJ5IdBL4oEu40VaD+klVzQ6HdByNt6STgiWIMVVOqFeLQA7XWebV8vR6wChAo5NssvzWVurwMa//dy+X6WH8rk6dxrNRpjMJiTHJSMlLgX5U/Lbuwp4Ps/mPhaBxrpYfHVjJJTP/xFP7yhCVUNVR5/RVB0UsbVYsLDN8tQ2LZkAGqKAatNZJMUm2X2utTwAgB07UHznEGjLC2Cc+AcpLVVnZl4zU9YXJQxMwxCDlZ4VzAuBYMQDoRTs8SKN/EmjARISBO546LA0QObdlVP9ug/KYf/qVhmCsNPZtk5aBy0tXGSCKu64FKhJLakeyufq3Fm8sxhP73gaVQ1VONpwFEqFEiqlyvvzrE6HSrXB0ju1PXE/9swBxq+BmJuIt/tn4ebiK7DqQy0SlYMQGxnbEbwqAEOLwS443V69HUuLmlFTA8x7PxHrk9o/u72lFePXwKErLKIiohAXFYeU2BQUTCmQdWspwD6mFGaC0Ucy1Ppldre8odSdMNR+GyI57F/dKoMMdjqj2YjsDdmWUfF7LH02kapD4cKRyP9qmFQ+4+xHOu2D7cu0vy5XXa9H0QcaaK8zQDx/1JK439qyWamBMm0FzNe/JOUsTYpLQk1jjdNAK1tDDi/FmS2PWD5j3Bq7kfspcSm4f8z92FGzAwdPH8Q18ddg8/2bEaWK6lpl+pHX8ZoIcQaDQQAQBoMh2EUJC6WlQiQmWv4NRYmJQgCWf8m17tZRqG8j1D38/Tu0mdpEYXmhyHolSxSWF4o2U1u3P1MO9SuHMnRHYXmhgBaWh/qoAIRQxR1z+n0KywuFQqsQ0EIotApRWF7otO6Oy9wxb6PLuiktFSIiwvWxtc3UJgpX3CFGT3pcRMTUCEybI5UL6uqO59PmiEEahSh8fIwYpFF0rIPDI7losN3zlFUpft0GA8XbeI0tpmRHDlfr3SGDi3XZYx1Rd4T6McKfiiqKULDilGU+9NRnULhwRFjMvBPq7Fo521tM73joMN5/bpr75WBpDf3mqS1227djZos/3vkUGhoUGDQIOHu247Os+0VEhP28CdLfv1aC1G9aMP/Yxfhl/mX49L2xMO1YiFG3v4Zv/3m31JKa8etkbHs1AkWpJmjTIU1ZaiuxKQI1A02AwtLPWZuuDYntjqPyqUtCvX9qLxmD0S1hUUdy6IjXS4X6McKfKmsrLUGpIQmoXCzr3JByFKjZiOzys45fg6TCDJy/9nmn73CVGN9x+3bMbKFQuM54P3GiJSj9zW/sj62WHKgFKLuoBdp04LlHr8W2mdvw4zvPouXMcBz8Wy4u/9W7UMbW4vIpa7F5xygYf/NfMKljkNw2AClNEUhRDrH7rpoYEzJORSKr72g8NfkpmIUZVz64CrHDG/HiSya/1GEwscWUAsqxdY6tdeQXbLYjGWCLafc45oT1V8ufbSun0WyUZmBy/I6u5Pl1dw6zOyRpOhbK7v9Op31UHcthMpvw9I6nLfUigPRTkdg+stXub6y5VI1mI8qryyGerwIMSVDHN6KxLrbrlRdAbDElWXAcAMlR0uQXbLYjGchLy0PhwhHIWj0bhQtHyH60s6zo9ah8rcT9lLnduCti28opBZp75kA8X4XX16mdlvOUk9SxVfeR2UaXd5zsDkk2JzpLq6yFAsBNF9+Em9ffjMHLB+Pm9TejxdhiucApL0BZVRkKyguwYf8Gu2lPkZDolDaqqqEKZVVl2F693bJsqg5QV2PEbes9lt9frdKBxBZTCqhAtJiy1ZWIqOf5dSaxpCQUJdVI/SidWkz9dFdEapX10KLo6au61Kprc5JyHPm/7eg2VNRUSItmJGXgy7ov0dDSYHlhzxzg4yXAJB0wXg8FFLis6ll8896d0vSmsS1Ao4tB9q7KF6hW6a5giyl5zZcLU18vYh37M/qjfyNbXYmIep51zni7hPWu6PXA4MGWh7uThUaDvJoEaAfcIeWEzUvL62jhmxONol+qYVy8sOMzu9CCmpeWB226FqPvfA/q+EY8/VR/pxZETzdgKmsrnVp1Oy2KzYnOsY/qwdMH7Rb99L2xaCjZZwlIAUtqq8ZEqPeWSPVSu+m+9n7MlgIqzLDLVZoUm2RXh52VX/YCnh8gwJguqvs8pQ9yTJ0hh3RMoZ7KhIgoFGW9kuWUpshleiLricLxZOHFwduSngnt6ZkgCssL7T+zGyefNlObyFiXIZXfmiLKU9FcpZTqTlFsvx9aCFV/g6Wqos9Y0kZFnRHKfufsynHHvI1SOimFFiJlfoTdZ2Suz3T7fa7KHyzexmtsMSWPV4uOrZM92bXPtm/ML+ZvQmKigF7v3OrKAdpERIFnN9odln6Odq2m1oPxxInAoEGWh+3JwovbXZW7XpcaAwXQ0cLnh5NP8c5iaSCU1Od06feAXu+2aIsmLUJ6Ujr67Z+PvqtP4nDpUjQ3W1Zt4sSOc4+3fTn/ee8/kaQcDJUJSFIOxsC+AyxvtPYHNpUCLYPRJ7rV7q7iuyunovC9V5D131XQphdi+i+etMsmMClhEn4xfxOih9TjF/M32X23tcXYXYuqLPVQoBwwbDENrGC2Ttpe6VmTEbu6QpVDKy4RUViyOQm88KJRqAa2J4Rvb63LKh7dcZLo7GDsTYvpL9VCUeCixdTHIg8aZHnYfpVdi2/7OUUdeVSIxESpaPfe6ybBfvvyCqVJWkXb1c3flm/Xipm/Ld/1+pUXdqxfAcQd8zYKdXyDAIztjcxmcce8jR7Xz3Fih/xt+TYJ+48GtVXUE7aYkl/42ifUn62Xtn1jkKpD1OB6lxfLHKBN5B+hOIKXAsymKXHF8ggYmxM7+joCSP3kVEdTY2cHYy9OKHm3LoN2nxpZfUdDm17osYXP3flGpwPOnbM8bFtA7Vp8U3WIjD2BZf1fBjQaqWi7dtm3nErnofZR78NuKJdW0bq6CxeZsPqz1XZlePXgqy7LXFlbKSXNFwqgdewqnDk5AGNu/jegNGHMzYfw7sqpbtcZcM6tuvv4bql8SNWFRj9ST3ooUA4YtpjKiz9bL+XUN4Z6h97ef5n7HDmx2SlKS4VISLC06ElTYL70Qrd2mu7sc+7ON+5aTL2ZQtbVlKSYltPexzPH5T5hNwWqTf9bV+zuBE7LEer4Bum7bL/bl+luQ2W/9TZeY2BK3eK4E/vzxB6IeaiFYPBB7vX2biG3rL/F7uR6y/pbgl0kkolAHY/t9jkfD849cSxvM7W132oXQh3f4HK9HQeFQQtRsL3A7edZ69H6uYMGmYU6vkEaCJWQYPYp2AzUb+NvDEypR4TiiTwUy0w9o7dftDiOGM5YlxHsIpFMBKpVzm6fk+nB2baMro4Rdq2g7ftNm6nN5bKuPksV2drev9QkEH1GXDbjWaeLxKxXsnp0nQOBfUypR4Ri/85QLDP1DH/k2Q1lEYoIj8+p9wpUPky7fS6AB+fu9J+2LaOr0fu2I98L0wulGaccl9Xrgccf73jtkdlGPLS+CEblD+2fpAT6NuM/KQtgFma7kfeOGRHCGQNT6pZQPJGHYpmJekJaYprdyTAtMS3IJSK5sEyt6V2gZA0Cr3xwFWKHN+LFl0zefUlODoxV36LoytNSAGmdsjPrlSzcvP5mZL6S2aWBeY6TA9z5vx91aaCuq9jZcTCSdTYsx2V1OsBkAgCBlhHbkL0hGwUrTgEQQJ8fgKizlkFMsFwUatO1yEzORHpSOnbU7HBa73AdrMgpSalHcBpRIvnz65STFFZ82Ta8mQbUHccpNNOT0lFeXd6RoQWup940mo0ofu5OVH6zFamXZyJv/rtS+fR6YN6T9Wi5qQAYvwYAELW6Di1n47s746n993dSP3o98FiuGcKstIygn5cMPH/UMquT9Xm7wvRC5E/J9zilqJymG/UGpyQlWeE0ou5xggCSC3ctP0S+bBuOKZZG3Lbe6+9x7DKwv26/XVBqfd2xK0HxzmJof9iIsotaoP1ho13if50OaDkbb5PmSoHMGXv91mtArweGjPwBBStOoayqDAUrTmHIyB+cjuk5OcAVM1ZLaZ0A2KV5iouKQ0pcCgqmFEhpsiwTDrjuQhGS0416gYEp9Yhg9uuUe+DHoJ2Iwol023/8GijmpeDeBwxe/Z3RbHS6HR0T5dyy5qorgWN+UNsgTaMBEhIE7njosDQD0rsrp/otR7dOBxjqY4HKxe2FWQxDfazLY/q9DxigmJcitdxm3PMNslbPRuHCkTi98DS++/130KZrpcA/9ZNTUAjX6+1L94pQwsth6hE5OcG7hW8b+MmxG4FG09HNgYgo1EmtfTa3tb1RvLMY5dYpQwFkJGUAAKobq6XX4qLiMPemuU6fmZqQiq3flUEoAIVwnj5VoVBg2uXTkDN9WldWyeN5RKMBNNpGGMY9016YZ6DeW4KFiwaiqGKZXT0smrQI5dXl2F+/H9fEX4PN929GlCrK7ffm3boM+HApKm8agdSJ99qtd1frWe4YmFLYk3vgF8ygncgR+5lSd1lv+3vDdnv7ruE7u5v2KqUKqQmpUh9TBRSYe9Nc5H81DJh5qd2ghby0PGDPno4+pjZBmreNE+62fb0eaG4GBg1yfR7JyQEemT0AxTtHoLI2C6npI5CXNgDFO5dJfUC3Vm2VlreuT3l1OZZ/vNxjXakezUW+IsJS+LhhwJT2fVGvh0qnQ75GA+Rs8aquQwUHP/VCHIjkf6xTCheBHlDBwJds2W5v2DPH0g+0vf+leq8Oy/IH4uzP7VsdVSmXWiJNFyOXbLevyH1P4MDbt2PSJAV27er8+GwpSwEELNOtLk17Eh8f+xgVc9fB3JiAhASBmhqF1+uWvSEbZVVl0vOslCwAcHpty/ROAsukJOf1dfWazHkbr/Fo0AvJ/dZ2KGKdUrgI9IAKa9oe21YkOY8kpsCy3d5QqQEMSYj6pBCRqkgY6mOxYjlQXZ1vufifCQzTADkaDfRLj0HXrIFGb8kHag1GjWZjxyj+v70MGBRQKLyL3SxlsRAAXtzzIhpaGoBJxUClBlHp7wKY5/W6uetesLVqq3Th51W/UFe3/eR+K7AbOPipF2KCef9jnVK4CPSAinAdSUyuuc212T6aKLU+UtrekPoM1PGNeP4P8dBpY51ygEqDRHNyoBu4DDXnBkKns89Rur16e0egm6pD1OB6r4/Llm3fQgGgxdhieTJ+DTAvGWd+/geXf+duYFReWh60Z8cg6ztAe3YM8tLy7JLxa9O13vULdZV8O4wTcgfsVv6yZcuwadMmfPnll+jbty8aGxudlqmtrcWjjz6K7du3Y8CAAZg5cyZKSkqgUnnfkMtb+URE/hPQW+16PYo+0EB7naH9dqn8cy9S90i36vfMBio1uOOhw3j/uWnSreiWIbG4/a7z+PTkbJh252FF4WD8LreP0+c4dpeyff5Of/tb5lZu85262b4d39t+dDvKa8qlv81IysC2mducvsfjXfUQvOUeKN7GawELTAsKChAbG4vjx4/jr3/9q1NgajKZcO2112L48OFYsWIFTp06hRkzZmDWrFkoLi52/aEuMDClcMF+qhT2kpJgPFaD4jvUqPyvG9jHtBeQ+lm2J5KPGlyP82fiYSx9EcUfLsX6lGZUqc3AH49KyfjPnByA4p3F2FmzEyZhglKhxOTEyW6T1s9f9BPOt50HblkKjF+DjKQMaeCU49849aHuPw35Lxx0eeBtMbbg9tdudzmC3mg24g87/oANBzagqfJetO34XyzLH4jcxxym8eWBXeJ1vCYCbO3atUKtVju9vnnzZqFUKkVdXZ30WmlpqYiJiRGtra1ef77BYBAAhMFg8EdxiYImMVEIwPIvUbC0mdpEYXmhyHolSxSWF4o2U5vL5UpLLdtqaanr5179UZDIpBhhr83UJjLWZQhoITBtjoD6qLhj3kYhhBCF5YVCoVVY3rN5f/QDf3R+Twuh0CpEYXmh03ckJJgFYDl2quKOifxt+aLN1Ob2N856Jcvuc7NmRXl14HXcL/K35dt9DrRwWT5f6sqb/S6UeRuvBa2P6e7duzFmzBjEx8dLr02dOhVNTU04fPiw279rbW1FU1OT3YMoHLCfKsmB45zitjPo2HKcGMKriSJk0i8ulCa1COX50It3FmO7NS/p+DXIWPUQ3l05FYDDoKf2963J+J3eg/v+yFffvRmIPgtEnYVx4jJEKCOgUqqk31ijbbSrO6c+1JdnwpiUgKLHx3isY8f94tWDrzot053+0sU7iy0zR/3uZRSsOOV2v+sNghaY1tXV2QWlAKTndXV1bv+upKQEarVaeowaNSqg5STqKTI5Z1Mvt7Nmp93gpJ01O10u53ghFUoXVp7KKreZ4ry9UJCj19epgWfOALozwJ45UClVHTMa2QSIAJASlyINBnJ8z+q7hu+cAsfWsauAxUMAzRBgvF4KDjUaQB3fCMM4TXvdFaB4Z7Hz4KP576J43cPQ/rjJYx07DtpzxZeBgo7bWWVtpWXmKEMSULm4Vw8K9Ckw1Wg0UCgUHh9HjhwJVFkBAEuWLIHBYJAex44dC+j3kXtyO4ATUfeZhMnjcyvHC6lQurDyVFZ3LW3B0pUsBnI5Np/6YCZwfjDQMhio1NgFbrYBYmF6Ib5+/GvkT8mHSqmS3stMzkRGUgaSY5MBAFUNVU6Bo7ssEjk5wA0rfiNN/SlgqUtr8v8t07dI3+dNHTuO2J9+9XQUTClASlwKUuJSkD8536sR9no9MHgw8Nhj9q32qQmpQOozgLoaSH3GKcgN5ZZzX/nU43zBggV44IEHPC6TkpLi1WcNHz4cn332md1r9fX10nvuREZGIjIy0qvvoMBi7k6i8KNUKO0SnSuTvw12kXpUx/SSS1BWVRb0XKupCak+5b287z7g9dct//f3sdnXjA3L8gdioeYntJmNuPWhw3aBm6fZoRzfy96QjaONRwE4B46OU3wumrRIes9Sd2VSwnx3dedNHeel5QHPPYdKtQGpBjXynnoSKqUK2nSty890V1c6HXDunGWZiIiOVntL3RSj8r9nu5xetDfl//UpMB06dCiGDh3qly+eMGECli1bhtOnT2PYsGEAgLKyMsTExOBnP/uZX76DAiuM8/v6LkRHXoZosd3irELdNzlxMv5VOaP9lqIGkxe+Euwi9aicHOCd/r+R0g8FO9eqr/Ohv/lmx//9fWy2DY7Kqsqwfv96zLxmptv9LPexCOQ+1q/9WdfmqAc8B47LP15uSai/Zza2V2pwzz//ivc/XwHj4oUwjTYhOc7SWDb96ulu6862jieOmgiT2YTsDdl2xxCVUoX823QdB8xOjivuAsmJE4Fjx4CoKODZZzuOu51N49qr8v8GavRVTU2N2LdvnygsLBQDBgwQ+/btE/v27RPNzc1CCCGMRqO46qqrRHZ2tvjyyy/Fhx9+KIYOHSqWLFni0/dwVD7JQogOqQ/RYrtlO5rX3She8qzN1CbumLdRRA2uE3fM2xiWo4M742o7ktOoaU9l6dfPsk/36+f/73Uc0W59pKxK8U+duBlK72l9pTKpjwpAiKgB1UIAovCX6i4dC3w6hnhI7+BYV7esv0UUlheKqMF1ArBkE/BFOBzbvI3XAhaYzpw5U8DSrcPusX37dmmZ6upqcdttt4no6GgxZMgQsWDBAtHW5tuGzcCUZCFE88+EaLHdckoF80pWsItEIchVICSnwMBTWbq6T3sTeLtK4+QqFVSXy9KFK2WpTNYy3PWCEImJIqt4tFPwbLdObgrn9hhSWirEoEGWh/VvrOWNiHD6HMffKGNdhn05HeqqM3K6MOoqb+O1gCXY7ylMsE9EVk7JszmrEPmJlCi+XVZKFrZM3xI2ZfFm3zGajXi64mms/my1ZQ55K4fk+VY+T3rkY98ivR4oKRG4+u7NaB27yu7We1FFEQrKC+yWL0wv7FgnN4VzWw/tyxuVkCaImFDXB4oPPsCui4Wl3+m7Z9zOIrWzZie2Ht0qfU8wt59g8TZeY+crIgobvvbHI/KWr4OQ/MFdn+lAlMWbPowqpQoRygg0tjTav5GqAyo1yJxxGLZ9SX0eh5CT41Nnd50OqK1VQPHONFQ/Z9+HNS8tD+v3r0dVQ5X0mt06uSmc22OIRgMsXYriG85bptStKkMZAEyxvL0VBmBnsRT4OvYZLaoowr+O/qvrv1m4DQjwgIEpEYWNzgYQEHVVMC56LANoCiAAbG1vIc2fkh+Qsngb7Domv0+JS8El/12FyMsP48Dbt0N/uX0KsUDGUJ4CX5VShZnXzLRr/bRbJ5vCWWO+iROBXbtU0GjyscWx3O3LV27IhrBprbaypqNyp9u/WS9Kg8Nb+URERDLUk90HvM1o4e5Wt8+37QPEdj0mjpoIIQR2H9/tcp2sy5bcPQctZ+MRESFgMik8roPt+tsKeNehMGgx5a18IiKiEOZtHk5/8PZug7uWP3etlz0dTzmmadKma7Hlx7uAmTpAM8yuENKyN50EKjX42fXNaPpujNuuB0azEeY9nyG5SQnExeG+iTmIUEZg17FdgW9FD3Tzs4ywxZSIiEiGwiEvry8tqf5YX5etzE9947IQvrZIF1UUQbu9AEIBKASgzShk1yEfeBuv+TQlKREREfUMV9NnhhqNxhIPejMAytqC6WrOem+nWXU5RambQribztSdytpKiPZ5SYXCc59S6rrQ28p7kXC4WiYiot7LlzvQlbtet8sMsOrTVQAs3Qd0OpVXY39cdjWYonL5R74OSOpKNgSex33H2pGx3jQ3LhERBZbcx8+kfnIKW8dCapU8d/4ctOVaAIBGk+9V6ilfMnP4msWjKyPrvTmPy/136WnsYypjckroTEREoU0uI+fdMZa+iOIPl2LV9W04J36SXnd37guF1khvzuNy/138hX1Mw4Cv/V+IiEKRt/0HqXt86e9p1ZO/jerRXOS/14gnpiz26tznqU+qWz28sXlzHu/K7xLO2GIqY6FwNUhE1F29pcVIrjzdSg7Gb+PtuU9qjdwzB6jUYPSd7+GrtU94/nCbFTJWfRvwcyzP4x28jdcYmBIRUVCxj11weQo+u/PbBDook5LdP18FGJKgjm9EY12s5z+yWaGiK0+7nCygqxiEesbAlIiIiDoVqAsDx1miphnex8F3pmHhIhNOX1mEVw++CgCYfvV0PDn5SZ+DOGsg+Po6NU59MBPL8gci97EIr//e3+M43M2KRRac+YmIiIg6FahJhSprK+3SP219ZRxazgJLi5pheLRIWq6wohBKhdLnIM46qj5/StfK15X0T544ri/znHYNA1MiIiLyO8fAL3PGXhx8ZxqiM9bD4LBsMIK4rqR/8sTfgW5vxcCUiIiI/M458JsK1XNAUYUBBeX2ywYjiPOUx7Qr/UX9Hej2VuxjSj2GAxyIiMhoNuLpiqe73cc0kNhf1P84+IlkJxBpRzgKkoiI/I0T3PgfE+yT7AQiiXCXEiwTEfkJJwcIT5zgJnjYYkohjVe1RBRMnBwgPPFunP+xxZR6BV+uatmyQUT+1p07QUazEUUVRcjekI2iiiIYzUb/F5C6xDowasv0Lcifks+gtAexxZRCmi9XtWzZICI54QAb6k2YYJ96BU/pPhxpNB1ZAYiIgo0J2Ymc8VY+9Ro5OZaWUqaqIiI54AAbImdsMSUiIgoCJmQncsbAlIjITziSl3zhS1ckot6Ct/LJo1AeyR7KZafQxLy6RETdw8CUPNLpLCPZdbpgl8R3oVx2Ck0czEJE1D0MTMmjQMzW1FNCuewUmjiYxQPewiAiLzCPKRGRn7CPqQcBTCSs13ekgmPWDSJ58jZeY2BKRESBF8DokZNnEMkfpyQlIqKe4c1t+gAmEma3HaLwwRZTIiLqHjZZ9gh2FaFQxilJiYioZ3C+3x5hTUcmILC1aisAMA8qhR3eyqeQwoG9RDLE+X57BNORUW/AwJRCCnOTElE48eVim+nIqDfgrXwKKbxjSEThxHqxXVIicPrKpz32H81LywMAu2WIwg0HPxEREQWJNYvWmLs2YZP6FxAQUEABbbqW/UcprDBdFBERkczl5ADfVhnx76Tfs/8oERiYEhERBY1eDwwZ+QOqtmTZvc7+o9RbMTAlIiIKEp0OMNTHApUdHedT4lI67T/KDCUUrhiYEhFR2DOajSiqKEL2hmwUVRTBaDYGu0gALAM51fGNQOozACyj7WdeM7PTxPnMUELhiqPyiYgo7Mk1OX1ODvDI7AEo3jkClbVZXo+2Z4YSClcMTImIKOzJOTm9SqnyOUjOyeF8BhSeeCufiIjCHpPTE4UGtpgSEVHYY3J6otAQsBbT6upqPPzww0hOTkZ0dDQuueQSFBQU4MKFC3bLHThwAGlpaYiKisKoUaOwfPnyQBWJiIh6Kevt8i3TtyB/Sn6ng4uIKDgCtmceOXIEZrMZa9aswaWXXopDhw5h1qxZ+PHHH7Fy5UoAllkAsrOzkZmZCb1ej4MHD+Khhx5CbGwsZs+eHaiiERERecVoNqJ4Z7HHqUKJyH96dErSFStWoLS0FFVVVQCA0tJSLF26FHV1dejbty8AQKPR4B//+AeOHDni1WdySlIiIgqUoooiaTQ/pwol6jpZTklqMBgwaNAg6fnu3bsxefJkKSgFgKlTp+Lrr79GQ0NDTxaNiIjIiZxH8xOFox4LTL/99lusXr0ac+bMkV6rq6tDfHy83XLW53V1dS4/p7W1FU1NTXYPIiKiQOBofqKe5XNgqtFooFAoPD4cb8OfOHECt956K+655x7MmjWrWwUuKSmBWq2WHqNGjerW5xERUc+Q6+xLnuSl5UGbrkVWSha06VqO5icKMJ/7mH7//fc4e/asx2VSUlKk2/MnT55Eeno6brrpJqxbtw5KZUcsPGPGDDQ1NeEf//iH9Nr27dtx880349y5c4iLi3P67NbWVrS2tkrPm5qaMGrUKPYxJSKSOfbXJOq9vO1j6vPQwqFDh2Lo0KFeLXvixAlkZGTg+uuvx9q1a+2CUgCYMGECli5dira2NvTp0wcAUFZWhiuuuMJlUAoAkZGRiIyM9LXYREQUZOyvSUSdCVgf0xMnTiA9PR0JCQlYuXIlvv/+e9TV1dn1Hb3vvvvQt29fPPzwwzh8+DDefPNNrFq1CvPnzw9UsYi8otcDSUmWf4nIP9hfk4g6E7B0UevWrcODDz7o8j3brzxw4AByc3OxZ88eDBkyBL/73e+wePFir7+H6aIoEJKSgJoaIDERqK4OdmmIwgNzghL1Xt7Gaz2axzQQGJhSIOj1gE4HaDRATk6wS0NERBTaGJgSERERkSzIMsE+EREREZE7DEyJiIiISBYYmBIRERGRLDAwJSIiIiJZYGBKRERERLLAwJSIiIiIZIGBKRERERHJAgNTIiIiIpIFBqZEREQyptdbpknW64NdEqLAY2BKRET+x2jKb3Q6oKbG8i9RuGNgSkRE/sdoym80GiAx0fIvUbhjYEpERP7HaMpvcnKA6mrLv0ThjoEpERH5XwhFU+x1QCQfDEyJiKhXY68DIvlgYEpERL0aex0QyYdCCCGCXYjuaGpqglqthsFgQExMTLCLQ0REREQOvI3X2GJKRERERLLAwJSIiIiIZIGBKRERERHJAgNTIiIiIpIFBqZEROSR0WxEUUURsjdko6iiCEazMdhFIqIwpQp2AYiISN7u/N+PsPFvM4DUk9g6XgsAyJ+SH9xCEVFYYospERF5tPWVcYAhCajUQECgsrYy2EUiojDFwJSIiDzKnLEXUFcDqToooEBqQmqwi0REYYq38omIyKN3V05F8a+KUVlbhdQELfLS8oJdJCIKUwxMiYjII5VSxT6lRNQjeCufiIgCRq8HkpIs/xIRdYaBKRERBYxOB9TUWP4lIuoMA1MiIgoYjQZITLT8S0TUGYUQQgS7EN3R1NQEtVoNg8GAmJiYYBeHiIiIiBx4G6+xxZSIiIiIZIGBKRERERHJAgNTIiIiIpIFBqZEREREJAsMTImIiIhIFhiYEhEREZEsMDAlIiIiIllgYEpEREREssDAlIiIiIhkgYEpEREREckCA1MiIiIikgUGpkREREQkCwxMiYiIiEgWVMEuQHcJIQAATU1NQS4JEREREblijdOscZs7IR+YNjc3AwBGjRoV5JIQERERkSfNzc1Qq9Vu31eIzkJXmTObzTh58iQGDhwIhUIR7OL4TVNTE0aNGoVjx44hJiYm2MUJC6xT/2J9+h/r1L9Yn/7HOvW/3lKnQgg0Nzdj5MiRUCrd9yQN+RZTpVKJiy++ONjFCJiYmJiw3lCDgXXqX6xP/2Od+hfr0/9Yp/7XG+rUU0upFQc/EREREZEsMDAlIiIiIllgYCpTkZGRKCgoQGRkZLCLEjZYp/7F+vQ/1ql/sT79j3Xqf6xTeyE/+ImIiIiIwgNbTImIiIhIFhiYEhEREZEsMDAlIiIiIllgYEpEREREssDAVKY2bdqEG2+8EdHR0YiLi8Ovf/1ru/dra2sxbdo09OvXD8OGDcPChQthNBqDU9gQ0traimuvvRYKhQJffvml3XsHDhxAWloaoqKiMGrUKCxfvjw4hZS56upqPPzww0hOTkZ0dDQuueQSFBQU4MKFC3bLsT598+KLLyIpKQlRUVG48cYb8dlnnwW7SCGjpKQE48ePx8CBAzFs2DD8+te/xtdff223TEtLC3JzczF48GAMGDAAd999N+rr64NU4tCi0+mgUCgwd+5c6TXWp+9OnDiB3/72txg8eDCio6MxZswY7N27V3pfCIH8/HyMGDEC0dHRyMzMxH/+858gljg4GJjK0Ntvv43p06fjwQcfxP79+/Hxxx/jvvvuk943mUyYNm0aLly4gF27dmH9+vVYt24d8vPzg1jq0LBo0SKMHDnS6fWmpiZkZ2cjMTERn3/+OVasWAGtVouXX345CKWUtyNHjsBsNmPNmjU4fPgwnn/+eej1euTl5UnLsD598+abb2L+/PkoKCjAF198gWuuuQZTp07F6dOng120kFBRUYHc3Fx88sknKCsrQ1tbG7Kzs/Hjjz9Ky8ybNw/vv/8+3nrrLVRUVODkyZO46667gljq0LBnzx6sWbMGV199td3rrE/fNDQ0YNKkSejTpw8++OAD/Pvf/8azzz6LuLg4aZnly5fjT3/6E/R6PT799FP0798fU6dORUtLSxBLHgSCZKWtrU1cdNFF4i9/+YvbZTZv3iyUSqWoq6uTXistLRUxMTGitbW1J4oZkjZv3ixGjx4tDh8+LACIffv2Se+99NJLIi4uzq7+Fi9eLK644ooglDT0LF++XCQnJ0vPWZ++ueGGG0Rubq703GQyiZEjR4qSkpIglip0nT59WgAQFRUVQgghGhsbRZ8+fcRbb70lLfPVV18JAGL37t3BKqbsNTc3i8suu0yUlZWJKVOmiCeeeEIIwfrsisWLF4vU1FS375vNZjF8+HCxYsUK6bXGxkYRGRkpXn/99Z4oomywxVRmvvjiC5w4cQJKpRJjx47FiBEjcNttt+HQoUPSMrt378aYMWMQHx8vvTZ16lQ0NTXh8OHDwSi27NXX12PWrFnYsGED+vXr5/T+7t27MXnyZPTt21d6berUqfj666/R0NDQk0UNSQaDAYMGDZKesz69d+HCBXz++efIzMyUXlMqlcjMzMTu3buDWLLQZTAYAEDaJj///HO0tbXZ1fHo0aORkJDAOvYgNzcX06ZNs6s3gPXZFf/85z8xbtw43HPPPRg2bBjGjh2LP//5z9L7R48eRV1dnV2dqtVq3Hjjjb2uThmYykxVVRUAQKvV4sknn8TGjRsRFxeH9PR0nDt3DgBQV1dnF5QCkJ7X1dX1bIFDgBACDzzwAHJycjBu3DiXy7BOu+7bb7/F6tWrMWfOHOk11qf3zpw5A5PJ5LK+WFe+M5vNmDt3LiZNmoSrrroKgGWb69u3L2JjY+2WZR2798Ybb+CLL75ASUmJ03usT99VVVWhtLQUl112GT766CM8+uij+P3vf4/169cD6Dgu8jjAwLTHaDQaKBQKjw9r3z0AWLp0Ke6++25cf/31WLt2LRQKBd56660gr4W8eFunq1evRnNzM5YsWRLsIsuat/Vp68SJE7j11ltxzz33YNasWUEqOVGH3NxcHDp0CG+88UawixKyjh07hieeeAKvvfYaoqKigl2csGA2m3HdddehuLgYY8eOxezZszFr1izo9fpgF012VMEuQG+xYMECPPDAAx6XSUlJwalTpwAAP/vZz6TXIyMjkZKSgtraWgDA8OHDnUbsWkdDDh8+3I+lljdv63Tbtm3YvXu30zzE48aNw/3334/169dj+PDhTiNKe1udelufVidPnkRGRgYmTpzoNKiJ9em9IUOGICIiwmV9sa588/jjj2Pjxo3YsWMHLr74Yun14cOH48KFC2hsbLRr5WMdu/b555/j9OnTuO6666TXTCYTduzYgRdeeAEfffQR69NHI0aMsDuvA8CVV16Jt99+G0DHcbG+vh4jRoyQlqmvr8e1117bY+WUhWB3ciV7BoNBREZG2g1+unDhghg2bJhYs2aNEKJj8FN9fb20zJo1a0RMTIxoaWnp8TLLXU1NjTh48KD0+OijjwQA8fe//10cO3ZMCNExWOfChQvS3y1ZsoSDddw4fvy4uOyyy8T//M//CKPR6PQ+69M3N9xwg3j88cel5yaTSVx00UUc/OQls9kscnNzxciRI8U333zj9L51sM7f//536bUjR45wsI4bTU1NdsfMgwcPinHjxonf/va34uDBg6zPLrj33nudBj/NnTtXTJgwQQjRMfhp5cqV0vvWeKC3DX5iYCpDTzzxhLjooovERx99JI4cOSIefvhhMWzYMHHu3DkhhBBGo1FcddVVIjs7W3z55Zfiww8/FEOHDhVLliwJcslDw9GjR51G5Tc2Nor4+Hgxffp0cejQIfHGG2+Ifv36SRcD1OH48ePi0ksvFbfccos4fvy4OHXqlPSwYn365o033hCRkZFi3bp14t///reYPXu2iI2Ntcu8Qe49+uijQq1Wi/Lycrvt8aeffpKWycnJEQkJCWLbtm1i7969YsKECVJQQJ2zHZUvBOvTV5999plQqVRi2bJl4j//+Y947bXXRL9+/cSrr74qLaPT6URsbKx47733xIEDB8SvfvUrkZycLM6fPx/Ekvc8BqYydOHCBbFgwQIxbNgwMXDgQJGZmSkOHTpkt0x1dbW47bbbRHR0tBgyZIhYsGCBaGtrC1KJQ4urwFQIIfbv3y9SU1NFZGSkuOiii4ROpwtOAWVu7dq1AoDLhy3Wp29Wr14tEhISRN++fcUNN9wgPvnkk2AXKWS42x7Xrl0rLXP+/Hnx2GOPibi4ONGvXz9x55132l1MkWeOgSnr03fvv/++uOqqq0RkZKQYPXq0ePnll+3eN5vN4qmnnhLx8fEiMjJS3HLLLeLrr78OUmmDRyGEED3ef4CIiIiIyAFH5RMRERGRLDAwJSIiIiJZYGBKRERERLLAwJSIiIiIZIGBKRERERHJAgNTIiIiIpIFBqZEREREJAsMTImIiIhIFhiYEhEREZEsMDAlIiIiIllgYEpEREREssDAlIiIiIhk4f8DePEx2zPQS64AAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Load three component mixture dirichlet saved params\n", + "num_mixture_components = 3\n", + "\n", + "params = joblib.load(os.path.join('mle_params', f'femnist_{num_mixture_components}_mixture', 'polya-mixture.joblib'))\n", + "print(params.keys())\n", + "alpha_mixture = np.array(params['alphas'])\n", + "print('alpha_mixture', alpha_mixture)\n", + "phi_mixture = np.array(params['phi'])\n", + "phi_mixture /= sum(phi_mixture)\n", + "print('phi_mixture', phi_mixture)\n", + "\n", + "num_samples_distribution_mixture = joblib.load(os.path.join('num_samples_distribution', f'femnist_{num_mixture_components}_mixture.joblib'))\n", + "num_samples_distribution_mixture = num_samples_distribution_mixture.numpy()\n", + "print('num_samples_distribution_mixture', num_samples_distribution_mixture.shape)\n", + "print(phi_mixture.shape, alpha_mixture.shape, num_samples_distribution_mixture.shape)\n", + "\n", + "# generate users\n", + "num_users = 500\n", + "true_users = generate_true_users(user_id_to_data)\n", + "simulated_dirichlet_mixture_users = generate_mixture_users(len(true_users), alpha_mixture, phi_mixture, num_samples_distribution_mixture, all_labels)\n", + "len_sampler = get_femnist_len_sampler(user_id_to_data)\n", + "simulated_uniform_users = generate_uniform_users(len(true_users), len_sampler, all_labels)\n", + "\n", + "# Run TSNE on the label counts of all users\n", + "tsne2 = TSNE(n_components=2)\n", + "X = np.vstack([true_users, simulated_dirichlet_mixture_users, simulated_uniform_users]) \n", + "X = X / X.sum(axis=1, keepdims=True) # This will normalize the counts to proportions to ignore num sample per user effects\n", + "X_2dim = tsne2.fit_transform(X)\n", + "\n", + "# plot\n", + "N = num_users\n", + "plt.figure(figsize=(8, 5))\n", + "plt.title('TSNE visualisation of user label distributions in CIFAR10 dataset')\n", + "plt.scatter(X_2dim[:N, 0], X_2dim[:N, 1], s=1, color='red', label='true users')\n", + "plt.scatter(X_2dim[N:2*N, 0], X_2dim[N:2*N, 1], s=5, color='green', label='single mixture dirichlet simulation')\n", + "plt.scatter(X_2dim[2*N:3*N, 0], X_2dim[2*N:3*N, 1], s=1, color='blue', label='Simulated users: partitioned uniformly randomly')\n", + "plt.legend(fontsize=10)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "80b5780a-71b5-4e73-8f85-fa7445700f5a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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9u3bI9Z27typhx56SO3bt1e3bt20cOFCd4aMQYcOHdKECRPUs2dPxcfH684779TcuXMVCoUi9pFxy3344Yfq0aOH2rdvryFDhmjLli1ujxSTFixYoAceeEAdOnRQSkqKRo0apX379kXsOXfunAKBgDp16qTbbrtNo0ePVlVVlUsTx76CggL5fD5Nnz7duUbGLXf8+HGNHTtWnTp1Unx8vPr166etW7c662am/Px8paWlKT4+Xjk5Odq/f7+LE7uLYtoMa9as0bhx4/T8889rx44d+vHHH/Xss8866w0NDRo5cqRCoZB++uknrVixQsuXL1d+fr6LU8em1157Tenp6U2uB4NB5ebmqnv37iovL9eiRYs0b948LV261IUpY8/evXsVDodVVFSk3bt367333lNhYaHmzJnj7CHjlvviiy/0yiuvaO7cudq2bZvuv/9+5eXl6dSpU26PFnNKS0sVCAS0efNmbdiwQXV1dcrNzdVff/3l7Hn55Ze1du1arVq1SqWlpTpx4oSeeuopF6eOXb/88ouKiop03333RVwn45Y5c+aMhg0bprZt2+qbb77Rnj179O677yo5OdnZs3DhQr3//vsqLCzUzz//rFtvvVV5eXk6d+6ci5O7yHBFdXV1lpGRYZ988sll96xfv97i4uKssrLSubZkyRJLTEy08+fP34gxbwrr16+3Pn362O7du02S/frrr87aRx99ZMnJyRF5zpw50+6++24XJr05LFy40Hr27Ok8J+OWGzx4sAUCAed5Q0ODpaen24IFC1yc6uZw6tQpk2SlpaVmZlZdXW1t27a1VatWOXt+++03k2RlZWVujRmTamtrrXfv3rZhwwZ75JFHbNq0aWZGxtfDzJkzLTs7+7Lr4XDYUlNTbdGiRc616upq8/v99vnnn9+IET2HO6ZXsW3bNh0/flxxcXEaMGCA0tLSNGLECFVUVDh7ysrK1K9fP3Xp0sW5lpeXp2AwqN27d7sxdsypqqrSxIkT9emnnyohIaHJellZmR5++GG1a9fOuZaXl6d9+/bpzJkzN3LUm0ZNTY1uv/125zkZt0woFFJ5eblycnKca3FxccrJyVFZWZmLk90campqJMl5zZaXl6uuri4i7z59+igzM5O8r1EgENDIkSMjspTI+Hr46quvlJWVpTFjxiglJUUDBgzQxx9/7KwfPHhQlZWVERknJSVpyJAhrTZjiulVHDhwQJI0b948vfHGG1q3bp2Sk5P16KOP6vTp05KkysrKiFIqyXleWVl5YweOQWam8ePHa/LkycrKyrrkHjK+vv744w8tXrxYL7zwgnONjFvmzz//VENDwyUzJL+WCYfDmj59uoYNG6a+fftKuvCabNeunTp27Bixl7yvTXFxsbZt26YFCxY0WSPjljtw4ICWLFmi3r17q6SkRFOmTNFLL72kFStWSLr4tZWvGxe12mI6a9Ys+Xy+Kz4a35cnSa+//rpGjx6tQYMGadmyZfL5fFq1apXLfwtva27GixcvVm1trWbPnu32yDGnuRn/0/Hjx/X4449rzJgxmjhxokuTA80XCARUUVGh4uJit0e5qRw9elTTpk3TypUr1b59e7fHuSmFw2ENHDhQ8+fP14ABAzRp0iRNnDhRhYWFbo/mWW3cHsAtM2bM0Pjx46+4p1evXjp58qQk6d5773Wu+/1+9erVS0eOHJEkpaamNjl523hqMTU19TpOHVuam/HGjRtVVlbW5P8LzsrK0nPPPacVK1YoNTW1yUlQMm5+xo1OnDihxx57TA8++GCTQ01k3DKdO3fWLbfccskMye+/mzp1qtatW6dNmzapa9euzvXU1FSFQiFVV1dH3NEj7+YrLy/XqVOnNHDgQOdaQ0ODNm3apA8++EAlJSVk3EJpaWkR/UGS7rnnHq1Zs0bSxa+tVVVVSktLc/ZUVVWpf//+N2xOT3H7Ta5eV1NTY36/P+LwUygUspSUFCsqKjKzi4efqqqqnD1FRUWWmJho586du+Ezx5rDhw/brl27nEdJSYlJstWrV9vRo0fN7OLBnFAo5Py52bNnczDnGhw7dsx69+5tTz/9tNXX1zdZJ+OWGzx4sE2dOtV53tDQYBkZGRx++g/C4bAFAgFLT0+333//vcl648Gc1atXO9f27t3LwZxrEAwGI7727tq1y7Kysmzs2LG2a9cuMr4OnnnmmSaHn6ZPn25Dhw41s4uHn9555x1nvbF3tNbDTxTTZpg2bZplZGRYSUmJ7d271yZMmGApKSl2+vRpMzOrr6+3vn37Wm5urm3fvt2+/fZbu+OOO2z27NkuTx6bDh482ORUfnV1tXXp0sXGjRtnFRUVVlxcbAkJCc43B7iyY8eO2V133WXDhw+3Y8eO2cmTJ51HIzJuueLiYvP7/bZ8+XLbs2ePTZo0yTp27BjxGzvQPFOmTLGkpCT7/vvvI16vf//9t7Nn8uTJlpmZaRs3brStW7fa0KFDnX/w8d/881S+GRm31JYtW6xNmzb29ttv2/79+23lypWWkJBgn332mbOnoKDAOnbsaF9++aXt3LnTnnjiCevZs6edPXvWxcndQzFthlAoZDNmzLCUlBTr0KGD5eTkWEVFRcSeQ4cO2YgRIyw+Pt46d+5sM2bMsLq6Opcmjm2XKqZmZjt27LDs7Gzz+/2WkZFhBQUF7gwYg5YtW2aSLvn4JzJuucWLF1tmZqa1a9fOBg8ebJs3b3Z7pJh0udfrsmXLnD1nz561F1980ZKTky0hIcGefPLJiG+2cO3+XUzJuOXWrl1rffv2Nb/fb3369LGlS5dGrIfDYXvzzTetS5cu5vf7bfjw4bZv3z6XpnWfz8zshr9/AAAAAPiXVnsqHwAAAN5CMQUAAIAnUEwBAADgCRRTAAAAeALFFAAAAJ5AMQUAAIAnUEwBAADgCRRTAAAAeALFFAAAAJ5AMQUAAIAnUEwBAADgCRRTAAAAeML/AxlHV/E5DyHKAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "N = num_users\n", + "plt.figure(figsize=(8, 5))\n", + "plt.title('TSNE visualisation of user label distributions in CIFAR10 dataset')\n", + "plt.scatter(X_2dim[:N, 0], X_2dim[:N, 1], s=1, color='red', label='true users')\n", + "plt.scatter(X_2dim[N:2*N, 0], X_2dim[N:2*N, 1], s=5, color='green', label='single mixture dirichlet simulation')\n", + "#plt.scatter(X_2dim[2*N:3*N, 0], X_2dim[2*N:3*N, 1], s=1, color='blue', label='Simulated users: partitioned uniformly randomly')\n", + "plt.legend(fontsize=10)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "863cdccf-3222-4139-b4fc-9b60b2925b62", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.10.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/publications/mdm/mdm_paper/training/__init__.py b/publications/mdm/mdm_paper/training/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/publications/mdm/mdm_paper/training/mle.py b/publications/mdm/mdm_paper/training/mle.py new file mode 100644 index 0000000..3376740 --- /dev/null +++ b/publications/mdm/mdm_paper/training/mle.py @@ -0,0 +1,102 @@ +import numpy as np + +from pfl.aggregate.simulate import SimulatedBackend +from pfl.callback import ModelCheckpointingCallback +from pfl.privacy import (CentrallyAppliedPrivacyMechanism, PLDPrivacyAccountant, GaussianMechanism) + +from publications.mdm.mdm_utils.utils.tools import ModelCheckpointingIterationCallback +from publications.mdm.mdm import (MDMModel, MDMModelHyperParams, + MDMAlgorithm, MDMAlgorithmParams, + MDMInitializationAlgorithm, + MDMInitializationAlgorithmParams) + + +def solve_polya_mixture_mle( + arguments, + training_federated_dataset, + val_federated_dataset, + num_components, + num_categories, + save_path, + save_path_histogram, + add_DP=False, + extract_labels_fn=lambda user_dataset: user_dataset.raw_data[1]): + """ + Solve polya-mixture MLE + """ + + # model + model = MDMModel() + model_params = MDMModelHyperParams(num_components, num_categories) + print(f'before init algo - model alphas: {model.alphas}, phi: {model.phi}') + + if add_DP: + num_iterations = arguments.central_num_iterations_init_algorithm + arguments.central_num_iterations_algorithm + + accountant = PLDPrivacyAccountant( + num_compositions=num_iterations, + sampling_probability=0.001, + mechanism='gaussian', + epsilon=2, + delta=1e-7, + noise_scale=1.0) + mechanism = GaussianMechanism.from_privacy_accountant( + accountant=accountant, clipping_bound=0.5) + + postprocessors = [CentrallyAppliedPrivacyMechanism(mechanism)] + else: + postprocessors = [] + backend = SimulatedBackend(training_data=training_federated_dataset, + val_data=val_federated_dataset, + postprocessors=postprocessors) + + bin_edges = np.linspace( + 0, arguments.max_num_samples_mixture_component_init_algorithm, 11)[1:] + num_samples_mixture_bins = np.vstack([bin_edges] * 6) + print('\nnum_samples_mixture_bins', num_samples_mixture_bins) + + # init algorithm + init_algorithm = MDMInitializationAlgorithm() + init_algorithm_params = MDMInitializationAlgorithmParams( + cohort_size=arguments.cohort_size_init_algorithm, + num_samples_mixture_bins=num_samples_mixture_bins, + strategy=arguments.strategy, + central_num_iterations=arguments.central_num_iterations_init_algorithm, + extract_categories_fn=extract_labels_fn) + init_algorithm.run( + algorithm_params=init_algorithm_params, + backend=backend, + model=model, + model_train_params=model_params, + model_eval_params=None, + callbacks=[ModelCheckpointingCallback(model_checkpoint_dir=save_path)]) + print(f'after init algo - model alphas: {model.alphas}, phi: {model.phi}') + + # TODO do I need to reset phi and alpha in model? + # Require model phi = (1 / num_mixture_components) * + # np.ones(num_mixture_components) + + # algorithm + algorithm = MDMAlgorithm() + algorithm_params = MDMAlgorithmParams( + cohort_size=arguments.cohort_size_algorithm, + num_samples_mixture_bins=num_samples_mixture_bins, + central_num_iterations=arguments.central_num_iterations_algorithm, + extract_categories_fn=extract_labels_fn) + algorithm.run( + algorithm_params=algorithm_params, + backend=backend, + model=model, + model_train_params=model_params, + model_eval_params=None, + callbacks=[ + ModelCheckpointingCallback(model_checkpoint_dir=save_path), + ModelCheckpointingIterationCallback( + model_checkpoint_dir=save_path + '_iteration_models', + checkpoint_frequency=1) + ]) + print( + f'after algo - model alphas: {model.alphas}, phi: {model.phi}, num_samples_distribution: {model.num_samples_distribution}' + ) + + return model.phi, model.alphas, model.num_samples_distribution diff --git a/publications/mdm/mdm_paper/training/train.py b/publications/mdm/mdm_paper/training/train.py new file mode 100644 index 0000000..9431ccd --- /dev/null +++ b/publications/mdm/mdm_paper/training/train.py @@ -0,0 +1,149 @@ +import os +import argparse +import datetime + +import numpy as np +import torch +import joblib + +from pfl.internal.ops import pytorch_ops +from pfl.internal.ops.selector import get_default_framework_module as get_ops +from pfl.internal.ops.selector import set_framework_module +from pfl.internal.platform.selector import get_platform + +from publications.mdm.mdm_utils.datasets import make_cifar10_datasets +from publications.mdm.mdm_utils.utils import (add_dataset_args, add_experiment_args, + add_mle_args, add_init_algorithm_args, + add_algorithm_args, + add_histogram_algorithm_args, + add_user_visualisation_args) + +from publications.mdm.mdm_paper.training.mle import solve_polya_mixture_mle + + +def get_arguments(): + parser = argparse.ArgumentParser() + add_experiment_args(parser) + add_dataset_args(parser) + add_mle_args(parser) + add_init_algorithm_args(parser) + add_algorithm_args(parser) + add_histogram_algorithm_args(parser) + add_user_visualisation_args(parser) + return parser.parse_args() + + +set_framework_module(pytorch_ops) +arguments = get_arguments() +np.random.seed(arguments.seed) +torch.random.manual_seed(arguments.seed) + +# Solve MLE using only CPU +os.environ['RAMSAY_PYTORCH_DEVICE'] = 'cpu' + +# Create data of live users +num_classes = 10 +input_shape = (32, 32, 3) + +# check arguments for mixture components +print('arguments.num_mixture_components', arguments.num_mixture_components, + type(arguments.num_mixture_components)) +print('arguments.component_mean_user_dataset_length', + arguments.component_mean_user_dataset_length) +print('arguments.component_phi', arguments.component_phi, + type(arguments.component_phi)) + +assert arguments.num_mixture_components == len( + arguments.component_mean_user_dataset_length) == len( + arguments.component_phi) +if len(arguments.component_alphas) == arguments.num_mixture_components: + # one alpha for all classes for each mixture component + alphas = np.array(arguments.component_alphas).reshape( + -1, 1) * np.ones(num_classes) + print('alphas', alphas) +else: + # must have length num mixture components * num_classes + print('len(arguments.component_alphas)', len(arguments.component_alphas)) + print('arguments.num_mixture_components * num_classes', + arguments.num_mixture_components * num_classes) + assert len(arguments.component_alphas + ) == arguments.num_mixture_components * num_classes + # assumes alphas are ordered each class, each mixture component + print('arguments.component_alphas', arguments.component_alphas) + alphas = np.array(arguments.component_alphas).reshape( + arguments.num_mixture_components, num_classes) + print('alphas', alphas.shape, alphas) + +print('arguments.component_phi', arguments.component_phi) +phi = np.array(arguments.component_phi) +# default values for samplers are tuple +# arguments.component_mean_user_dataset_length (50, 30) +# but these default values can be overwritten at run time of lambda fn. +samplers = [ + lambda x=x: x for x in arguments.component_mean_user_dataset_length +] +print('samplers', [s() for s in samplers]) +print('true phi', phi) +print('true alphas', alphas) + +# option to create artificial_federated_dataset or federated_dataset +live_training_data, live_val_data, central_val_data = make_cifar10_datasets( + dataset_type='artificial_federated_dataset', + data_dir=arguments.data_dir, + user_dataset_len_samplers=samplers, + numpy_to_tensor=get_ops().to_tensor, + phi=phi, + alphas=alphas) + +# TODO support modelling federated dataset using mixture-polya +# or uniform distribution + +# If running simulations then compute phi, alphas and num_samples_histos +# either by solving the polya MLE or just computing the histogram for +# uniform simulations +print('simulated_dirichlet_mixture experiment') +if arguments.precomputed_parameter_filepath is None: + print('learn simulated_dirichlet_mixture parameters') + dir_path = get_platform().create_checkpoint_directories([arguments.mle_param_dirname])[0] + current_time = datetime.datetime.now() + timestamp = current_time.strftime("%Y-%m-%d_%H-%M") + save_dir = ( + #f'cifar10_{arguments.num_mixture_components}_mixture_{timestamp}') + f'cifar10_{arguments.num_mixture_components}_mixture_{arguments.dirname}' + ) + save_path = os.path.join(dir_path, save_dir) + + dir_path_histogram = get_platform().create_checkpoint_directories( + ['num_samples_distribution'])[0] + save_path_histogram = os.path.join(dir_path_histogram, + save_dir + '.joblib') + + # Solve polya-mixture MLE + # TODO use mle arguments for cohort size, num iterations, etc. + # TODO what to do about num_samples_histos? + phi, alphas, num_samples_distributions = solve_polya_mixture_mle( + arguments=arguments, + training_federated_dataset=live_training_data, + val_federated_dataset=None, + num_components=arguments.num_mixture_components, + num_categories=num_classes, + save_path=save_path, + save_path_histogram=save_path_histogram) + + phi = phi.numpy() if isinstance(phi, torch.Tensor) else phi + alphas = alphas.numpy() if isinstance(alphas, torch.Tensor) else alphas + num_samples_distributions = num_samples_distributions.numpy() + print('phi', phi) + print('alphas', alphas) + print('num_samples_distributions', num_samples_distributions) + +else: + params = joblib.load(arguments.precomputed_parameter_filepath) + + phi = np.array(params['phi']) + phi /= phi.sum() + alphas = np.array(params['alphas']) + num_samples_distributions = np.array(params['num_samples_distributions']) + num_samples_distributions /= np.sum(num_samples_distributions, + axis=1, + keepdims=True) diff --git a/publications/mdm/mdm_paper/training/train_femnist.py b/publications/mdm/mdm_paper/training/train_femnist.py new file mode 100644 index 0000000..dd6c90e --- /dev/null +++ b/publications/mdm/mdm_paper/training/train_femnist.py @@ -0,0 +1,101 @@ +import os +import argparse + +import joblib +import numpy as np +import torch + +from pfl.internal.ops import pytorch_ops +from pfl.internal.ops.selector import get_default_framework_module as get_ops +from pfl.internal.ops.selector import set_framework_module +from pfl.internal.platform.selector import get_platform + +from publications.mdm.mdm_utils.datasets import make_femnist_datasets +from publications.mdm.mdm_utils.utils import (add_experiment_args, add_mle_args, + add_init_algorithm_args, add_algorithm_args, + add_histogram_algorithm_args, + add_user_visualisation_args) + +from publications.mdm.mdm_paper.training.mle import solve_polya_mixture_mle + + +def get_arguments(): + parser = argparse.ArgumentParser() + add_experiment_args(parser) + add_mle_args(parser) + add_init_algorithm_args(parser) + add_algorithm_args(parser) + add_histogram_algorithm_args(parser) + add_user_visualisation_args(parser) + return parser.parse_args() + + +set_framework_module(pytorch_ops) +arguments = get_arguments() +np.random.seed(arguments.seed) +torch.random.manual_seed(arguments.seed) + +# Solve MLE using only CPU +os.environ['RAMSAY_PYTORCH_DEVICE'] = 'cpu' + +# Create data of live users +num_classes = 62 +input_shape = (28, 28, 1) + +live_training_data, live_val_data, central_val_data = make_femnist_datasets( + arguments.data_dir, + digits_only=False, + numpy_to_tensor=get_ops().to_tensor, + dataset_type=arguments.dataset_type) + +add_DP = True + +# If running simulations then compute phi, alphas and num_samples_histos +# either by solving the polya MLE or just computing the histogram for +# uniform simulations +print('simulated_dirichlet_mixture experiment') +if arguments.precomputed_parameter_filepath is None: + print('learn simulated_dirichlet_mixture parameters') + dir_path = get_platform().create_checkpoint_directories([arguments.mle_param_dirname])[0] + save_dir = ( + f'femnist_{arguments.dataset_type}_{arguments.num_mixture_components}_mixture' + ) + if add_DP: + save_dir += '_DP' + save_path = os.path.join(dir_path, save_dir) + + dir_path_histogram = get_platform().create_checkpoint_directories( + ['num_samples_distribution'])[0] + save_path_histogram = os.path.join(dir_path_histogram, + save_dir + '.joblib') + + # Solve polya-mixture MLE + # TODO use mle arguments for cohort size, num iterations, etc. + # TODO what to do about num_samples_histos? + phi, alphas, num_samples_distributions = solve_polya_mixture_mle( + arguments=arguments, + training_federated_dataset=live_training_data, + val_federated_dataset=None, + num_components=arguments.num_mixture_components, + num_categories=num_classes, + save_path=save_path, + save_path_histogram=save_path_histogram, + add_DP=add_DP) + + phi = phi.numpy() if isinstance(phi, torch.Tensor) else phi + alphas = alphas.numpy() if isinstance(alphas, torch.Tensor) else alphas + num_samples_distributions = num_samples_distributions.numpy() + print('phi', phi) + print('alphas', alphas) + print('num_samples_distributions', num_samples_distributions) + +else: + params = joblib.load(arguments.precomputed_parameter_filepath) + + phi = np.array(params['phi']) + phi /= phi.sum() + alphas = np.array(params['alphas']) + num_samples_distributions = np.array(params['num_samples_distributions']) + num_samples_distributions /= np.sum(num_samples_distributions, + axis=1, + keepdims=True) diff --git a/publications/mdm/mdm_paper/training/train_femnist_rebuttal.py b/publications/mdm/mdm_paper/training/train_femnist_rebuttal.py new file mode 100644 index 0000000..096c7ec --- /dev/null +++ b/publications/mdm/mdm_paper/training/train_femnist_rebuttal.py @@ -0,0 +1,117 @@ +import os +import argparse + +import joblib +import numpy as np +import torch + +from pfl.internal.ops import pytorch_ops +from pfl.internal.ops.selector import get_default_framework_module as get_ops +from pfl.internal.ops.selector import set_framework_module +from pfl.internal.platform.selector import get_platform + +from publications.mdm.mdm_utils.datasets import make_femnist_datasets +from publications.mdm.mdm_utils.utils import (add_experiment_args, add_mle_args, + add_init_algorithm_args, add_algorithm_args, + add_histogram_algorithm_args, + add_user_visualisation_args, + add_dataset_preprocessing_args) + +from publications.mdm.mdm_paper.training.mle import solve_polya_mixture_mle + + +def get_arguments(): + parser = argparse.ArgumentParser() + add_experiment_args(parser) + add_mle_args(parser) + add_init_algorithm_args(parser) + add_algorithm_args(parser) + add_histogram_algorithm_args(parser) + add_user_visualisation_args(parser) + add_dataset_preprocessing_args(parser) + return parser.parse_args() + + +set_framework_module(pytorch_ops) +arguments = get_arguments() +np.random.seed(arguments.seed) +torch.random.manual_seed(arguments.seed) + +# Solve MLE using only CPU +os.environ['RAMSAY_PYTORCH_DEVICE'] = 'cpu' + +# Create data of live users +num_classes = 62 +input_shape = (28, 28, 1) + +live_training_data, live_val_data, central_val_data = make_femnist_datasets( + arguments.data_dir, + digits_only=False, + numpy_to_tensor=get_ops().to_tensor, + dataset_type=arguments.dataset_type, + filter_method=arguments.filter_method, + sample_fraction=arguments.sample_fraction, + start_idx=arguments.start_idx, + end_idx=arguments.end_idx, + include_sampled=arguments.include_sampled) + +add_DP = False + +# If running simulations then compute phi, alphas and num_samples_histos +# either by solving the polya MLE or just computing the histogram for +# uniform simulations +print('simulated_dirichlet_mixture experiment') +if arguments.precomputed_parameter_filepath is None: + print('learn simulated_dirichlet_mixture parameters') + dir_path = get_platform().create_checkpoint_directories([arguments.mle_param_dirname])[0] + save_dir = ( + f'femnist_{arguments.dataset_type}_{arguments.num_mixture_components}_mixture_{arguments.filter_method}_filter_method' + ) + if arguments.filter_method is not None: + if arguments.filter_method == 'index': + save_dir += f'_{arguments.start_idx}_start_idx_{arguments.end_idx}_end_idx' + elif arguments.filter_method == 'sample': + save_dir += f'_{arguments.sample_fraction}_sample_fraction_{arguments.include_sampled}_include_sampled' + else: + raise ValueError( + f'Invalid value for filter_method: {arguments.filter_method}') + + if add_DP: + save_dir += '_DP' + save_path = os.path.join(dir_path, save_dir) + + dir_path_histogram = get_platform().create_checkpoint_directories( + ['num_samples_distribution'])[0] + save_path_histogram = os.path.join(dir_path_histogram, + save_dir + '.joblib') + + # Solve polya-mixture MLE + # TODO use mle arguments for cohort size, num iterations, etc. + # TODO what to do about num_samples_histos? + phi, alphas, num_samples_distributions = solve_polya_mixture_mle( + arguments=arguments, + training_federated_dataset=live_training_data, + val_federated_dataset=None, + num_components=arguments.num_mixture_components, + num_categories=num_classes, + save_path=save_path, + save_path_histogram=save_path_histogram, + add_DP=add_DP) + + phi = phi.numpy() if isinstance(phi, torch.Tensor) else phi + alphas = alphas.numpy() if isinstance(alphas, torch.Tensor) else alphas + num_samples_distributions = num_samples_distributions.numpy() + print('phi', phi) + print('alphas', alphas) + print('num_samples_distributions', num_samples_distributions) + +else: + params = joblib.load(arguments.precomputed_parameter_filepath) + + phi = np.array(params['phi']) + phi /= phi.sum() + alphas = np.array(params['alphas']) + num_samples_distributions = np.array(params['num_samples_distributions']) + num_samples_distributions /= np.sum(num_samples_distributions, + axis=1, + keepdims=True) diff --git a/publications/mdm/mdm_utils/__init__.py b/publications/mdm/mdm_utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/publications/mdm/mdm_utils/datasets/__init__.py b/publications/mdm/mdm_utils/datasets/__init__.py new file mode 100644 index 0000000..e189449 --- /dev/null +++ b/publications/mdm/mdm_utils/datasets/__init__.py @@ -0,0 +1,3 @@ +from .mixture_dataset import get_user_counts +from .cifar10_dataset import make_cifar10_datasets +from .femnist_dataset import make_femnist_datasets diff --git a/publications/mdm/mdm_utils/datasets/cifar10_dataset.py b/publications/mdm/mdm_utils/datasets/cifar10_dataset.py new file mode 100644 index 0000000..3d06410 --- /dev/null +++ b/publications/mdm/mdm_utils/datasets/cifar10_dataset.py @@ -0,0 +1,158 @@ +# -*- coding: utf-8 -*- + +import os +import pickle +from typing import Callable, List, Optional, Tuple + +import numpy as np + +from pfl.data import (ArtificialFederatedDataset, FederatedDataset, + FederatedDatasetBase) +from pfl.data.sampling import get_user_sampler, get_data_sampler +from pfl.data.dataset import Dataset + +from .mixture_dataset import (ArtificialFederatedDatasetMixture, + partition_by_dirichlet_mixture_class_distribution + ) +from .sampler import DirichletDataSampler + + +def load_and_preprocess(pickle_file_path: str, + channel_means: Optional[np.ndarray] = None, + channel_stddevs: Optional[np.ndarray] = None, + exclude_classes=None): + images, labels = pickle.load(open(pickle_file_path, 'rb')) + images = images.astype(np.float32) + + # Normalize per-channel. + if channel_means is None: + channel_means = images.mean(axis=(0, 1, 2), dtype='float64') + if channel_stddevs is None: + channel_stddevs = images.std(axis=(0, 1, 2), dtype='float64') + images = (images - channel_means) / channel_stddevs + + if exclude_classes is not None: + for exclude_class in exclude_classes: + mask = (labels != exclude_class).reshape(-1) + labels = labels[mask] + images = images[mask] + + return images, labels, channel_means, channel_stddevs + + +def make_artificial_federated_dataset( + images: np.ndarray, + labels: np.ndarray, + user_dataset_len_samplers: List[Callable], + phi: np.ndarray = None, + alphas: np.ndarray = None, + numpy_to_tensor: Callable = lambda x: x) -> FederatedDatasetBase: + """ + Create an artificial federated dataset from the CIFAR10 dataset + """ + data = [numpy_to_tensor(images), numpy_to_tensor(labels)] + if alphas is not None: + data_samplers = [ + DirichletDataSampler(alpha, labels) for alpha in alphas + ] + return ArtificialFederatedDatasetMixture.from_slices( + phi, data, data_samplers, user_dataset_len_samplers) + else: + data_sampler = get_data_sampler('random', len(labels)) + return ArtificialFederatedDataset.from_slices( + data, data_sampler, user_dataset_len_samplers[0]) + + +def make_federated_dataset( + images: np.ndarray, + labels: np.ndarray, + user_dataset_len_samplers: List[Callable], + phi: np.ndarray = None, + alphas: np.ndarray = None, + numpy_to_tensor: Callable = lambda x: x) -> FederatedDataset: + """ + Create a federated dataset from the CIFAR10 dataset. + """ + + if alphas is not None: + user_idxs = partition_by_dirichlet_mixture_class_distribution( + labels, phi, alphas, user_dataset_len_samplers) + else: + all_idxs = np.arange(len(labels)).astype(int) + np.random.shuffle(all_idxs) + user_idxs = [] + while True: + n = user_dataset_len_samplers[0]() + if len(all_idxs) >= n: + user_idxs.append(all_idxs[:n]) + all_idxs = all_idxs[n:] + else: + user_idxs.append(all_idxs) + break + + user_sampler = get_user_sampler('random', list(range(len(user_idxs)))) + images = numpy_to_tensor(images) + labels = numpy_to_tensor(labels) + + data = dict() + for user_id in range(len(user_idxs)): + data[user_id] = [ + images[user_idxs[user_id]], labels[user_idxs[user_id]] + ] + + return FederatedDataset.from_slices(data, user_sampler) + + +def make_central_dataset(images: np.ndarray, labels: np.ndarray) -> Dataset: + """ + Create central dataset (represented as a ``Dataset``) from CIFAR10. + This ``Dataset`` can be used for central evaluation with + ``CentralEvaluationCallback``. + """ + return Dataset(raw_data=[images, labels]) + + +def make_cifar10_datasets( + dataset_type: str, + data_dir: str, + user_dataset_len_samplers: List[Callable], + numpy_to_tensor: Callable, + phi: np.ndarray = None, + alphas: np.ndarray = None +) -> Tuple[FederatedDataset, FederatedDataset, Dataset]: + """ + Create a train and val ``ArtificialFederatedDataset`` as well as a + central dataset from the CIFAR10 dataset. + + The data files can be found at ``s3://pfl/data/cifar10/``. + """ + train_images, train_labels, channel_means, channel_stddevs = ( + load_and_preprocess(os.path.join(data_dir, 'cifar10_train.p'))) + + val_images, val_labels, _, _ = load_and_preprocess( + os.path.join(data_dir, 'cifar10_test.p'), channel_means, + channel_stddevs) + + # supports artificial federated dataset and federated dataset + fed_dataset_fn = make_artificial_federated_dataset \ + if dataset_type == 'artificial_federated_dataset' \ + else make_federated_dataset + + # create federated training and val datasets + # from central training and val data. + training_federated_dataset = fed_dataset_fn( + train_images, + train_labels, + user_dataset_len_samplers, + phi=phi, + alphas=alphas, + numpy_to_tensor=numpy_to_tensor) + val_federated_dataset = fed_dataset_fn(val_images, + val_labels, + user_dataset_len_samplers, + phi=phi, + alphas=alphas, + numpy_to_tensor=numpy_to_tensor) + central_val_data = make_central_dataset(val_images, val_labels) + + return training_federated_dataset, val_federated_dataset, central_val_data diff --git a/publications/mdm/mdm_utils/datasets/femnist_dataset.py b/publications/mdm/mdm_utils/datasets/femnist_dataset.py new file mode 100644 index 0000000..c921e4f --- /dev/null +++ b/publications/mdm/mdm_utils/datasets/femnist_dataset.py @@ -0,0 +1,324 @@ +# -*- coding: utf-8 -*- + +import os +from typing import Callable, Dict, Tuple, List, Optional + +import h5py +import numpy as np +import torch + +from pfl.data import ArtificialFederatedDataset, FederatedDataset +from pfl.data.sampling import get_user_sampler, get_data_sampler +from pfl.data.dataset import Dataset + +from .mixture_dataset import (ArtificialFederatedDatasetMixture, + partition_by_dirichlet_mixture_class_distribution + ) +from .sampler import DirichletDataSampler + + +def _sample_users(user_id_to_data: Dict[str, List[np.ndarray]], + filter_method: Optional[str] = None, + sample_fraction: float = None, + start_idx: int = None, + end_idx: int = None, + include_sampled: bool = True): + + user_ids = list(user_id_to_data.keys()) + + if filter_method is None: + print('\nKEEP ALL USERS') + # no change. Use all users + return user_id_to_data + + elif filter_method == 'index': + assert start_idx is not None + assert end_idx is not None + print(f'\nKEEP ALL USERS WITH IDS IN RANGE {start_idx}-{end_idx}') + + selected_user_ids = user_ids[start_idx:end_idx] + + elif filter_method == 'sample': + assert sample_fraction >= 0 and sample_fraction <= 1 + + sample_number = int(sample_fraction * len(user_ids)) + + original_state = np.random.get_state() + np.random.seed(0) + sampled_ids = np.random.choice(len(user_ids), + sample_number, + replace=False) + np.random.set_state(original_state) + + if not include_sampled: + sampled_ids = np.setdiff1d(np.arange(len(user_ids)), sampled_ids) + print( + f'\nKEEP {len(sampled_ids)} SAMPLED USERS WITH IDS: {sampled_ids}') + selected_user_ids = [user_ids[i] for i in sampled_ids] + + else: + raise ValueError(f'filter_method {filter_method} is not valid') + + return {user_id: user_id_to_data[user_id] for user_id in selected_user_ids} + + +def _load_h5_into_dict( + h5_file_path: str, + digits_only: bool, + numpy_to_tensor: Callable = lambda x: x +) -> Dict[str, List[np.ndarray]]: + """ + Load data into memory and create a mapping from user ids to that + user's data. + + :returns: + A dictionary mapping user ids to data. The data is a tuple + `(pixels,labels)`, where `pixels` is a `BxWxHx1` `np.ndarray` + (stacked images of a user) and `labels` is a `Bx1` vector of + categorical labels. + """ + user_id_to_data = {} + with h5py.File(h5_file_path, "r") as f: + for user, h5_group in f['examples'].items(): + images = np.expand_dims(h5_group['pixels'][()], axis=-1) + labels = h5_group['label'][()] + if digits_only: + images = images[labels < 10] + labels = labels[labels < 10] + user_id_to_data[user] = [ + numpy_to_tensor(images), + numpy_to_tensor(labels) + ] + + return user_id_to_data + + +def make_federated_dataset(user_id_to_data: Dict[str, List[np.ndarray]], + use_existing_partition: bool = True, + phi=None, + alphas=None, + user_dataset_len_samplers=None) -> FederatedDataset: + """ + Create federated dataset from a FEMNIST data file. + """ + + user_ids = list(user_id_to_data.keys()) + + if not use_existing_partition: + images = torch.cat([data[0] for data in user_id_to_data.values()]) + labels = torch.cat([data[1] for data in user_id_to_data.values()]) + + if alphas is not None: + user_idxs = partition_by_dirichlet_mixture_class_distribution( + labels.cpu().numpy(), phi, alphas, user_dataset_len_samplers) + else: + all_idxs = np.arange(len(labels)).astype(int) + np.random.shuffle(all_idxs) + user_idxs = [] + while True: + n = user_dataset_len_samplers[0]() + if len(all_idxs) >= n: + user_idxs.append(all_idxs[:n]) + all_idxs = all_idxs[n:] + else: + user_idxs.append(all_idxs) + break + + user_ids = [str(i) for i in range(len(user_idxs))] + user_id_to_data = dict( + zip(user_ids, [(images[idx], labels[idx]) for idx in user_idxs])) + + sampler = get_user_sampler('random', user_ids) + federated_dataset = FederatedDataset.from_slices(user_id_to_data, sampler) + + return federated_dataset + + +def make_special_federated_dataset( + user_id_to_data: Dict[str, List[np.ndarray]]) -> FederatedDataset: + """ + Create federated dataset from a FEMNIST data file. + Keep same label distribution per user, but mix up the datapoints. + """ + + user_ids = list(user_id_to_data.keys()) + images = torch.cat([data[0] for data in user_id_to_data.values()]) + + labels = torch.cat([data[1] + for data in user_id_to_data.values()]).cpu().numpy() + unique_labels = np.unique(labels) + indices_per_class = { + i: np.random.permutation(np.nonzero(labels == i)[0]) + for i in unique_labels + } + #from collections import Counter + #print('labels count',Counter(labels)) + #for k,v in indices_per_class.items(): + # print('indices_per_class', k, len(v)) + + new_user_id_to_data = dict() + start_id_per_class = {i: 0 for i in unique_labels} + #print('start_id_per_class', start_id_per_class) + for user_id, data in user_id_to_data.items(): + #print('user_id', user_id) + user_labels = data[1].cpu().numpy() + #print('labels', labels) + + # sample images based off labels. + sampled_data_idx = [] + for label in user_labels: + #print('label', label) + #print('start_id_per_class[label]', start_id_per_class[label]) + #print(' indices_per_class[label]', type(indices_per_class[label]), len(indices_per_class[label])) + sampled_data_idx.append( + indices_per_class[label][start_id_per_class[label]]) + start_id_per_class[label] += 1 + + # TODO might need to ensure labels in not on cpu any more. + new_user_id_to_data[user_id] = [images[sampled_data_idx], data[1]] + + #new_labels = torch.cat([data[1] for data in new_user_id_to_data.values()]).cpu().numpy() + #print('new label counts', Counter(new_labels)) + + sampler = get_user_sampler('random', user_ids) + federated_dataset = FederatedDataset.from_slices(new_user_id_to_data, + sampler) + + return federated_dataset + + +def make_artificial_federated_dataset( + user_id_to_data: Dict[str, List[np.ndarray]], + user_dataset_len_samplers: List[Callable], + phi: np.ndarray = None, + alphas: np.ndarray = None) -> Tuple[ArtificialFederatedDataset, dict]: + """ + Create artificial federated dataset from a FEMNIST data file. + """ + images = torch.cat([data[0] for data in user_id_to_data.values()]) + labels = torch.cat([data[1] for data in user_id_to_data.values()]) + + data = [images, labels] + + if alphas is not None: + data_samplers = [ + DirichletDataSampler(alpha, + labels.cpu().numpy()) for alpha in alphas + ] + return ArtificialFederatedDatasetMixture.from_slices( + phi, data, data_samplers, user_dataset_len_samplers) + else: + data_sampler = get_data_sampler('random', len(labels)) + return ArtificialFederatedDataset.from_slices( + data, data_sampler, user_dataset_len_samplers[0]) + + +def make_central_dataset( + user_id_to_data: Dict[str, List[np.ndarray]]) -> Dataset: + """ + Create central dataset from a FEMNIST data file. + """ + images = np.concatenate([data[0].cpu() for data in user_id_to_data.values()], + axis=0) + labels = np.concatenate([data[1].cpu() for data in user_id_to_data.values()], + axis=0) + + return Dataset(raw_data=[images, labels]) + + +def make_femnist_datasets( + data_dir: str, + digits_only: bool = False, + numpy_to_tensor: Callable = lambda x: x, + dataset_type: str = 'original', + phi=None, + alphas=None, + user_dataset_len_samplers=None, + filter_method: Optional[str] = None, + sample_fraction: float = None, + start_idx: int = None, + end_idx: int = None, + include_sampled: bool = True +) -> Tuple[FederatedDataset, FederatedDataset, Dataset]: + """ + Create a train and val ``FederatedDataset`` as well as a central dataset + from the FEMNIST data. + """ + + train_h5_file_path = os.path.join(data_dir, 'fed_emnist_train.h5') + val_h5_file_path = os.path.join(data_dir, 'fed_emnist_test.h5') + + train_user_id_to_data = _load_h5_into_dict(train_h5_file_path, digits_only, + numpy_to_tensor) + train_user_id_to_data = _sample_users(train_user_id_to_data, filter_method, + sample_fraction, start_idx, end_idx, + include_sampled) + + val_user_id_to_data = _load_h5_into_dict(val_h5_file_path, digits_only, + numpy_to_tensor) + val_user_id_to_data = _sample_users(val_user_id_to_data, filter_method, + sample_fraction, start_idx, end_idx, + include_sampled) + + # create federated training and val datasets from central training and val + # data + if dataset_type == 'original': + training_federated_dataset = make_federated_dataset( + train_user_id_to_data) + val_federated_dataset = make_federated_dataset(val_user_id_to_data) + + elif dataset_type == 'original_labels_uniform_datapoints': + training_federated_dataset = make_special_federated_dataset( + train_user_id_to_data) + val_federated_dataset = make_special_federated_dataset( + val_user_id_to_data) + + elif dataset_type == 'polya_mixture_federated': + training_federated_dataset = make_federated_dataset( + user_id_to_data=train_user_id_to_data, + use_existing_partition=False, + phi=phi, + alphas=alphas, + user_dataset_len_samplers=user_dataset_len_samplers) + val_federated_dataset = make_federated_dataset( + user_id_to_data=val_user_id_to_data, + use_existing_partition=False, + phi=phi, + alphas=alphas, + user_dataset_len_samplers=user_dataset_len_samplers) + + elif dataset_type == 'polya_mixture_artificial_federated': + training_federated_dataset = make_artificial_federated_dataset( + train_user_id_to_data, + user_dataset_len_samplers, + phi=phi, + alphas=alphas) + val_federated_dataset = make_artificial_federated_dataset( + val_user_id_to_data, + user_dataset_len_samplers, + phi=phi, + alphas=alphas) + + elif dataset_type == 'uniform_federated': + training_federated_dataset = make_federated_dataset( + train_user_id_to_data, + use_existing_partition=False, + user_dataset_len_samplers=user_dataset_len_samplers) + val_federated_dataset = make_federated_dataset( + val_user_id_to_data, + use_existing_partition=False, + user_dataset_len_samplers=user_dataset_len_samplers) + + elif dataset_type == 'uniform_artificial_federated': + training_federated_dataset = make_artificial_federated_dataset( + train_user_id_to_data, user_dataset_len_samplers) + val_federated_dataset = make_artificial_federated_dataset( + val_user_id_to_data, user_dataset_len_samplers) + + else: + raise NotImplementedError( + f'Dataset type {dataset_type} not recognized.') + + central_data = make_central_dataset(val_user_id_to_data) + + return training_federated_dataset, val_federated_dataset, central_data diff --git a/publications/mdm/mdm_utils/datasets/mixture_dataset.py b/publications/mdm/mdm_utils/datasets/mixture_dataset.py new file mode 100644 index 0000000..495d4b1 --- /dev/null +++ b/publications/mdm/mdm_utils/datasets/mixture_dataset.py @@ -0,0 +1,154 @@ +from collections import defaultdict +from typing import Callable, Iterable, List, Tuple + +import numpy as np +import joblib + +from pfl.data import ArtificialFederatedDataset, FederatedDatasetBase +from pfl.data.dataset import AbstractDataset +from pfl.internal.ops.selector import (get_default_framework_module as get_ops) + + +class ArtificialFederatedDatasetMixture(FederatedDatasetBase): + """ + A type of federated dataset that is a mixture of multiple + ArtificialFederatedDataset. To sample a new users we randomly + sample a component with corresponding probability vector phi, + we then sample a user from the corresponding + ArtificialFederatedDataset. + :param phi: + A np.ndarray of shape len(mixture_component_datasets), + probability vector that gives the probability of + each mixture component + :param mixture_component_datasets: + List of type ArtificialFederatedDataset + """ + + def __init__(self, phi, mixture_component_datasets): + super().__init__() + self.phi = phi + self.mixture_component_datasets = mixture_component_datasets + + def __next__(self): + mixture_component = np.random.choice(range(len(self.phi)), p=self.phi) + return next(self.mixture_component_datasets[mixture_component]) + + def get_cohort(self, + cohort_size: int) -> Iterable[Tuple[AbstractDataset, int]]: + for i in range(cohort_size): + if (i % get_ops().distributed.world_size + ) == get_ops().distributed.global_rank: + yield next(self) + + @classmethod + def from_slices(cls, phi, data, data_samplers, dataset_len_samplers): + """ + Construct a mixture of simulated federated datasets from a single + regular dataset where there is no such thing as a user identifier. + Each mixture samples a user from the same data but using its + own data_sampler and dataset_len_sampler. + :param phi: + A np.ndarray probability vector + :param data: + A list of ``np.ndarray``, i.e. the same format as a ``Dataset`` + accepts. + :param data_samplers: + List of callables of length len(phi), each callable is a data + sampler for an ArtificialFederatedDataset + :param dataset_len_samplers: + List of callables of length len(phi), each callable is a data + length sampler for an ArtificialFederatedDataset + :returns: + An instance of `ArtificialFederatedDatasetMixture`. + """ + mixture_component_datasets = [] + for data_sampler, dataset_len_sampler in zip(data_samplers, + dataset_len_samplers): + mixture_component_datasets.append( + ArtificialFederatedDataset.from_slices(data, data_sampler, + dataset_len_sampler)) + return cls(phi, mixture_component_datasets) + + +def partition_by_dirichlet_mixture_class_distribution( + labels: np.ndarray, + phi: np.ndarray, + alphas: np.ndarray, + user_dataset_len_samplers: List[Callable], + spread_distribution_after_num_fails: int = 20, + spread_distribution_after_fails_percentage: float = 0.02 +) -> List[List[int]]: + """ + Partitions central data using a mixture of dirichlet distributions. Works + the same as partition_by_dirichlet_class_distribution except that it first + randomly samples a mixture component using probability vector phi, and then + selects the corresponding alpha and user_dataset_len_sampler. + """ + num_components = len(phi) + num_classes = len(np.unique(labels)) + indices_per_class = [ + list(np.where(labels == i)[0]) for i in range(num_classes) + ] + users_to_indices = defaultdict(list) + + user_id = 0 + while True: + component = np.random.choice(num_components, p=phi) + alpha = alphas[component] + user_dataset_len_sampler = user_dataset_len_samplers[component] + class_priors = np.random.dirichlet(alpha=alpha) + class_prior_cdf = np.cumsum(class_priors) + user_num_datapoints = user_dataset_len_sampler() + if user_num_datapoints > sum( + [len(cidxs) for cidxs in indices_per_class]): + # Not enough datapoints left. + break + + i = 1 + while True: + if len(users_to_indices[user_id]) >= user_num_datapoints: + user_id += 1 + break + # Sample class from user's class distribution (Dirichlet) + sampled_class = np.argmax(np.random.uniform() <= class_prior_cdf) + if len(indices_per_class[sampled_class]): + # Add datapoint to user if there are still datapoints + # available of that class. + users_to_indices[user_id].append( + indices_per_class[sampled_class].pop()) + if i % (user_num_datapoints * + spread_distribution_after_num_fails) == 0: + # Every this number of failed samples, + # even out the class distribution a tiny bit (at least 2% + # chance for every class) such that + # sampling classes with datapoints remaining to be allocated + # are more probable. This will typically only be an issue for + # the final few 1-5 users. + class_priors += spread_distribution_after_fails_percentage + class_priors /= sum(class_priors) + class_prior_cdf = np.cumsum(class_priors) + i += 1 + return list(users_to_indices.values()) + + +def get_user_counts(training_federated_dataset, num_classes, + num_central_iterations, cohort_size, save_path): + """ + Helper function to check the label counts of a cohort of users. + Can be used to visualize the users generated from different experiments + over a number of central iterations in train.py. + """ + print('get_user_counts') + all_counts = dict() + for r in range(num_central_iterations): + all_counts[r + 1] = [] + l = list(training_federated_dataset.get_cohort(cohort_size)) + for d, _ in l: + _, y = d.raw_data + y = y.cpu().numpy() + uniques, counts = np.unique(y, return_counts=True) + full_y = np.zeros(num_classes) + full_y[uniques.astype(int)] = counts + all_counts[r + 1].append(full_y.tolist()) + + joblib.dump(all_counts, save_path) diff --git a/publications/mdm/mdm_utils/datasets/sampler.py b/publications/mdm/mdm_utils/datasets/sampler.py new file mode 100644 index 0000000..070783b --- /dev/null +++ b/publications/mdm/mdm_utils/datasets/sampler.py @@ -0,0 +1,123 @@ +# -*- coding: utf-8 -*- + +import itertools + +import numpy as np + + +class DirichletDataSampler: + """ + Data sampling mechanism that samples user class proportions from a + Dirichlet distribution with a given alpha parameter. + Sampling is done by first drawing a vector of class proportions + p ~ Dir(alpha), then sampling a class from a categorical + distribution with parameter p and uniformly at random choosing + (with replacement) an index with the corresponding class. + + :param alpha: + Parameter of the Dirichlet distribution. Must be array_like and + have length equal to the number of unique classes present in labels. + :param labels: + A one-dimensional array of all labels (integers). This should have + length equal to the size of the corresponding dataset. + """ + + def __init__(self, alpha: np.ndarray, labels: np.ndarray): + self.unique_labels = np.unique(labels) + assert len(alpha) == len( + self.unique_labels + ), "Number of classes doesn't equal dirichlet parameter dimension." + self.indices_per_class = { + i: np.nonzero(labels == i)[0] + for i in self.unique_labels + } + self.alpha = alpha + + def __call__(self, n: int): + """ + Sample a list of datapoint indices. + :param n: + Number of samples to draw. + :returns: + Sampled indices in range '[0, len(labels)]' + """ + class_priors = np.random.dirichlet(alpha=self.alpha) + sampled_class_counts = np.random.multinomial(n, pvals=class_priors) + sampled_indices = [ + list( + np.random.choice(self.indices_per_class[i], + size=class_count, + replace=True)) + for i, class_count in zip(self.unique_labels, sampled_class_counts) + ] + return sum(sampled_indices, []) + + +class DirichletMixtureDataSampler: + + def __init__(self, phi: np.ndarray, alphas: np.ndarray, + labels: np.ndarray): + self.phi = phi + self.dirichlet_samplers = [ + DirichletDataSampler(alpha, labels) for alpha in alphas + ] + + def __call__(self, n: int): + j = np.random.choice(range(len(self.phi)), p=self.phi) + return self.dirichlet_samplers[j](n) + + +class MinimizeReuseDataSampler: + """ + Data sampling mechanism that maximises the time between instances of reuse. + This is done by simply iterating through the sample space in linear fashion + and starting over once the end is reached. + Every data sampling mechanism returns a list of indices when called. + The indices can be used to construct an artificial user dataset. + :param max_bound: + Maximum bound for sampling space. + Will sample in the range `[0, max_bound)`. + """ + + def __init__(self, max_bound): + self._index_iter = itertools.cycle(range(max_bound)) + + def __call__(self, n): + """ + Sample a list of data point indices. + :param n: + Number of samples to draw. + :returns: + Sampled indices in range `[0, max_bound)`. + """ + return list(itertools.islice(self._index_iter, n)) + + +def get_data_sampler(sample_type, + max_bound=None, + phi=None, + alphas=None, + alpha=None, + labels=None): + """ + Factory for data sampling mechanisms. + These samplers can be used when sampling data points for an artificial + user dataset in `ArtificialFederatedDataset`, by providing it as the + `sampler` argument. + Implemented samplers: + * random - Randomly sample from the range `[0, max_bound)`. + * minimize_reuse - Sample while minimizing the number of times a number is + sampled again. + * dirichlet - Sample class proportions from a Dirichlet with given alpha + parameter and sample classes according to these proportions. + """ + if sample_type == 'random': + return lambda n: np.random.randint(0, max_bound, size=n) + elif sample_type == 'minimize_reuse': + return MinimizeReuseDataSampler(max_bound) + elif sample_type == 'dirichlet': + return DirichletDataSampler(alpha, labels) + elif sample_type == 'dirichlet_mixture': + return DirichletMixtureDataSampler(phi, alphas, labels) + else: + raise NotImplementedError diff --git a/publications/mdm/mdm_utils/models/__init__.py b/publications/mdm/mdm_utils/models/__init__.py new file mode 100644 index 0000000..92c2260 --- /dev/null +++ b/publications/mdm/mdm_utils/models/__init__.py @@ -0,0 +1 @@ +from .pytorch_model import simple_cnn diff --git a/publications/mdm/mdm_utils/models/argument_parsing.py b/publications/mdm/mdm_utils/models/argument_parsing.py new file mode 100644 index 0000000..3d70d70 --- /dev/null +++ b/publications/mdm/mdm_utils/models/argument_parsing.py @@ -0,0 +1,188 @@ +# -*- coding: utf-8 -*- + +import argparse +from typing import Optional, Tuple + + +def add_model_arguments( + parser: argparse.ArgumentParser) -> argparse.ArgumentParser: + """ + Add `model_name` argument to parser and add + model-specific arguments depending on the model specified in + `model_name` argument. + """ + + parser.add_argument( + '--model_name', + choices=[ + 'simple_cnn', 'simple_dnn', 'resnet18', 'lm_lstm', + 'lm_transformer', 'multi_label_cnn' + ], + default='simple_cnn', + help='Which model to train. See models.py for definitions.') + + # Get the value of `model_name` argument and dynamically add + # arguments depending on which model is chosen. + known_args, _ = parser.parse_known_args() + + if known_args.model_name in {'lm_lstm', 'lm_transformer'}: + parser.add_argument("--embedding_size", + type=int, + required=True, + help='Number of dimensions in embedding layer.') + + if known_args.model_name == 'lm_lstm': + parser.add_argument("--num_cell_states", + type=int, + required=True, + help='Number of cell states in each LSTM.') + + parser.add_argument("--num_lstm_layers", + type=int, + required=True, + help='Number of stacked LSTM layers.') + + if known_args.model_name == 'lm_transformer': + parser.add_argument("--hidden_size", + type=int, + required=True, + help='Number of hidde states in each Transformer.') + + parser.add_argument( + "--num_heads", + type=int, + required=True, + help='Number of heads in multi-head attention layers.') + + parser.add_argument( + '--feedforward_size', + type=int, + required=True, + help='Number of feed forward hidden states in each Transformer.') + + parser.add_argument("--num_transformer_layers", + type=int, + required=True, + help='Number of stacked Transformer layers.') + + parser.add_argument( + '--dropout_rate', + type=float, + default=0.1, + help='Dropout rate applied in the Transformer model.') + + if known_args.model_name == 'multi_label_cnn': + _torchvision_architectures = [ + 'alexnet', 'resnet18', 'resnet34', 'resnet50', 'resnet101', + 'resnet152', 'resnext50_32x4d', 'resnext101_32x8d', + 'wide_resnet50_2', 'wide_resnet101_2', 'vgg11', 'vgg11_bn', + 'vgg13', 'vgg13_bn', 'vgg16', 'vgg16_bn', 'vgg19_bn', 'vgg19', + 'squeezenet1_0', 'squeezenet1_1', 'inception_v3', 'densenet121', + 'densenet169', 'densenet201', 'densenet161', 'googlenet', + 'mobilenet_v2', 'mnasnet0_5', 'mnasnet0_75', 'mnasnet1_0', + 'mnasnet1_3', 'shufflenet_v2_x0_5', 'shufflenet_v2_x1_0', + 'shufflenet_v2_x1_5', 'shufflenet_v2_x2_0' + ] + + parser.add_argument('--model_type', + choices=_torchvision_architectures, + help='Model architecture.') + + return parser + + +def _get_model_dims_for_dataset( + dataset_name: str) -> Tuple[Optional[Tuple[int, ...]], Optional[int]]: + """ + Get the correct input shape and number of outputs for the + specified dataset. + """ + if dataset_name == 'femnist': + input_shape = (28, 28, 1) + num_outputs = 62 + elif dataset_name == 'femnist_digits': + input_shape = (28, 28, 1) + num_outputs = 10 + elif dataset_name in ['cifar10', 'cifar10_iid']: + input_shape = (32, 32, 3) + num_outputs = 10 + else: + input_shape = None + num_outputs = None + + return input_shape, num_outputs + + +def get_model_tf2(args: argparse.Namespace): + """ + Initialize the TensorFlow v2 model specified by ``args.model_name`` with + other required arguments also available in ``args``. + Use ``add_model_arguments`` to dynamically add arguments required by + the selected model. + """ + assert 'model_name' in vars(args) + from . import tf2 + + input_shape, num_outputs = _get_model_dims_for_dataset(args.dataset) + + model_name = args.model_name.lower() + if model_name == 'dnn': + model = tf2.dnn(input_shape, args.hidden_dims, num_outputs) + elif model_name == 'simple_dnn': + model = tf2.simple_dnn(input_shape, num_outputs) + elif model_name == 'simple_cnn': + model = tf2.simple_cnn(input_shape, num_outputs) + elif model_name == 'resnet18': + model = tf2.resnet18(input_shape, num_outputs) + elif model_name == 'lm_lstm': + model = tf2.lm_lstm(args.embedding_size, args.num_cell_states, + args.num_lstm_layers, args.vocab_size) + elif model_name == 'lm_transformer': + model = tf2.lm_transformer(args.embedding_size, args.hidden_size, + args.num_heads, args.feedforward_size, + args.num_transformer_layers, + args.vocab_size, args.max_sequence_length, + args.dropout_rate) + else: + raise TypeError(f'Model {model_name} not implemented for TF2.') + + return model + + +def get_model_pytorch(args: argparse.Namespace): + """ + Initialize the PyTorch model specified by ``args.model_name`` with + other required arguments also available in ``args``. + Use ``add_model_arguments`` to dynamically add arguments required by + the selected model. + """ + assert 'model_name' in vars(args) + from . import pytorch + + input_shape, num_outputs = _get_model_dims_for_dataset(args.dataset) + + model_name = args.model_name.lower() + + if model_name == 'dnn': + model = pytorch.dnn(input_shape, args.hidden_dims, num_outputs) + elif model_name == 'simple_dnn': + model = pytorch.simple_dnn(input_shape, num_outputs) + elif model_name == 'simple_cnn': + model = pytorch.simple_cnn(input_shape, num_outputs) + elif model_name == 'lm_lstm': + model = pytorch.lm_lstm(args.embedding_size, args.num_cell_states, + args.num_lstm_layers, args.vocab_size, + args.pad_symbol, args.unk_symbol) + elif model_name == 'lm_transformer': + model = pytorch.lm_transformer( + args.embedding_size, args.hidden_size, args.num_heads, + args.feedforward_size, args.num_transformer_layers, + args.vocab_size, args.max_sequence_length, args.pad_symbol, + args.unk_symbol, args.dropout_rate) + elif model_name == 'multi_label_cnn': + model = pytorch.multi_label_cnn(args.model_type, args.num_classes, + args.channel_mean, + args.channel_stddevs, args.pretrained) + else: + raise TypeError(f'Model {model_name} not implemented for PyTorch.') + return model diff --git a/publications/mdm/mdm_utils/models/pytorch/__init__.py b/publications/mdm/mdm_utils/models/pytorch/__init__.py new file mode 100644 index 0000000..664abd6 --- /dev/null +++ b/publications/mdm/mdm_utils/models/pytorch/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- + +from .cnn import simple_cnn, multi_label_cnn +from .dnn import dnn, simple_dnn +from .lstm import lm_lstm +from .transformer import lm_transformer diff --git a/publications/mdm/mdm_utils/models/pytorch/cnn.py b/publications/mdm/mdm_utils/models/pytorch/cnn.py new file mode 100644 index 0000000..ef85a40 --- /dev/null +++ b/publications/mdm/mdm_utils/models/pytorch/cnn.py @@ -0,0 +1,226 @@ +# -*- coding: utf-8 -*- + +import types +from typing import Tuple, List + +import numpy as np +import torch # type: ignore +import torch.nn as nn +import torch.nn.functional as F +from pfl.metrics import Weighted + +from .layer import Transpose2D +from .metrics import image_classification_metrics, image_classification_loss +from ..numpy.metrics import AveragedPrecision, MacroWeighted + + +def multi_label_cnn( + model_type: str, + num_outputs: int, + channel_mean: List[float], + channel_stddevs: List[float], + pretrained: bool, +): + """ + A CNN used for multi-label classification task. + + :param model_type: + The architecture of the model. + :param num_outputs: + Size of the output multi-label classification layer. + :param channel_mean: + Means for input image RGB channels. + :param channel_stddevs: + Standard deviations for input image RGB channels. + :param pretrained: + Whether to use ImageNet pretrained model. + + :return: + A Pytorch CNN module for multi-label classification. + """ + + import torchvision.models # type: ignore + import torchvision.transforms as transforms # type: ignore + from .module_modification import (validate_no_batchnorm, + freeze_batchnorm_modules, + convert_batchnorm_modules) + + torchvision_models = torchvision.models.__dict__ + + class MultiLabelCNN(nn.Module): + """ + Wrapper of torchvision.models used for Ramsay PFL training on multi-label + classification task, e.g. on FLAIR dataset. + """ + + def __init__( + self, + torchvision_model_type: str, + num_outputs: int, + channel_mean: List[float], + channel_stddevs: List[float], + pretrained: bool, + ): + super().__init__() + self._num_outputs = num_outputs + + # input image transformation, same as standard ImageNet training + self.train_transform = transforms.Compose([ + transforms.RandomResizedCrop(224), + transforms.RandomHorizontalFlip(), + transforms.Normalize(channel_mean, channel_stddevs) + ]) + self.eval_transform = transforms.Compose([ + transforms.Resize(224), + transforms.Normalize(channel_mean, channel_stddevs) + ]) + + # per-class binary cross-entropy for multi-label classification + # learning objective + self.loss_fct = nn.BCEWithLogitsLoss() + + # https://github.com/pytorch/examples/blob/master/imagenet/main.py + base_model = torchvision_models[torchvision_model_type]( + num_classes=self._num_outputs) + if pretrained: + pretrained_model = torchvision_models[torchvision_model_type]( + pretrained=True) + pretrained_state = pretrained_model.state_dict() + # Pretrained models typically use Batch Normalization. Since we do + # not want to collect channel statistics in private learning, we + # freeze the trained statistics in all batch norm modules, i.e., + # the statistics will be from pretrained dataset (ImageNet) instead + # of private data on device. + base_model = freeze_batchnorm_modules(base_model) + base_state = base_model.state_dict() + state_to_load = {} + # skip loading the final classifier layer's weight and bias + for k, v in list(pretrained_state.items())[:-2]: + assert k in base_state and v.size() == base_state[k].size() + state_to_load[k] = v + base_model.load_state_dict(state_to_load, strict=False) + self.base_model = base_model + else: + # convert all batch norm module to group norm if not using + # pretrained models + self.base_model = convert_batchnorm_modules(base_model) + + # assert there is no batch norm module in current model + validate_no_batchnorm(self) + + def transform(self, images: torch.Tensor): + images = (images.float() / 255.0).permute(0, 3, 1, 2) + if self.training: + return self.train_transform(images) + else: + return self.eval_transform(images) + + def forward(self, images): + x = self.transform(images) + return self.base_model(x) + + def loss(self, inputs, targets, eval=False): + self.eval() if eval else self.train() + return self.loss_fct(self(inputs), targets) + + @torch.no_grad() + def metrics(self, inputs, targets, eval=True): + self.eval() if eval else self.train() + logits = self(inputs) + + num_data = len(inputs) + num_predictions = np.ones(self._num_outputs) * num_data + summed_loss = F.binary_cross_entropy_with_logits( + logits, targets, reduction='none').sum(dim=0) + + scores = torch.sigmoid(logits) + predictions = torch.round(scores) + correct = torch.sum(torch.eq(targets, predictions), dim=0) + + # evaluate precision and recall + predictions = predictions.bool() + targets = targets.bool() + # true positives, positive label predicted as positive + tps = torch.sum(predictions & targets, dim=0) + # false positives, negative label predicted as positive + fps = torch.sum(predictions & ~targets, dim=0) + # false negatives, positive label predicted as negative + fns = torch.sum(~predictions & targets, dim=0) + # micro true positives, false positives, false negatives + tps_sum = tps.sum().item() + fps_sum = fps.sum().item() + fns_sum = fns.sum().item() + + return { + # Micro metrics: averaged over all predictions + "micro loss": + Weighted(summed_loss.sum().item(), num_predictions.sum()), + "micro accuracy": + Weighted(correct.sum().item(), num_predictions.sum()), + "micro precision": + Weighted(tps_sum, tps_sum + fps_sum), + "micro recall": + Weighted(tps_sum, tps_sum + fns_sum), + "micro AP": + AveragedPrecision(y_true=targets.cpu().numpy(), + y_pred=scores.cpu().numpy(), + multi_label=False), + # Macro metrics: averaged over classes + "macro loss": + MacroWeighted(summed_loss.cpu().numpy(), num_predictions), + "macro accuracy": + MacroWeighted(correct.cpu().numpy(), num_predictions), + "macro precision": + MacroWeighted(tps.cpu().numpy(), + tps.cpu().numpy() + fps.cpu().numpy()), + "macro recall": + MacroWeighted(tps.cpu().numpy(), + tps.cpu().numpy() + fns.cpu().numpy()), + "macro AP": + AveragedPrecision(y_true=targets.cpu().numpy(), + y_pred=scores.cpu().numpy(), + multi_label=True), + } + + return MultiLabelCNN(model_type, num_outputs, channel_mean, + channel_stddevs, pretrained) + + +def simple_cnn(input_shape: Tuple[int, ...], num_outputs: int) -> nn.Module: + """ + A simple CNN with 2 convolutional layers and one dense hidden layer. + + :param input_shape: + The shape of the input images, e.g. (32,32,3). + :param num_outputs: + Size of output softmax layer. + :return: + A PyTorch CNN model. + """ + in_channels = input_shape[-1] + maxpool_output_size = (input_shape[0] - 4) // 2 + flatten_size = maxpool_output_size * maxpool_output_size * 64 + + model = nn.Sequential(*[ + Transpose2D(), + nn.Conv2d(in_channels, 32, kernel_size=(3, 3)), + nn.ReLU(), + nn.Conv2d(32, 64, kernel_size=(3, 3)), + nn.ReLU(), + nn.MaxPool2d((2, 2)), + nn.Dropout(0.25), + nn.Flatten(), + nn.Linear(flatten_size, 128), + nn.ReLU(), + nn.Dropout(0.5), + nn.Linear(128, num_outputs), + ]) + + # Apply Glorot (Xavier) uniform initialization to match TF2 model. + for m in model.modules(): + if isinstance(m, nn.Conv2d) or isinstance(m, nn.Linear): + torch.nn.init.xavier_uniform_(m.weight) + + model.loss = types.MethodType(image_classification_loss, model) + model.metrics = types.MethodType(image_classification_metrics, model) + return model diff --git a/publications/mdm/mdm_utils/models/pytorch/dnn.py b/publications/mdm/mdm_utils/models/pytorch/dnn.py new file mode 100644 index 0000000..a07e152 --- /dev/null +++ b/publications/mdm/mdm_utils/models/pytorch/dnn.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- + +from typing import Tuple +import functools +import types + +import torch.nn as nn +import numpy as np + +from .metrics import image_classification_metrics, image_classification_loss + + +def dnn(input_shape: Tuple[int, ...], hidden_dims: Tuple[int, ...], + num_outputs: int) -> nn.Module: + """ + Define a feed-forward neural network in PyTorch. + + :param input_shape: + The shape of the input data (excluding batch size). E.g. if the + input is an image of dimensions (12,12,3), then it will be flattened + into a 432-dimensional vector before propagated through the network. + :param hidden_dims: + A tuple describing the size of each hidden layer. + :param num_outputs: + Size of output softmax layer. + :return: + A PyTorch DNN model. + """ + + in_features = int(np.prod(input_shape)) + layers = [nn.Flatten()] + for dim in hidden_dims: + layers.extend([nn.Linear(in_features, dim), nn.ReLU()]) + in_features = dim + layers.append(nn.Linear(in_features, num_outputs)) + model = nn.Sequential(*layers) + model.loss = types.MethodType(image_classification_loss, model) + model.metrics = types.MethodType(image_classification_metrics, model) + return model + + +def simple_dnn(input_shape: Tuple[int, ...], num_outputs: int) -> nn.Module: + """ + Define a feed-forward neural network with 2 hidden layers of size 200. + This is the same architecture as used in + McMahan et al. 2017 https://arxiv.org/pdf/1602.05629.pdf. + See ``dnn`` for description about parameters. + """ + return functools.partial(dnn, hidden_dims=[200, + 200])(input_shape, + num_outputs=num_outputs) diff --git a/publications/mdm/mdm_utils/models/pytorch/layer.py b/publications/mdm/mdm_utils/models/pytorch/layer.py new file mode 100644 index 0000000..b21d35d --- /dev/null +++ b/publications/mdm/mdm_utils/models/pytorch/layer.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- + +from abc import ABC + +import torch +import torch.nn as nn +import torch.nn.functional as F +from torch.nn.modules.batchnorm import _NormBase +from ..numpy.layer import positional_encoding + + +class _FrozenBatchNorm(_NormBase, ABC): + """ + A special batch normalization module that will freeze the statistics + during training and only update the affine parameters. + """ + + def forward(self, input: torch.Tensor) -> torch.Tensor: + self._check_input_dim(input) + + # turn of training so no batchnorm statistics is collected + # and use pretrained statistics in training as well + self.training = False + + if self.momentum is None: + exponential_average_factor = 0.0 + else: + exponential_average_factor = self.momentum + + bn_training = (self.running_mean is None) and (self.running_var + is None) + + return F.batch_norm( + input, + # If buffers are not tracked, ensure that they won't be updated + self.running_mean + if not self.training or self.track_running_stats else None, + self.running_var + if not self.training or self.track_running_stats else None, + self.weight, + self.bias, + bn_training, + exponential_average_factor, + self.eps) + + +class FrozenBatchNorm1D(_FrozenBatchNorm): + + def _check_input_dim(self, input): + if input.dim() != 2 and input.dim() != 3: + raise ValueError('expected 2D or 3D input (got {}D input)'.format( + input.dim())) + + +class FrozenBatchNorm2D(_FrozenBatchNorm): + + def _check_input_dim(self, input): + if input.dim() != 4: + raise ValueError('expected 4D input (got {}D input)'.format( + input.dim())) + + +class FrozenBatchNorm3D(_FrozenBatchNorm): + + def _check_input_dim(self, input): + if input.dim() != 5: + raise ValueError('expected 5D input (got {}D input)'.format( + input.dim())) + + +class Transpose2D(nn.Module): + """ + Transpose Tensorflow style image to PyTorch compatible + """ + + def forward(self, inputs: torch.Tensor): + return inputs.permute((0, 3, 1, 2)) + + +class PositionalEncoding(nn.Module): + + def __init__(self, embedding_size: int, max_sequence_length: int): + super().__init__() + pe = positional_encoding(max_sequence_length, embedding_size) + self.register_buffer('pe', torch.as_tensor(pe)) + + def forward(self, x: torch.Tensor) -> torch.Tensor: + return x + torch.unsqueeze(self.pe[:x.size(1)], 0) diff --git a/publications/mdm/mdm_utils/models/pytorch/metrics.py b/publications/mdm/mdm_utils/models/pytorch/metrics.py new file mode 100644 index 0000000..2f9f096 --- /dev/null +++ b/publications/mdm/mdm_utils/models/pytorch/metrics.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- + +from typing import Dict + +import torch +import torch.nn as nn + +from pfl.metrics import Weighted + + +def cross_entropy(logits: torch.Tensor, targets: torch.Tensor, + reduction: str) -> torch.Tensor: + """ PyTorch cross entropy loss """ + # TODO: support logits with more than 2 dimensions + assert logits.ndim == 2, f"expect 2D tensor, get {logits.ndim}D" + loss_fct = nn.CrossEntropyLoss(reduction=reduction) + if targets.dim() > 1: + targets = targets.squeeze() + return loss_fct(logits, targets.long()) + + +@torch.no_grad() +def accuracy(logits: torch.Tensor, targets: torch.Tensor) -> torch.Tensor: + """ PyTorch classification accuracy """ + # TODO: support logits with more than 2 dimensions + assert logits.ndim == 2, f"expect 2D tensor, get {logits.ndim}D" + correct = logits.argmax(-1) == targets.squeeze().long() + return correct.float().sum() + + +def image_classification_loss(self: nn.Module, + inputs: torch.Tensor, + targets: torch.Tensor, + eval: bool = False) -> torch.Tensor: + """ Loss function to be attached to `PyTorchModel` for classification """ + self.eval() if eval else self.train() + return cross_entropy(self(inputs), targets, "mean") + + +@torch.no_grad() +def image_classification_metrics(self: nn.Module, + inputs: torch.Tensor, + targets: torch.Tensor, + eval: bool = True) -> Dict[str, Weighted]: + """ Metrics function to be attached to `PyTorchModel` for classification """ + self.eval() if eval else self.train() + logits = self(inputs) + num_samples = len(inputs) + correct = accuracy(logits, targets).item() + loss = cross_entropy(logits, targets, "sum").item() + return { + "loss": Weighted(loss, num_samples), + "accuracy": Weighted(correct, num_samples) + } diff --git a/publications/mdm/mdm_utils/models/pytorch/module_modification.py b/publications/mdm/mdm_utils/models/pytorch/module_modification.py new file mode 100644 index 0000000..39d9047 --- /dev/null +++ b/publications/mdm/mdm_utils/models/pytorch/module_modification.py @@ -0,0 +1,131 @@ +# -*- coding: utf-8 -*- + +from typing import Callable, Type + +from torch import nn + +from .layer import FrozenBatchNorm1D, FrozenBatchNorm2D, FrozenBatchNorm3D + + +def _replace_child(root: nn.Module, child_name: str, + converter: Callable[[nn.Module], nn.Module]) -> None: + """ + Converts a sub-module to a new module given a helper + function, the root module and a string representing + the name of the submodule to be replaced. + """ + # find the immediate parent + parent = root + nameList = child_name.split(".") + for name in nameList[:-1]: + parent = parent._modules[name] + # set to identity + parent._modules[nameList[-1]] = converter(parent._modules[nameList[-1]]) + + +def replace_all_modules( + root: nn.Module, + target_class: Type[nn.Module], + converter: Callable[[nn.Module], nn.Module], +) -> nn.Module: + """ + Converts all the submodules (of root) that have the same + type as target_class, given a converter, a module root, + and a target class type. + """ + # base case + if isinstance(root, target_class): + return converter(root) + + for name, obj in root.named_modules(): + if isinstance(obj, target_class): + _replace_child(root, name, converter) + return root + + +def _batchnorm_to_groupnorm( + module: nn.modules.batchnorm._BatchNorm) -> nn.Module: + """ + Converts a BatchNorm ``module`` to GroupNorm module. + This is a helper function. + + Notes: + A default value of 32 is chosen for the number of groups based on the + paper *Accurate, Large Minibatch SGD: Training ImageNet in 1 Hour* + https://arxiv.org/pdf/1706.02677.pdf + """ + return nn.GroupNorm(min(32, module.num_features), + module.num_features, + affine=True) + + +def _batchnorm_to_freeze_batchnorm( + module: nn.modules.batchnorm._BatchNorm) -> nn.Module: + """ + Converts a BatchNorm module to the corresponding FrozenBatchNorm module. + This is useful for private finetuning models with BatchNorm module since + we do not want to collect training data statistics for updating BatchNorm + parameters. Instead, the statistics of FrozenBatchNorm is never updated. + """ + + def match_dim(): + if isinstance(module, nn.BatchNorm1d): + return FrozenBatchNorm1D + elif isinstance(module, nn.BatchNorm2d): + return FrozenBatchNorm2D + elif isinstance(module, nn.BatchNorm3d): + return FrozenBatchNorm3D + + return match_dim()(num_features=module.num_features, + eps=module.eps, + momentum=module.momentum, + affine=module.affine, + track_running_stats=module.track_running_stats) + + +def validate_no_batchnorm(module: nn.Module): + """ + Assert no regular batch normalization in model architecture. + """ + ans = not isinstance(module, nn.modules.batchnorm._BatchNorm) + for child in module.children(): + ans = ans and validate_no_batchnorm(child) + assert ans + return ans + + +def convert_batchnorm_modules( + model: nn.Module, + converter: Callable[[nn.modules.batchnorm._BatchNorm], + nn.Module] = _batchnorm_to_groupnorm, +) -> nn.Module: + """ + Converts all BatchNorm modules to another module + (defaults to GroupNorm) that is privacy compliant. + + :param model + Module instance, potentially with sub-modules + :param converter + Function or a lambda that converts an instance of a + Batchnorm to another nn.Module. + + :return + Model with all the BatchNorm types replaced by another operation + by using the provided converter, defaulting to GroupNorm if one + isn't provided. + """ + return replace_all_modules(model, nn.modules.batchnorm._BatchNorm, + converter) + + +def freeze_batchnorm_modules(model: nn.Module): + """ + Convert all BatchNorm modules to FrozenBatchNorm modules where the stats + are frozen and not updated during training. + + :param model + Module instance, potentially with sub-modules + :return + A `FrozenBatchNorm` module with the same dimension as input module. + """ + return convert_batchnorm_modules(model, _batchnorm_to_freeze_batchnorm) diff --git a/publications/mdm/mdm_utils/models/pytorch_model.py b/publications/mdm/mdm_utils/models/pytorch_model.py new file mode 100644 index 0000000..cadc368 --- /dev/null +++ b/publications/mdm/mdm_utils/models/pytorch_model.py @@ -0,0 +1,105 @@ +import types +from typing import Tuple, Dict + +import torch +from torch import nn + +from pfl.metrics import Weighted + +# Taken directly from the Ramsay Examples Repo, all methods needed to define the +# pytorch model used for training. + + +def simple_cnn(input_shape: Tuple[int, ...], num_outputs: int) -> nn.Module: + """ + A simple CNN with 2 convolutional layers and one dense hidden layer. + + :param input_shape: + The shape of the input images, e.g. (32,32,3). + :param num_outputs: + Size of output softmax layer. + :return: + A PyTorch CNN model. + """ + in_channels = input_shape[-1] + maxpool_output_size = (input_shape[0] - 4) // 2 + flatten_size = maxpool_output_size * maxpool_output_size * 64 + + model = nn.Sequential(*[ + Transpose2D(), + nn.Conv2d(in_channels, 32, kernel_size=(3, 3)), + nn.ReLU(), + nn.Conv2d(32, 64, kernel_size=(3, 3)), + nn.ReLU(), + nn.MaxPool2d((2, 2)), + nn.Dropout(0.25), + nn.Flatten(), + nn.Linear(flatten_size, 128), + nn.ReLU(), + nn.Dropout(0.5), + nn.Linear(128, num_outputs), + ]) + + # Apply Glorot (Xavier) uniform initialization to match TF2 model. + for m in model.modules(): + if isinstance(m, nn.Conv2d) or isinstance(m, nn.Linear): + torch.nn.init.xavier_uniform_(m.weight) + + model.loss = types.MethodType(image_classification_loss, model) + model.metrics = types.MethodType(image_classification_metrics, model) + return model + + +class Transpose2D(nn.Module): + """ + Transpose Tensorflow style image to PyTorch compatible + """ + + def forward(self, inputs: torch.Tensor): + return inputs.permute((0, 3, 1, 2)) + + +def image_classification_loss(self: nn.Module, + inputs: torch.Tensor, + targets: torch.Tensor, + eval: bool = False) -> torch.Tensor: + """ Loss function to be attached to `PyTorchModel` for classification """ + self.eval() if eval else self.train() + return cross_entropy(self(inputs), targets, "mean") + + +def cross_entropy(logits: torch.Tensor, targets: torch.Tensor, + reduction: str) -> torch.Tensor: + """ PyTorch cross entropy loss """ + # TODO: support logits with more than 2 dimensions + assert logits.ndim == 2, f"expect 2D tensor, get {logits.ndim}D" + loss_fct = nn.CrossEntropyLoss(reduction=reduction) + if targets.dim() > 1: + targets = targets.squeeze() + return loss_fct(logits, targets.long()) + + +@torch.no_grad() +def accuracy(logits: torch.Tensor, targets: torch.Tensor) -> torch.Tensor: + """ PyTorch classification accuracy """ + # TODO: support logits with more than 2 dimensions + assert logits.ndim == 2, f"expect 2D tensor, get {logits.ndim}D" + correct = logits.argmax(-1) == targets.squeeze().long() + return correct.float().sum() + + +@torch.no_grad() +def image_classification_metrics(self: nn.Module, + inputs: torch.Tensor, + targets: torch.Tensor, + eval: bool = True) -> Dict[str, Weighted]: + """ Metrics function to be attached to `PyTorchModel` for classification """ + self.eval() if eval else self.train() + logits = self(inputs) + num_samples = len(inputs) + correct = accuracy(logits, targets).item() + loss = cross_entropy(logits, targets, "sum").item() + return { + "loss": Weighted(loss, num_samples), + "accuracy": Weighted(correct, num_samples) + } diff --git a/publications/mdm/mdm_utils/utils/__init__.py b/publications/mdm/mdm_utils/utils/__init__.py new file mode 100644 index 0000000..b3fccc1 --- /dev/null +++ b/publications/mdm/mdm_utils/utils/__init__.py @@ -0,0 +1,5 @@ +from .argument_parsing import (add_dataset_args, add_experiment_args, + add_init_algorithm_args, add_algorithm_args, + add_mle_args, add_histogram_algorithm_args, + add_user_visualisation_args, + add_dataset_preprocessing_args) diff --git a/publications/mdm/mdm_utils/utils/argument_parsing.py b/publications/mdm/mdm_utils/utils/argument_parsing.py new file mode 100644 index 0000000..2650e66 --- /dev/null +++ b/publications/mdm/mdm_utils/utils/argument_parsing.py @@ -0,0 +1,154 @@ +import argparse + + +class store_bool(argparse.Action): + + def __init__(self, option_strings, dest, **kwargs): + argparse.Action.__init__(self, option_strings, dest, **kwargs) + + def __call__(self, parser, namespace, values, option_string=None): + false_values = set(['false', 'no']) + true_values = set(['true', 'yes']) + + values = values.lower() + + if not values in (false_values | true_values): + raise argparse.ArgumentError( + self, 'Value must be either "true" or "false"') + value = (values in true_values) + + setattr(namespace, self.dest, value) + + +def add_experiment_args(parser): + parser.add_argument('--seed', type=int, default=0) + parser.add_argument('--data_dir', type=str) + parser.add_argument('--dirname', type=str) + parser.add_argument('--mle_param_dirname', type=str, default='publications/mdm/mle_params') + parser.add_argument( + '--precomputed_parameter_filepath', + type=str, + default=None, + # default='saved_mle_params/femnist_2_mixture.pkl', + help='If given then the inferred dirichlet mixture' + 'params will be loaded from here, do not specify file extension') + parser.add_argument('--dataset_type', + type=str, + default='original', + choices=[ + 'original', + 'original_labels_uniform_datapoints', + 'polya_mixture_federated', + 'polya_mixture_artificial_federated', + 'uniform_federated', + 'uniform_artificial_federated', + ]) + return parser + + +def add_dataset_preprocessing_args(parser): + parser.add_argument('--filter_method', + type=str, + default=None, + choices=['index', 'sample']) + parser.add_argument('--sample_fraction', type=float, default=1.0) + parser.add_argument('--start_idx', type=int, default=0) + parser.add_argument('--end_idx', type=int, default=-1) + parser.add_argument('--include_sampled', action=store_bool, default=True) + return parser + + +def float_list(arg): + try: + float_values = [float(val) for val in arg.split()] + return float_values + except ValueError: + raise argparse.ArgumentTypeError("Invalid float values in the list") + + +def int_list(arg): + try: + int_values = [int(val) for val in arg.split()] + return int_values + except ValueError: + raise argparse.ArgumentTypeError("Invalid int values in the list") + + +def add_dataset_args(parser): + # Args that are used to create a dirichlet mixture partition of cifar10 + parser.add_argument( + '--component_mean_user_dataset_length', + type=int_list, + default=50, + help="Mean number of samples per user in each component") + parser.add_argument('--component_phi', + type=float_list, + default=1.0, + help='True mixture component weights') + parser.add_argument( + '--component_alphas', + type=float_list, + default=0.1, + help='The alpha value for each mixture component ' + '(all entries of vector/all categories take same value)') + return parser + + +def add_init_algorithm_args(parser): + parser.add_argument('--cohort_size_init_algorithm', type=int) + parser.add_argument('--max_num_samples_mixture_component_init_algorithm', + type=int) + parser.add_argument('--strategy', type=str, default='random') + parser.add_argument('--central_num_iterations_init_algorithm', + type=int, + default=1) + return parser + + +def add_algorithm_args(parser): + parser.add_argument('--cohort_size_algorithm', type=int) + parser.add_argument('--max_num_samples_mixture_component_algorithm', + type=int) + parser.add_argument('--central_num_iterations_algorithm', + type=int, + default=10) + return parser + + +def add_histogram_algorithm_args(parser): + parser.add_argument('--cohort_size_histogram_algorithm', type=int) + parser.add_argument('--central_num_iterations_histogram_algorithm', + type=int, + default=1) + parser.add_argument('--num_bins_histogram', type=int, default=500) + return parser + + +def add_mle_args(parser): + # Add the arguments related to the solving of the Polya Mixture MLE + parser.add_argument( + '--num_mixture_components', + type=int, + default=1, + help='Number of Polya mixture components to try to infer') + return parser + + +def add_user_visualisation_args(parser): + parser.add_argument('--cohort_size_visualization', type=int, default=100) + parser.add_argument('--num_iterations_visualization', type=int, default=20) + return parser + + +def add_flair_visualisation_args(parser): + parser.add_argument('--use_fine_grained_labels', + action=store_bool, + default=False, + help='Whether to use fine-grained label taxonomy.') + + parser.add_argument('--max_num_user_images', + type=int, + default=100, + help='Maximum number of images per user') + + return parser diff --git a/publications/mdm/mdm_utils/utils/tools.py b/publications/mdm/mdm_utils/utils/tools.py new file mode 100644 index 0000000..6280ee1 --- /dev/null +++ b/publications/mdm/mdm_utils/utils/tools.py @@ -0,0 +1,55 @@ +import os +from typing import Tuple + +from pfl.callback import TrainingProcessCallback +from pfl.internal.ops.selector import get_default_framework_module as get_ops + +from pfl.metrics import Metrics +from pfl.model.base import StatefulModel + + +class ModelCheckpointingIterationCallback(TrainingProcessCallback): + """ + Callback to save model checkpoints. + + :param model_checkpoint_dir: + A path to disk for saving the trained model. + :param checkpoint_frequency: + The number of central iterations after which to save a model. + When zero (the default), the model is saved once after + training is complete. + """ + + def __init__(self, + model_checkpoint_dir: str, + *, + checkpoint_frequency: int = 0): + if get_ops().distributed.local_rank == 0: + self.checkpoint_frequency = checkpoint_frequency + from pfl.internal.platform.selector import get_platform + self.model_checkpoint_dir = get_platform( + ).create_checkpoint_directories([model_checkpoint_dir])[0] + + def _should_checkpoint_now(self, central_iteration: int) -> bool: + """ + Return true when the number of `central_iteration`s that have + completed is a non-zero multiple of `self.checkpoint_frequency`. + """ + return (self.checkpoint_frequency > 0 + and central_iteration % self.checkpoint_frequency + == (self.checkpoint_frequency - 1)) + + def after_central_iteration( + self, aggregate_metrics: Metrics, model: StatefulModel, *, + central_iteration: int) -> Tuple[bool, Metrics]: + if get_ops().distributed.local_rank == 0: + if self._should_checkpoint_now(central_iteration): + model.save( + os.path.join(self.model_checkpoint_dir, + f'{central_iteration}')) + return False, Metrics() + + def on_train_end(self, *, model: StatefulModel) -> None: + if get_ops().distributed.local_rank == 0: + if self.checkpoint_frequency == 0: + model.save(self.model_checkpoint_dir + '_end') diff --git a/publications/mdm/mdm_utils/utils/visualize_results.py b/publications/mdm/mdm_utils/utils/visualize_results.py new file mode 100644 index 0000000..281f39d --- /dev/null +++ b/publications/mdm/mdm_utils/utils/visualize_results.py @@ -0,0 +1,71 @@ +import os +from itertools import product + +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd + +PARENT_DIR = os.path.dirname(os.getcwd()) + + +def plot_cifar10_results(): + filename = os.path.join(PARENT_DIR, 'results', 'cifar10_hp_search.csv') + df = pd.read_csv(filename) + experiments = np.unique(df['experiment'].values).tolist() + + dfs = dict() + for experiment in experiments: + dfs[experiment] = (df.loc[df['experiment'] == experiment]) + + column_names = [ + 'cohort_size', 'local_batch_size', 'local_learning_rate', + 'local_num_epochs' + ] + unique_vals = dict() + for column_name in column_names: + unique_vals[column_name] = np.unique(dfs['live'][column_name]).tolist() + + accs = dict() + for name, df in dfs.items(): + accs[name] = dict() + for tup in product(*unique_vals.values()): + filter_dic = dict(zip(column_names, tup)) + a = df.loc[(df[list(filter_dic)] == pd.Series(filter_dic)).all( + axis=1)]['Central val | accuracy (avg)'].values.mean() + accs[name][tup] = a + + x = np.array(list(accs['live'].values())) + permutation = np.argsort(-x) + mask = np.array(list(accs['live'].values()))[permutation] >= 0.6 + + dic = dict() + c = dict(zip(accs.keys(), ['blue', 'red', 'green'])) + + plt.rcParams.update({'font.size': 13}) + for name, d in accs.items(): + x = np.array(list(d.values()))[permutation][mask] + dic[name] = x + + plt.plot(x, label=name, c=c[name]) + + plt.xlabel('Random hyperparameter setting') + plt.ylabel('Classification accuracy (%)') + plt.legend() + plt.show() + + print( + np.mean( + np.abs( + np.array(dic['live']) - np.array(dic['simulated_dirichlet'])))) + print( + np.mean( + np.abs(np.array(dic['live']) - + np.array(dic['simulated_uniform'])))) + + +def main(): + plot_cifar10_results() + + +if __name__ == '__main__': + main() diff --git a/publications/mdm/run_cifar10_mse_alpha_phi_experiments.sh b/publications/mdm/run_cifar10_mse_alpha_phi_experiments.sh new file mode 100755 index 0000000..23e6be9 --- /dev/null +++ b/publications/mdm/run_cifar10_mse_alpha_phi_experiments.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +set -oeux + +export PYTHONPATH=. + +num_components='1' +type='easy' + +if [ "$num_components" -eq 1 ] && [ "$type" == "easy" ]; then + + alphas='1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0' + phi='1.0' + user_dataset_length='20' + +elif [ "$num_components" -eq 2 ] && [ "$type" == "easy" ]; then + + alphas='1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.8 0.8 0.8 0.8 0.8 0.8 0.8 0.8 0.8 0.8' + phi='0.5 0.5' + user_dataset_length='20 20' + +elif [ "$num_components" -eq 3 ] && [ "$type" == "easy" ]; then + + alphas='1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.8 0.8 0.8 0.8 0.8 0.8 0.8 0.8 0.8 0.8 1.1 1.1 1.1 1.1 1.1 1.1 1.1 1.1 1.1 1.1' + phi='0.334 0.333 0.333' + user_dataset_length='20 20 20' + +elif [ "$num_components" -eq 1 ] && [ "$type" == "medium" ]; then + + alphas='0.1 0.2 0.6 1.0 2.0 0.1 1.0 2.0 0.5 0.5' + phi='1.0' + user_dataset_length='20' + +elif [ "$num_components" -eq 2 ] && [ "$type" == "medium" ]; then + + alphas='0.1 0.2 0.6 1.0 2.0 0.1 1.0 2.0 0.5 0.5 1.1 0.1 0.7 0.9 1.0 0.2 0.5 1.0 0.8 1.5' + phi='0.4 0.6' + user_dataset_length='20 20' + +elif [ "$num_components" -eq 3 ] && [ "$type" == "medium" ]; then + + alphas='0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.1 0.2 0.6 1.0 2.0 0.1 1.0 2.0 0.5 0.5 1.1 0.1 0.7 0.9 1.0 0.2 0.5 1.0 0.8 1.5' + phi='0.2 0.3 0.5' + user_dataset_length='20 20 20' + +elif [ "$num_components" -eq 1 ] && [ "$type" == "hard" ]; then + + alphas=0.1 + phi='1.0' + user_dataset_length='20' + +elif [ "$num_components" -eq 2 ] && [ "$type" == "hard" ]; then + + alphas='0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3' + phi='0.1 0.9' + user_dataset_length='20 20' + +elif [ "$num_components" -eq 3 ] && [ "$type" == "hard" ]; then + + alphas='0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 1.1 0.1 0.7 0.9 1.0 0.2 0.5 1.0 0.8 1.5' + phi='0.05 0.15 0.8' + user_dataset_length='20 20 20' + +else + + echo 'fail' + +fi + +python3 publications/mdm/mdm_paper/training/train.py --num_mixture_components "$num_components" --component_mean_user_dataset_length "$user_dataset_length" --component_alphas "$alphas" --cohort_size_init_algorithm 1000 --central_num_iterations_init_algorithm 1 --max_num_samples_mixture_component_init_algorithm 40 --cohort_size_algorithm 1000 --central_num_iterations_algorithm 60 --component_phi "$phi" --data_dir data/cifar10 --dirname "$type" diff --git a/publications/mdm/run_femnist.sh b/publications/mdm/run_femnist.sh new file mode 100755 index 0000000..419d978 --- /dev/null +++ b/publications/mdm/run_femnist.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +set -oeux + +export PYTHONPATH=. + +for num_components in 1 2 3; do + max_num_samples_mixture_component=450 + filter_method='sample' # 'sample' 'index' + sample_fraction=0.5 + include_sampled='True' + start_idx=0 + end_idx=1302 + + if [ "$filter_method" == "sample" ]; then + cohort_size=$(echo "scale=0; ($sample_fraction * 3400)" | bc | cut -d'.' -f1) + else + cohort_size=$(echo "$end_idx - $start_idx" | bc) + fi + + cohort_size_init_algorithm=$cohort_size + central_num_iterations_init_algorithm=1 + + cohort_size_algorithm=$cohort_size + central_num_iterations_algorithm=50 + + if [ "$filter_method" == "index" ]; then + python3 publications/mdm/mdm_paper/training/train_femnist_rebuttal.py --num_mixture_components "$num_components" --cohort_size_init_algorithm "$cohort_size_init_algorithm" --max_num_samples_mixture_component_init_algorithm "$max_num_samples_mixture_component" --central_num_iterations_init_algorithm "$central_num_iterations_init_algorithm" --cohort_size_algorithm "$cohort_size_algorithm" --max_num_samples_mixture_component_algorithm "$max_num_samples_mixture_component" --central_num_iterations_algorithm "$central_num_iterations_algorithm" --data_dir data/femnist --filter_method "$filter_method" --start_idx "$start_idx" --end_idx "$end_idx" + + elif [ "$filter_method" == "sample" ]; then + python3 publications/mdm/mdm_paper/training/train_femnist_rebuttal.py --num_mixture_components "$num_components" --cohort_size_init_algorithm "$cohort_size_init_algorithm" --max_num_samples_mixture_component_init_algorithm "$max_num_samples_mixture_component" --central_num_iterations_init_algorithm "$central_num_iterations_init_algorithm" --cohort_size_algorithm "$cohort_size_algorithm" --max_num_samples_mixture_component_algorithm "$max_num_samples_mixture_component" --central_num_iterations_algorithm "$central_num_iterations_algorithm" --data_dir data/femnist --filter_method "$filter_method" --sample_fraction "$sample_fraction" --include_sampled "$include_sampled" + + fi +done From d10e441d41663fedbafca86ab5db9d9423164eba Mon Sep 17 00:00:00 2001 From: fgranqvist Date: Tue, 4 Jun 2024 13:27:55 +0200 Subject: [PATCH 20/22] Prepare 0.2 release: changelog + bump version (#74) --- CHANGELOG.md | 23 +++++++++++++++++++++++ VERSION | 2 +- pfl/version.py | 2 +- pyproject.toml | 2 +- 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10438ac..c49ba7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,29 @@ * +## v0.2.0 + +### Breaking change! + +* `EMMGMMHyperParams` is renamed to `EMGMMHyperParams` (#55) + +### New features + +* Return local metadata from model training to algorithm (#71). + +### Tasks completed + +* Update FLAIR preprocessing script to download dataset from HuggingFace, available at https://huggingface.co/datasets/apple/flair (#72). +* Update LLM Benchmark Configs (#63). +* New improved worker scheduling in distributed simulations. Speeds up FLAIR benchmark by 19% (#73). +* Don't pin PyTorch version to 2.0.1 (#69). +* Move `--noise_cohort_size` to `add_mechanism_arguments` (#70). + +### Bug fixes + +* + + ## v0.1.0 2024-03-01 diff --git a/VERSION b/VERSION index 6e8bf73..0ea3a94 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.1.0 +0.2.0 diff --git a/pfl/version.py b/pfl/version.py index 3dc1f76..d3ec452 100644 --- a/pfl/version.py +++ b/pfl/version.py @@ -1 +1 @@ -__version__ = "0.1.0" +__version__ = "0.2.0" diff --git a/pyproject.toml b/pyproject.toml index bb3b6dc..7aba581 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -205,7 +205,7 @@ markers = [ # Run with command: # poetry run bump-my-version bump [tool.bumpversion] -current_version = "0.1.0" +current_version = "0.2.0" commit = "True" tag = "False" From 19ef43765b07fe514d83c7891fac2bf8181d2617 Mon Sep 17 00:00:00 2001 From: Filip Granqvist Date: Tue, 4 Jun 2024 13:49:34 +0200 Subject: [PATCH 21/22] same ruff ignores in publications as in benchmarks --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 7aba581..242ebaa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -168,6 +168,7 @@ ignore = [ "tests/integration/*" = ["S607"] "pfl/*" = ["S101", "S607"] "benchmarks/*" = ["S101", "SIM115", "A002", "B007", "E741", "S310"] +"publications/*" = ["S101", "SIM115", "A002", "B007", "E741", "S310"] [tool.coverage.report] skip_empty = true From 2065d11e735e9b6d32e90a863fd625fa3b51f081 Mon Sep 17 00:00:00 2001 From: ac554 <47990575+ac554@users.noreply.github.com> Date: Tue, 4 Jun 2024 21:07:43 +0100 Subject: [PATCH 22/22] ruff and mypy on publications/mdm (#78) --- .pre-commit-config.yaml | 1 + publications/__init__.py | 0 publications/mdm/__init__.py | 0 publications/mdm/mdm/__init__.py | 7 ++-- publications/mdm/mdm/algorithm.py | 20 ++++++------ publications/mdm/mdm/bridge/__init__.py | 0 publications/mdm/mdm/bridge/base.py | 7 ++-- publications/mdm/mdm/bridge/factory.py | 1 - .../mdm/mdm/bridge/pytorch/polya_mixture.py | 16 ++++++---- publications/mdm/mdm/init_algorithm.py | 18 ++++------- publications/mdm/mdm/model.py | 18 +++++------ .../mdm/mdm_paper/notebooks/__init__.py | 0 publications/mdm/mdm_paper/training/mle.py | 28 ++++++++-------- publications/mdm/mdm_paper/training/train.py | 25 ++++++++------- .../mdm/mdm_paper/training/train_femnist.py | 21 ++++++------ .../training/train_femnist_rebuttal.py | 23 +++++++------ .../mdm/mdm_utils/datasets/__init__.py | 2 +- .../mdm/mdm_utils/datasets/cifar10_dataset.py | 13 +++----- .../mdm/mdm_utils/datasets/femnist_dataset.py | 32 ++++++++----------- .../mdm/mdm_utils/datasets/mixture_dataset.py | 6 ++-- .../mdm/mdm_utils/datasets/sampler.py | 2 -- .../mdm/mdm_utils/models/argument_parsing.py | 2 -- .../mdm/mdm_utils/models/pytorch/__init__.py | 4 +-- .../mdm/mdm_utils/models/pytorch/cnn.py | 16 ++++------ .../mdm/mdm_utils/models/pytorch/dnn.py | 8 ++--- .../mdm/mdm_utils/models/pytorch/layer.py | 18 ++++------- .../mdm/mdm_utils/models/pytorch/metrics.py | 2 -- .../models/pytorch/module_modification.py | 2 -- .../mdm/mdm_utils/models/pytorch_model.py | 4 +-- publications/mdm/mdm_utils/utils/__init__.py | 15 ++++++--- .../mdm/mdm_utils/utils/argument_parsing.py | 16 ++++++---- publications/mdm/mdm_utils/utils/tools.py | 1 - .../mdm/mdm_utils/utils/visualize_results.py | 10 +++--- 33 files changed, 159 insertions(+), 179 deletions(-) create mode 100644 publications/__init__.py create mode 100644 publications/mdm/__init__.py create mode 100644 publications/mdm/mdm/bridge/__init__.py create mode 100644 publications/mdm/mdm_paper/notebooks/__init__.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index da4f768..e91a0b0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -45,6 +45,7 @@ repos: rev: v1.5.0 hooks: - id: mypy + exclude: ^publications/ # TODO: license header hook diff --git a/publications/__init__.py b/publications/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/publications/mdm/__init__.py b/publications/mdm/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/publications/mdm/mdm/__init__.py b/publications/mdm/mdm/__init__.py index 7ae9963..89c1ea9 100644 --- a/publications/mdm/mdm/__init__.py +++ b/publications/mdm/mdm/__init__.py @@ -1,4 +1,3 @@ -from .model import (MDMModelHyperParams, MDMModel) -from .init_algorithm import (MDMInitializationAlgorithmParams, - MDMInitializationAlgorithm) -from .algorithm import (MDMAlgorithmParams, MDMAlgorithm) +from .algorithm import MDMAlgorithm, MDMAlgorithmParams +from .init_algorithm import MDMInitializationAlgorithm, MDMInitializationAlgorithmParams +from .model import MDMModel, MDMModelHyperParams diff --git a/publications/mdm/mdm/algorithm.py b/publications/mdm/mdm/algorithm.py index 0f3be49..0f360c6 100644 --- a/publications/mdm/mdm/algorithm.py +++ b/publications/mdm/mdm/algorithm.py @@ -1,22 +1,18 @@ -# -*- coding: utf-8 -*- - from dataclasses import dataclass -from typing import Tuple, Optional, TypeVar, Callable, Union +from typing import Callable, Optional, Tuple, TypeVar, Union import numpy as np import torch +from pfl.algorithm.base import AlgorithmHyperParams, FederatedAlgorithm from pfl.common_types import Population -from pfl.data.dataset import AbstractDataset +from pfl.context import CentralContext +from pfl.data.dataset import AbstractDataset, AbstractDatasetType from pfl.hyperparam import get_param_value from pfl.metrics import Metrics -from pfl.context import CentralContext from pfl.stats import MappedVectorStatistics -from pfl.algorithm.base import FederatedAlgorithm, AlgorithmHyperParams -from pfl.data.dataset import AbstractDatasetType - -from publications.mdm.mdm.model import MDMModelType, MDMModelHyperParamsType from publications.mdm.mdm.bridge.factory import FrameworkBridgeFactory as bridges +from publications.mdm.mdm.model import MDMModelHyperParamsType, MDMModelType @dataclass(frozen=True) @@ -44,7 +40,8 @@ class MDMAlgorithmParams(AlgorithmHyperParams): class MDMAlgorithm(FederatedAlgorithm[MDMAlgorithmParamsType, MDMModelHyperParamsType, MDMModelType, - MappedVectorStatistics, AbstractDatasetType]): + MappedVectorStatistics, + AbstractDatasetType]): """ Federated algorithm class for learning mixture of Polya (Dirichlet-Multinomial) distribution using MLE algorithm. @@ -161,7 +158,8 @@ def simulate_one_user( e[:, selected_bin] = posterior_probabilities.view(-1) statistics = MappedVectorStatistics() - statistics['posterior_probabilities'] = posterior_probabilities.to('cpu') + statistics['posterior_probabilities'] = posterior_probabilities.to( + 'cpu') statistics['numerator'] = numerator.to('cpu') statistics['denominator'] = denominator.to('cpu') statistics['num_samples_distribution'] = e.to('cpu') diff --git a/publications/mdm/mdm/bridge/__init__.py b/publications/mdm/mdm/bridge/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/publications/mdm/mdm/bridge/base.py b/publications/mdm/mdm/bridge/base.py index f63e763..a9900ef 100644 --- a/publications/mdm/mdm/bridge/base.py +++ b/publications/mdm/mdm/bridge/base.py @@ -1,7 +1,4 @@ -# -*- coding: utf-8 -*- - -from typing import Any, Dict, Protocol, TypeVar, Tuple - +from typing import Any, Dict, Protocol, Tuple, TypeVar Tensor = TypeVar('Tensor') @@ -9,7 +6,7 @@ class PolyaMixtureFrameworkBridge(Protocol[Tensor]): """ Interface for Polya-Mixture algorithm for a particular Deep Learning - framework. + framework. """ @staticmethod diff --git a/publications/mdm/mdm/bridge/factory.py b/publications/mdm/mdm/bridge/factory.py index c395e26..4c3e449 100644 --- a/publications/mdm/mdm/bridge/factory.py +++ b/publications/mdm/mdm/bridge/factory.py @@ -8,7 +8,6 @@ ) from pfl.internal.ops.framework_types import MLFramework from pfl.internal.ops.selector import get_framework_module - from publications.mdm.mdm.bridge.base import PolyaMixtureFrameworkBridge diff --git a/publications/mdm/mdm/bridge/pytorch/polya_mixture.py b/publications/mdm/mdm/bridge/pytorch/polya_mixture.py index a43ed9c..463e42a 100644 --- a/publications/mdm/mdm/bridge/pytorch/polya_mixture.py +++ b/publications/mdm/mdm/bridge/pytorch/polya_mixture.py @@ -1,6 +1,5 @@ -# -*- coding: utf-8 -*- - from typing import Tuple + import torch from ..base import PolyaMixtureFrameworkBridge @@ -40,11 +39,13 @@ def category_probabilities_polya_mixture_initialization( def expectation_step(phi, alphas, num_samples_distribution, category_counts) -> torch.Tensor: if (num_samples_distribution == 0).any(): - raise AssertionError('num_samples_distribution contains zero values, which cannot work with expectation step on clients') + raise AssertionError( + 'num_samples_distribution contains zero values, which cannot work with expectation step on clients' + ) # E Step - compute posterior probability of each component # Compute log prior + log likelihood - # TODO log_v might be missing + torch.lgamma(torch.sum(counts)+1) - torch.sum(torch.lgamma(category_counts+1), dim=1, keepdim=False) + # TODO log_v might be missing + torch.lgamma(torch.sum(counts)+1) - torch.sum(torch.lgamma(category_counts+1), dim=1, keepdim=False) phi = torch.Tensor(phi).to('cpu') alphas = torch.Tensor(alphas).to('cpu') category_counts = category_counts.to('cpu') @@ -56,7 +57,7 @@ def expectation_step(phi, alphas, num_samples_distribution, torch.sum( torch.lgamma(category_counts + alphas) - torch.lgamma(alphas), dim=1, - keepdim=False)) + torch.log(num_samples_distribution) + keepdim=False)) + torch.log(num_samples_distribution) # TODO Ignore this as log(0) => NaN # TODO fix this equation so that it works with num_samples_distribution = 0 @@ -75,12 +76,13 @@ def expectation_step(phi, alphas, num_samples_distribution, @staticmethod def maximization_step(posterior_probabilities, category_counts, - alphas) -> torch.Tensor: + alphas) -> torch.Tensor: # M Step - compute client update to alphas for fixed point update # which will be applied by the model in process_aggregated_statistics. # Note the numerator and denominator are both weighted by w (the # probability vector giving the client belonging to each component). - posterior_probabilities = torch.Tensor(posterior_probabilities).to('cpu') + posterior_probabilities = torch.Tensor(posterior_probabilities).to( + 'cpu') category_counts = torch.Tensor(category_counts).to('cpu') alphas = torch.Tensor(alphas).to('cpu') numerator = posterior_probabilities.reshape( diff --git a/publications/mdm/mdm/init_algorithm.py b/publications/mdm/mdm/init_algorithm.py index 9a24c1b..9acaaee 100644 --- a/publications/mdm/mdm/init_algorithm.py +++ b/publications/mdm/mdm/init_algorithm.py @@ -1,24 +1,20 @@ -# -*- coding: utf-8 -*- - -from dataclasses import dataclass -from typing import Tuple, Optional, TypeVar, Callable, Union from collections import defaultdict +from dataclasses import dataclass +from typing import Callable, Optional, Tuple, TypeVar, Union import numpy as np import torch +from pfl.algorithm.base import AlgorithmHyperParams, FederatedAlgorithm from pfl.common_types import Population -from pfl.data.dataset import AbstractDataset +from pfl.context import CentralContext +from pfl.data.dataset import AbstractDataset, AbstractDatasetType from pfl.hyperparam import get_param_value +from pfl.internal.ops import get_ops from pfl.metrics import Metrics -from pfl.context import CentralContext from pfl.stats import MappedVectorStatistics -from pfl.internal.ops import get_ops -from pfl.algorithm.base import FederatedAlgorithm, AlgorithmHyperParams -from pfl.data.dataset import AbstractDatasetType - -from publications.mdm.mdm.model import MDMModelType, MDMModelHyperParamsType from publications.mdm.mdm.bridge.factory import FrameworkBridgeFactory as bridges +from publications.mdm.mdm.model import MDMModelHyperParamsType, MDMModelType @dataclass(frozen=True) diff --git a/publications/mdm/mdm/model.py b/publications/mdm/mdm/model.py index 3372fa3..65813f0 100644 --- a/publications/mdm/mdm/model.py +++ b/publications/mdm/mdm/model.py @@ -1,20 +1,18 @@ -# -*- coding: utf-8 -*- - -from typing import TypeVar, Generic, Tuple, List, Union, Optional -from dataclasses import dataclass import os -import joblib +from dataclasses import dataclass +from typing import Generic, List, Optional, Tuple, TypeVar, Union +import joblib import numpy as np -from pfl.hyperparam.base import ModelHyperParams -from pfl.model.base import Model -from pfl.metrics import Metrics -from pfl.stats import MappedVectorStatistics from pfl.exception import CheckpointNotFoundError -from pfl.internal.ops.selector import set_framework_module +from pfl.hyperparam.base import ModelHyperParams from pfl.internal.ops import pytorch_ops from pfl.internal.ops.selector import get_default_framework_module as get_ops +from pfl.internal.ops.selector import set_framework_module +from pfl.metrics import Metrics +from pfl.model.base import Model +from pfl.stats import MappedVectorStatistics Tensor = TypeVar('Tensor') FrameworkModelType = TypeVar('FrameworkModelType') diff --git a/publications/mdm/mdm_paper/notebooks/__init__.py b/publications/mdm/mdm_paper/notebooks/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/publications/mdm/mdm_paper/training/mle.py b/publications/mdm/mdm_paper/training/mle.py index 3376740..88d9394 100644 --- a/publications/mdm/mdm_paper/training/mle.py +++ b/publications/mdm/mdm_paper/training/mle.py @@ -2,13 +2,16 @@ from pfl.aggregate.simulate import SimulatedBackend from pfl.callback import ModelCheckpointingCallback -from pfl.privacy import (CentrallyAppliedPrivacyMechanism, PLDPrivacyAccountant, GaussianMechanism) - +from pfl.privacy import CentrallyAppliedPrivacyMechanism, GaussianMechanism, PLDPrivacyAccountant +from publications.mdm.mdm import ( + MDMAlgorithm, + MDMAlgorithmParams, + MDMInitializationAlgorithm, + MDMInitializationAlgorithmParams, + MDMModel, + MDMModelHyperParams, +) from publications.mdm.mdm_utils.utils.tools import ModelCheckpointingIterationCallback -from publications.mdm.mdm import (MDMModel, MDMModelHyperParams, - MDMAlgorithm, MDMAlgorithmParams, - MDMInitializationAlgorithm, - MDMInitializationAlgorithmParams) def solve_polya_mixture_mle( @@ -33,13 +36,12 @@ def solve_polya_mixture_mle( if add_DP: num_iterations = arguments.central_num_iterations_init_algorithm + arguments.central_num_iterations_algorithm - accountant = PLDPrivacyAccountant( - num_compositions=num_iterations, - sampling_probability=0.001, - mechanism='gaussian', - epsilon=2, - delta=1e-7, - noise_scale=1.0) + accountant = PLDPrivacyAccountant(num_compositions=num_iterations, + sampling_probability=0.001, + mechanism='gaussian', + epsilon=2, + delta=1e-7, + noise_scale=1.0) mechanism = GaussianMechanism.from_privacy_accountant( accountant=accountant, clipping_bound=0.5) diff --git a/publications/mdm/mdm_paper/training/train.py b/publications/mdm/mdm_paper/training/train.py index 9431ccd..811cefe 100644 --- a/publications/mdm/mdm_paper/training/train.py +++ b/publications/mdm/mdm_paper/training/train.py @@ -1,24 +1,26 @@ -import os import argparse import datetime +import os +import joblib import numpy as np import torch -import joblib from pfl.internal.ops import pytorch_ops from pfl.internal.ops.selector import get_default_framework_module as get_ops from pfl.internal.ops.selector import set_framework_module from pfl.internal.platform.selector import get_platform - -from publications.mdm.mdm_utils.datasets import make_cifar10_datasets -from publications.mdm.mdm_utils.utils import (add_dataset_args, add_experiment_args, - add_mle_args, add_init_algorithm_args, - add_algorithm_args, - add_histogram_algorithm_args, - add_user_visualisation_args) - from publications.mdm.mdm_paper.training.mle import solve_polya_mixture_mle +from publications.mdm.mdm_utils.datasets import make_cifar10_datasets +from publications.mdm.mdm_utils.utils import ( + add_algorithm_args, + add_dataset_args, + add_experiment_args, + add_histogram_algorithm_args, + add_init_algorithm_args, + add_mle_args, + add_user_visualisation_args, +) def get_arguments(): @@ -104,7 +106,8 @@ def get_arguments(): print('simulated_dirichlet_mixture experiment') if arguments.precomputed_parameter_filepath is None: print('learn simulated_dirichlet_mixture parameters') - dir_path = get_platform().create_checkpoint_directories([arguments.mle_param_dirname])[0] + dir_path = get_platform().create_checkpoint_directories( + [arguments.mle_param_dirname])[0] current_time = datetime.datetime.now() timestamp = current_time.strftime("%Y-%m-%d_%H-%M") save_dir = ( diff --git a/publications/mdm/mdm_paper/training/train_femnist.py b/publications/mdm/mdm_paper/training/train_femnist.py index dd6c90e..9b118b3 100644 --- a/publications/mdm/mdm_paper/training/train_femnist.py +++ b/publications/mdm/mdm_paper/training/train_femnist.py @@ -1,5 +1,5 @@ -import os import argparse +import os import joblib import numpy as np @@ -9,14 +9,16 @@ from pfl.internal.ops.selector import get_default_framework_module as get_ops from pfl.internal.ops.selector import set_framework_module from pfl.internal.platform.selector import get_platform - -from publications.mdm.mdm_utils.datasets import make_femnist_datasets -from publications.mdm.mdm_utils.utils import (add_experiment_args, add_mle_args, - add_init_algorithm_args, add_algorithm_args, - add_histogram_algorithm_args, - add_user_visualisation_args) - from publications.mdm.mdm_paper.training.mle import solve_polya_mixture_mle +from publications.mdm.mdm_utils.datasets import make_femnist_datasets +from publications.mdm.mdm_utils.utils import ( + add_algorithm_args, + add_experiment_args, + add_histogram_algorithm_args, + add_init_algorithm_args, + add_mle_args, + add_user_visualisation_args, +) def get_arguments(): @@ -56,7 +58,8 @@ def get_arguments(): print('simulated_dirichlet_mixture experiment') if arguments.precomputed_parameter_filepath is None: print('learn simulated_dirichlet_mixture parameters') - dir_path = get_platform().create_checkpoint_directories([arguments.mle_param_dirname])[0] + dir_path = get_platform().create_checkpoint_directories( + [arguments.mle_param_dirname])[0] save_dir = ( f'femnist_{arguments.dataset_type}_{arguments.num_mixture_components}_mixture' ) diff --git a/publications/mdm/mdm_paper/training/train_femnist_rebuttal.py b/publications/mdm/mdm_paper/training/train_femnist_rebuttal.py index 096c7ec..9848838 100644 --- a/publications/mdm/mdm_paper/training/train_femnist_rebuttal.py +++ b/publications/mdm/mdm_paper/training/train_femnist_rebuttal.py @@ -1,5 +1,5 @@ -import os import argparse +import os import joblib import numpy as np @@ -9,15 +9,17 @@ from pfl.internal.ops.selector import get_default_framework_module as get_ops from pfl.internal.ops.selector import set_framework_module from pfl.internal.platform.selector import get_platform - -from publications.mdm.mdm_utils.datasets import make_femnist_datasets -from publications.mdm.mdm_utils.utils import (add_experiment_args, add_mle_args, - add_init_algorithm_args, add_algorithm_args, - add_histogram_algorithm_args, - add_user_visualisation_args, - add_dataset_preprocessing_args) - from publications.mdm.mdm_paper.training.mle import solve_polya_mixture_mle +from publications.mdm.mdm_utils.datasets import make_femnist_datasets +from publications.mdm.mdm_utils.utils import ( + add_algorithm_args, + add_dataset_preprocessing_args, + add_experiment_args, + add_histogram_algorithm_args, + add_init_algorithm_args, + add_mle_args, + add_user_visualisation_args, +) def get_arguments(): @@ -63,7 +65,8 @@ def get_arguments(): print('simulated_dirichlet_mixture experiment') if arguments.precomputed_parameter_filepath is None: print('learn simulated_dirichlet_mixture parameters') - dir_path = get_platform().create_checkpoint_directories([arguments.mle_param_dirname])[0] + dir_path = get_platform().create_checkpoint_directories( + [arguments.mle_param_dirname])[0] save_dir = ( f'femnist_{arguments.dataset_type}_{arguments.num_mixture_components}_mixture_{arguments.filter_method}_filter_method' ) diff --git a/publications/mdm/mdm_utils/datasets/__init__.py b/publications/mdm/mdm_utils/datasets/__init__.py index e189449..533151f 100644 --- a/publications/mdm/mdm_utils/datasets/__init__.py +++ b/publications/mdm/mdm_utils/datasets/__init__.py @@ -1,3 +1,3 @@ -from .mixture_dataset import get_user_counts from .cifar10_dataset import make_cifar10_datasets from .femnist_dataset import make_femnist_datasets +from .mixture_dataset import get_user_counts diff --git a/publications/mdm/mdm_utils/datasets/cifar10_dataset.py b/publications/mdm/mdm_utils/datasets/cifar10_dataset.py index 3d06410..bd27c0e 100644 --- a/publications/mdm/mdm_utils/datasets/cifar10_dataset.py +++ b/publications/mdm/mdm_utils/datasets/cifar10_dataset.py @@ -1,19 +1,14 @@ -# -*- coding: utf-8 -*- - import os import pickle from typing import Callable, List, Optional, Tuple import numpy as np -from pfl.data import (ArtificialFederatedDataset, FederatedDataset, - FederatedDatasetBase) -from pfl.data.sampling import get_user_sampler, get_data_sampler +from pfl.data import ArtificialFederatedDataset, FederatedDataset, FederatedDatasetBase from pfl.data.dataset import Dataset +from pfl.data.sampling import get_data_sampler, get_user_sampler -from .mixture_dataset import (ArtificialFederatedDatasetMixture, - partition_by_dirichlet_mixture_class_distribution - ) +from .mixture_dataset import ArtificialFederatedDatasetMixture, partition_by_dirichlet_mixture_class_distribution from .sampler import DirichletDataSampler @@ -94,7 +89,7 @@ def make_federated_dataset( images = numpy_to_tensor(images) labels = numpy_to_tensor(labels) - data = dict() + data = {} for user_id in range(len(user_idxs)): data[user_id] = [ images[user_idxs[user_id]], labels[user_idxs[user_id]] diff --git a/publications/mdm/mdm_utils/datasets/femnist_dataset.py b/publications/mdm/mdm_utils/datasets/femnist_dataset.py index c921e4f..21880a8 100644 --- a/publications/mdm/mdm_utils/datasets/femnist_dataset.py +++ b/publications/mdm/mdm_utils/datasets/femnist_dataset.py @@ -1,27 +1,23 @@ -# -*- coding: utf-8 -*- - import os -from typing import Callable, Dict, Tuple, List, Optional +from typing import Callable, Dict, List, Optional, Tuple import h5py import numpy as np import torch from pfl.data import ArtificialFederatedDataset, FederatedDataset -from pfl.data.sampling import get_user_sampler, get_data_sampler from pfl.data.dataset import Dataset +from pfl.data.sampling import get_data_sampler, get_user_sampler -from .mixture_dataset import (ArtificialFederatedDatasetMixture, - partition_by_dirichlet_mixture_class_distribution - ) +from .mixture_dataset import ArtificialFederatedDatasetMixture, partition_by_dirichlet_mixture_class_distribution from .sampler import DirichletDataSampler def _sample_users(user_id_to_data: Dict[str, List[np.ndarray]], filter_method: Optional[str] = None, - sample_fraction: float = None, - start_idx: int = None, - end_idx: int = None, + sample_fraction: Optional[float] = None, + start_idx: Optional[int] = None, + end_idx: Optional[int] = None, include_sampled: bool = True): user_ids = list(user_id_to_data.keys()) @@ -156,7 +152,7 @@ def make_special_federated_dataset( #for k,v in indices_per_class.items(): # print('indices_per_class', k, len(v)) - new_user_id_to_data = dict() + new_user_id_to_data = {} start_id_per_class = {i: 0 for i in unique_labels} #print('start_id_per_class', start_id_per_class) for user_id, data in user_id_to_data.items(): @@ -218,10 +214,10 @@ def make_central_dataset( """ Create central dataset from a FEMNIST data file. """ - images = np.concatenate([data[0].cpu() for data in user_id_to_data.values()], - axis=0) - labels = np.concatenate([data[1].cpu() for data in user_id_to_data.values()], - axis=0) + images = np.concatenate( + [data[0].cpu() for data in user_id_to_data.values()], axis=0) + labels = np.concatenate( + [data[1].cpu() for data in user_id_to_data.values()], axis=0) return Dataset(raw_data=[images, labels]) @@ -235,9 +231,9 @@ def make_femnist_datasets( alphas=None, user_dataset_len_samplers=None, filter_method: Optional[str] = None, - sample_fraction: float = None, - start_idx: int = None, - end_idx: int = None, + sample_fraction: Optional[float] = None, + start_idx: Optional[int] = None, + end_idx: Optional[int] = None, include_sampled: bool = True ) -> Tuple[FederatedDataset, FederatedDataset, Dataset]: """ diff --git a/publications/mdm/mdm_utils/datasets/mixture_dataset.py b/publications/mdm/mdm_utils/datasets/mixture_dataset.py index 495d4b1..2de7789 100644 --- a/publications/mdm/mdm_utils/datasets/mixture_dataset.py +++ b/publications/mdm/mdm_utils/datasets/mixture_dataset.py @@ -1,12 +1,12 @@ from collections import defaultdict from typing import Callable, Iterable, List, Tuple -import numpy as np import joblib +import numpy as np from pfl.data import ArtificialFederatedDataset, FederatedDatasetBase from pfl.data.dataset import AbstractDataset -from pfl.internal.ops.selector import (get_default_framework_module as get_ops) +from pfl.internal.ops.selector import get_default_framework_module as get_ops class ArtificialFederatedDatasetMixture(FederatedDatasetBase): @@ -139,7 +139,7 @@ def get_user_counts(training_federated_dataset, num_classes, over a number of central iterations in train.py. """ print('get_user_counts') - all_counts = dict() + all_counts = {} for r in range(num_central_iterations): all_counts[r + 1] = [] l = list(training_federated_dataset.get_cohort(cohort_size)) diff --git a/publications/mdm/mdm_utils/datasets/sampler.py b/publications/mdm/mdm_utils/datasets/sampler.py index 070783b..c419d53 100644 --- a/publications/mdm/mdm_utils/datasets/sampler.py +++ b/publications/mdm/mdm_utils/datasets/sampler.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - import itertools import numpy as np diff --git a/publications/mdm/mdm_utils/models/argument_parsing.py b/publications/mdm/mdm_utils/models/argument_parsing.py index 3d70d70..3f109a8 100644 --- a/publications/mdm/mdm_utils/models/argument_parsing.py +++ b/publications/mdm/mdm_utils/models/argument_parsing.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - import argparse from typing import Optional, Tuple diff --git a/publications/mdm/mdm_utils/models/pytorch/__init__.py b/publications/mdm/mdm_utils/models/pytorch/__init__.py index 664abd6..ee4accf 100644 --- a/publications/mdm/mdm_utils/models/pytorch/__init__.py +++ b/publications/mdm/mdm_utils/models/pytorch/__init__.py @@ -1,6 +1,4 @@ -# -*- coding: utf-8 -*- - -from .cnn import simple_cnn, multi_label_cnn +from .cnn import multi_label_cnn, simple_cnn from .dnn import dnn, simple_dnn from .lstm import lm_lstm from .transformer import lm_transformer diff --git a/publications/mdm/mdm_utils/models/pytorch/cnn.py b/publications/mdm/mdm_utils/models/pytorch/cnn.py index ef85a40..f8d00ba 100644 --- a/publications/mdm/mdm_utils/models/pytorch/cnn.py +++ b/publications/mdm/mdm_utils/models/pytorch/cnn.py @@ -1,17 +1,16 @@ -# -*- coding: utf-8 -*- - import types -from typing import Tuple, List +from typing import List, Tuple import numpy as np import torch # type: ignore import torch.nn as nn import torch.nn.functional as F + from pfl.metrics import Weighted -from .layer import Transpose2D -from .metrics import image_classification_metrics, image_classification_loss from ..numpy.metrics import AveragedPrecision, MacroWeighted +from .layer import Transpose2D +from .metrics import image_classification_loss, image_classification_metrics def multi_label_cnn( @@ -41,9 +40,8 @@ def multi_label_cnn( import torchvision.models # type: ignore import torchvision.transforms as transforms # type: ignore - from .module_modification import (validate_no_batchnorm, - freeze_batchnorm_modules, - convert_batchnorm_modules) + + from .module_modification import convert_batchnorm_modules, freeze_batchnorm_modules, validate_no_batchnorm torchvision_models = torchvision.models.__dict__ @@ -218,7 +216,7 @@ def simple_cnn(input_shape: Tuple[int, ...], num_outputs: int) -> nn.Module: # Apply Glorot (Xavier) uniform initialization to match TF2 model. for m in model.modules(): - if isinstance(m, nn.Conv2d) or isinstance(m, nn.Linear): + if isinstance(m, (nn.Conv2d, nn.Linear)): torch.nn.init.xavier_uniform_(m.weight) model.loss = types.MethodType(image_classification_loss, model) diff --git a/publications/mdm/mdm_utils/models/pytorch/dnn.py b/publications/mdm/mdm_utils/models/pytorch/dnn.py index a07e152..b6ac8bf 100644 --- a/publications/mdm/mdm_utils/models/pytorch/dnn.py +++ b/publications/mdm/mdm_utils/models/pytorch/dnn.py @@ -1,13 +1,11 @@ -# -*- coding: utf-8 -*- - -from typing import Tuple import functools import types +from typing import Tuple -import torch.nn as nn import numpy as np +import torch.nn as nn -from .metrics import image_classification_metrics, image_classification_loss +from .metrics import image_classification_loss, image_classification_metrics def dnn(input_shape: Tuple[int, ...], hidden_dims: Tuple[int, ...], diff --git a/publications/mdm/mdm_utils/models/pytorch/layer.py b/publications/mdm/mdm_utils/models/pytorch/layer.py index b21d35d..9c62736 100644 --- a/publications/mdm/mdm_utils/models/pytorch/layer.py +++ b/publications/mdm/mdm_utils/models/pytorch/layer.py @@ -1,11 +1,10 @@ -# -*- coding: utf-8 -*- - from abc import ABC import torch import torch.nn as nn import torch.nn.functional as F from torch.nn.modules.batchnorm import _NormBase + from ..numpy.layer import positional_encoding @@ -22,10 +21,7 @@ def forward(self, input: torch.Tensor) -> torch.Tensor: # and use pretrained statistics in training as well self.training = False - if self.momentum is None: - exponential_average_factor = 0.0 - else: - exponential_average_factor = self.momentum + exponential_average_factor = 0.0 if self.momentum is None else self.momentum bn_training = (self.running_mean is None) and (self.running_var is None) @@ -48,24 +44,22 @@ class FrozenBatchNorm1D(_FrozenBatchNorm): def _check_input_dim(self, input): if input.dim() != 2 and input.dim() != 3: - raise ValueError('expected 2D or 3D input (got {}D input)'.format( - input.dim())) + raise ValueError( + f'expected 2D or 3D input (got {input.dim()}D input)') class FrozenBatchNorm2D(_FrozenBatchNorm): def _check_input_dim(self, input): if input.dim() != 4: - raise ValueError('expected 4D input (got {}D input)'.format( - input.dim())) + raise ValueError(f'expected 4D input (got {input.dim()}D input)') class FrozenBatchNorm3D(_FrozenBatchNorm): def _check_input_dim(self, input): if input.dim() != 5: - raise ValueError('expected 5D input (got {}D input)'.format( - input.dim())) + raise ValueError(f'expected 5D input (got {input.dim()}D input)') class Transpose2D(nn.Module): diff --git a/publications/mdm/mdm_utils/models/pytorch/metrics.py b/publications/mdm/mdm_utils/models/pytorch/metrics.py index 2f9f096..92c1523 100644 --- a/publications/mdm/mdm_utils/models/pytorch/metrics.py +++ b/publications/mdm/mdm_utils/models/pytorch/metrics.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - from typing import Dict import torch diff --git a/publications/mdm/mdm_utils/models/pytorch/module_modification.py b/publications/mdm/mdm_utils/models/pytorch/module_modification.py index 39d9047..345fe64 100644 --- a/publications/mdm/mdm_utils/models/pytorch/module_modification.py +++ b/publications/mdm/mdm_utils/models/pytorch/module_modification.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - from typing import Callable, Type from torch import nn diff --git a/publications/mdm/mdm_utils/models/pytorch_model.py b/publications/mdm/mdm_utils/models/pytorch_model.py index cadc368..5ab603e 100644 --- a/publications/mdm/mdm_utils/models/pytorch_model.py +++ b/publications/mdm/mdm_utils/models/pytorch_model.py @@ -1,5 +1,5 @@ import types -from typing import Tuple, Dict +from typing import Dict, Tuple import torch from torch import nn @@ -42,7 +42,7 @@ def simple_cnn(input_shape: Tuple[int, ...], num_outputs: int) -> nn.Module: # Apply Glorot (Xavier) uniform initialization to match TF2 model. for m in model.modules(): - if isinstance(m, nn.Conv2d) or isinstance(m, nn.Linear): + if isinstance(m, (nn.Conv2d, nn.Linear)): torch.nn.init.xavier_uniform_(m.weight) model.loss = types.MethodType(image_classification_loss, model) diff --git a/publications/mdm/mdm_utils/utils/__init__.py b/publications/mdm/mdm_utils/utils/__init__.py index b3fccc1..37bf735 100644 --- a/publications/mdm/mdm_utils/utils/__init__.py +++ b/publications/mdm/mdm_utils/utils/__init__.py @@ -1,5 +1,10 @@ -from .argument_parsing import (add_dataset_args, add_experiment_args, - add_init_algorithm_args, add_algorithm_args, - add_mle_args, add_histogram_algorithm_args, - add_user_visualisation_args, - add_dataset_preprocessing_args) +from .argument_parsing import ( + add_algorithm_args, + add_dataset_args, + add_dataset_preprocessing_args, + add_experiment_args, + add_histogram_algorithm_args, + add_init_algorithm_args, + add_mle_args, + add_user_visualisation_args, +) diff --git a/publications/mdm/mdm_utils/utils/argument_parsing.py b/publications/mdm/mdm_utils/utils/argument_parsing.py index 2650e66..e936c8b 100644 --- a/publications/mdm/mdm_utils/utils/argument_parsing.py +++ b/publications/mdm/mdm_utils/utils/argument_parsing.py @@ -7,12 +7,12 @@ def __init__(self, option_strings, dest, **kwargs): argparse.Action.__init__(self, option_strings, dest, **kwargs) def __call__(self, parser, namespace, values, option_string=None): - false_values = set(['false', 'no']) - true_values = set(['true', 'yes']) + false_values = {'false', 'no'} + true_values = {'true', 'yes'} values = values.lower() - if not values in (false_values | true_values): + if values not in (false_values | true_values): raise argparse.ArgumentError( self, 'Value must be either "true" or "false"') value = (values in true_values) @@ -24,7 +24,9 @@ def add_experiment_args(parser): parser.add_argument('--seed', type=int, default=0) parser.add_argument('--data_dir', type=str) parser.add_argument('--dirname', type=str) - parser.add_argument('--mle_param_dirname', type=str, default='publications/mdm/mle_params') + parser.add_argument('--mle_param_dirname', + type=str, + default='publications/mdm/mle_params') parser.add_argument( '--precomputed_parameter_filepath', type=str, @@ -61,17 +63,19 @@ def add_dataset_preprocessing_args(parser): def float_list(arg): try: float_values = [float(val) for val in arg.split()] - return float_values except ValueError: raise argparse.ArgumentTypeError("Invalid float values in the list") + else: + return float_values def int_list(arg): try: int_values = [int(val) for val in arg.split()] - return int_values except ValueError: raise argparse.ArgumentTypeError("Invalid int values in the list") + else: + return int_values def add_dataset_args(parser): diff --git a/publications/mdm/mdm_utils/utils/tools.py b/publications/mdm/mdm_utils/utils/tools.py index 6280ee1..44deab7 100644 --- a/publications/mdm/mdm_utils/utils/tools.py +++ b/publications/mdm/mdm_utils/utils/tools.py @@ -3,7 +3,6 @@ from pfl.callback import TrainingProcessCallback from pfl.internal.ops.selector import get_default_framework_module as get_ops - from pfl.metrics import Metrics from pfl.model.base import StatefulModel diff --git a/publications/mdm/mdm_utils/utils/visualize_results.py b/publications/mdm/mdm_utils/utils/visualize_results.py index 281f39d..67ddc80 100644 --- a/publications/mdm/mdm_utils/utils/visualize_results.py +++ b/publications/mdm/mdm_utils/utils/visualize_results.py @@ -13,7 +13,7 @@ def plot_cifar10_results(): df = pd.read_csv(filename) experiments = np.unique(df['experiment'].values).tolist() - dfs = dict() + dfs = {} for experiment in experiments: dfs[experiment] = (df.loc[df['experiment'] == experiment]) @@ -21,13 +21,13 @@ def plot_cifar10_results(): 'cohort_size', 'local_batch_size', 'local_learning_rate', 'local_num_epochs' ] - unique_vals = dict() + unique_vals = {} for column_name in column_names: unique_vals[column_name] = np.unique(dfs['live'][column_name]).tolist() - accs = dict() + accs = {} for name, df in dfs.items(): - accs[name] = dict() + accs[name] = {} for tup in product(*unique_vals.values()): filter_dic = dict(zip(column_names, tup)) a = df.loc[(df[list(filter_dic)] == pd.Series(filter_dic)).all( @@ -38,7 +38,7 @@ def plot_cifar10_results(): permutation = np.argsort(-x) mask = np.array(list(accs['live'].values()))[permutation] >= 0.6 - dic = dict() + dic = {} c = dict(zip(accs.keys(), ['blue', 'red', 'green'])) plt.rcParams.update({'font.size': 13})